Writing basic minting policies
Minting policy scripts are the programs that can be used to control the minting of new assets on the chain. Minting policy scripts are much like validator scripts, and they are written similarly, so check out the basic validators tutorial before reading this one.
Minting policy arguments
Minting policies, like validators, receive some information from the validating node:
The redeemer, which is some script-specific data specified by the party performing the minting.
The script context, which contains a representation of the spending transaction, as well as the hash of the minting policy which is currently being run.
The minting policy is a function which receives these two inputs as arguments.
The validating node is responsible for passing them in and running the minting policy.
As with validator scripts, the arguments are passed encoded as
Using the script context
Minting policies have access to the script context as their second argument.
This will always be a value of type :hsobj:
PlutusLedgerApi.V1.Contexts.ScriptContext encoded as
Minting policies tend to be particularly interested in the
mint field, since the point of a minting policy is to control which tokens are minted.
It is also important for a minting policy to look at the tokens in the
mint field that are part of its own asset group.
This requires the policy to refer to its own hash – fortunately this is provided for us in the script context of a minting policy.
Writing minting policies
Here is an example that puts this together to make a simple policy that allows anyone to mint the token so long as they do it one token at a time. To begin with, we’ll write a version that works with structured types.
oneAtATimePolicy :: () -> ScriptContext -> Bool oneAtATimePolicy _ ctx = -- 'ownCurrencySymbol' lets us get our own hash (= currency symbol) -- from the context let ownSymbol = ownCurrencySymbol ctx txinfo = scriptContextTxInfo ctx minted = txInfoMint txinfo -- Here we're looking at some specific token name, which we -- will assume we've got from elsewhere for now. in valueOf minted ownSymbol tname == 1
However, scripts are actually given their arguments as type
Data, and must signal failure with
error, so we need to wrap up our typed version to use it on-chain.
-- The 'plutus-ledger' package from 'plutus-apps' provides helper functions to automate -- some of this boilerplate. oneAtATimePolicyUntyped :: BuiltinData -> BuiltinData -> () -- 'check' fails with 'error' if the argument is not 'True'. oneAtATimePolicyUntyped r c = check $ oneAtATimePolicy (unsafeFromBuiltinData r) (unsafeFromBuiltinData c) -- We can use 'compile' to turn a minting policy into a compiled Plutus Core program, -- just as for validator scripts. oneAtATimeCompiled :: CompiledCode (BuiltinData -> BuiltinData -> ()) oneAtATimeCompiled = $$(compile [|| oneAtATimePolicyUntyped ||])
Other policy examples
Probably the simplest useful policy is one that requires a specific key to have signed the transaction in order to do any minting. This gives the key holder total control over the supply, but this is often sufficient for asset types where there is a centralized authority.
singleSignerPolicy :: () -> ScriptContext -> Bool singleSignerPolicy _ ctx = txSignedBy (scriptContextTxInfo ctx) key
We don’t need to check that this transaction actually mints any of our asset type: the ledger rules ensure that the minting policy will only be run if some of that asset is being minted.