I'm currently going through week 5 of the plutus piooner lectures, and I have some questions about the NFT process. Here is a reference with the complete code, but here are the important parts:

The on-chain part makes sense to me. We want our NFT to be unique, so we take as input a UTxO (always is unique) and check that we're minting only one token:

mkPolicy :: TxOutRef -> TokenName -> ScriptContext -> Bool
mkPolicy oref tn ctx = traceIfFalse "UTxO not consumed"   hasUTxO           &&
                       traceIfFalse "wrong amount minted" checkMintedAmount

The off-chain part is what brings me some confusion, so let's lay down what we want to achieve:

We need to build a transaction that spends a specified UTxO and mints only one token.

The most relevant part of the off-chain code is this:

let val     = Value.singleton (curSymbol oref tn) tn 1
    lookups = Constraints.monetaryPolicy (policy oref tn) <> Constraints.unspentOutputs utxos
    tx      = Constraints.mustForgeValue val <> Constraints.mustSpendPubKeyOutput oref
  1. I understand that mustSpendPubKeyOutput makes sure that the transaction to be built contains the necessary UTxO (oref) so that the on-chain policy passes. What happens behind the scenes? If the constraint is not specified Plutus will just use it's own logic to grab the UTxO used for building this transaction? If the constraint is not specified, is there still a chance that the right UTxO will be used?

  2. What we need is to build a transaction that spends the required UTxO. One way of doing this is what we done before by specifying a constraint. But what if we only pass one UTxO to the lookup? Then transaction will be forced to be built with that UTxO right? There are no other options to be picked. Well, I tried that and it fails, this very clearly proves my understanding is wrong, why?

  3. So far in the course we never had to pass UTxOs on the lookups and Plutus was able to find them automatically. Why it's only in this specific scenario that we need?

1 Answer 1

  1. Actually in this code Value.singleton (curSymbol oref tn) tn 1 you are only specifying the Value to be minted. To be more precise: curSymbol oref tn is the currency symbol of your NFT to be minted with two parameters: oref and tn. For example, you can create a minting policy without any params (Free.hs in lesson 05) and mint using Value.singleton curSymbol tn 1. That's not related to Constraints.mustSpendPubKeyOutput.
  2. Because if you remove mustSpendPubKeyOutput that means, you will not spend any UTxO and if you check the onchain code, there is a validation ensuring the use of the UTxO.
  3. Purpose to use a UTxO to create an NFT, it's because an NFT should be unique. To ensure that, we have to specify something unique in the currency symbol and all UTxO are uniques, if you spend a UTxO, you can never use it again. It's the best way to identify our NFT.

Here some concepts to be clear on how this works:

  • tx: specifies the transaction to be built. In one transaction many things can be achieved at same time: mint values, pay to pubkeys, spend UTxO's (from PubKeys or scripts).
  • lookups: in order to successfully validate a transaction (from onchain code), there should be a "guide" to specify where those UTxO are. We do that, using lookups.

So, we say to our onchain code: validate this transaction (tx) using these UTxOs (lookups).

submitTxConstraintsWith @Void lookups tx
  • Your answer almost answers what I was trying to ask. I realized the question was not laid out very well, I edited my question to make it clearer and easier to follow, could you take a new look?
    – lgvaz
    Oct 11, 2021 at 21:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.