Regarding the Week05 course material. It is recommended in the lecture on NFT minting policy that rather than rely on a deadline and constraint of 1 token per mint, that a unique input such as a UTxO be used, along with said 1 token constraint.

I was wondering, could an alternate unique input be a base64 (or other encoding scheme) of the actual NFT asset? Further, assuming this encoded string has been checked that it fits in the block size, could it be stored as datum somehow? (Though if I recall minting policies do not output datum, somebody please correct me if I am wrong.)

3 Answers 3


By input, I assume you mean TokenName or CurrencySymbol.

CurrencySymbol is the hash of your script, so you cannot act on it. Having a particular TokenName does not solve the problem because the rules of the minting policy (whether it returns True or False given a context and a redeemer) determine if the token can be minted.

You can write:

mkPolicy :: TokenName -> () -> ScriptContext -> Bool
mkPolicy tn () ctx = traceIfFalse "wrong amount minted" checkMintedAmount
    checkMintedAmount :: Bool
    checkMintedAmount = case flattenValue (txInfoMint . scriptContextInfo $ ctx) of
        [(_, tn', amt)] -> tn' == tn && amt == 1
        _               -> False

Deploying the contract with parameter 0x849720EF472980, if two people try to mint an amount of 1 (PutScriptHashHere, 0x849720EF472980), they will both succeed.

Putting deadlines will not solve the problem as the two can still both mint before the deadline.

The presence of a datum could solve the problem as you could have an Int which is incremented till it is one (or a Boolean).

  1. As you mention it, there is none (although I did not understand exactly why there could not be).
  2. If two minting transactions get to nodes at the same timeslot, both should succeed.

Creating an NFT using an tx hash (unspent) is exactly what the state machine thread token does. You can see how by looking at the plutus source code for state machine below. You can then use a forward minting policy hash and store it in the datum so each time a token is minted, the minting policy can ensures that no identical tokens are minted.

let mph = Scripts.forwardingMintingPolicyHash typedValidator

-- | Create a thread token. The thread token contains a reference to an unspent output of the wallet,
-- so it needs to used with 'mkStateMachine' immediately, and the machine must be initialised,
-- to prevent the output from getting spent in the mean time.
getThreadToken :: AsSMContractError e => Contract w schema e ThreadToken
getThreadToken = mapError (review _SMContractError) $ do
    txOutRef <- getUnspentOutput
    pure $ ThreadToken txOutRef (scriptCurrencySymbol (curPolicy txOutRef))



This isn't an answer, because I was wondering as well how to do the following, which may or may not be the same thing as you're asking how to do:

How do you prevent the same item (hash of a digitized item) from being tokenized into an NFT more than once when the script doesn't have access to the blockchain history?

Maybe it's possible to use the Statemachine feature to maintain a map of NFTs to item hashes, so it could track all the item hashes that have been minted with this policy?

I guess someone else could possibly make trivial changes to the policy's code just to change the script address, and then could mint a duplicate NFT of the same asset, but a statemachine could at least track assets for this one particular script.

This is all assuming a minting policy script can work with a statemachine, or a Datum.

Edit: I noticed in this set of instructions for minting NFTs using the cardano-cli that metadata can be attached to the NFT. https://developers.cardano.org/docs/native-tokens/minting-nfts/ Meaning that it might be possible to add a datum value to the minted token somehow. In order to check for duplicates across the whole BC, it might be necessary to use a third party NFT registry app.

Edit 2: One thing that shows up in a later Plutus Pioneer lecture is using an NFT to verify that the correct oracles are being referenced. I think it's in the Uniswap code. The Uniswap operator mints an NFT as a kind of id, and the SC that runs the swap pools uses that NFT to make sure that only the operator can control the Dapp. Using that idea, your contract could do something similar, making sure that no one else is running the same contract to make duplicates. This combined with some form of mapping to make sure no one duplicates the same asset on your contract, and registering with an NFT registry, might be a fairly solid way to ensure uniqueness of the assets being tokenized.

I could of course be missing something, I'm fairly new to this too.

Your Answer

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

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