Table of Contents
-
- 7.1 Mocking
ScriptContext - 7.2 Example Test Case
- 7.3 Running Tests
- 7.1 Mocking
This tutorial guides Haskell beginners through creating and testing a Plutus Auction Minting Policy. You’ll learn how to:
- Define on-chain parameters and redeemer types
- Implement
auctionTypedMintingPolicylogic - Compile the policy to Plutus Core
- Write unit and property-based tests
- Haskell basics (records, pattern matching)
- GHC and Cabal installed
- Plutus libraries available (via Nix or direct Cabal setup)
-
Change to project root:
cd ~/projects/auction
-
Launch REPL:
cabal repl
-
Load the minting module:
λ> :l src/AuctionMintingPolicy.hs [1 of 1] Compiling AuctionMintingPolicy ( src/AuctionMintingPolicy.hs, interpreted ) Ok, one module loaded.
-
Inspect the main function:
λ> :t auctionTypedMintingPolicy auctionTypedMintingPolicy :: PubKeyHash -> () -> ScriptContext -> Bool
-- The parameter is simply the seller's PubKeyHash
type AuctionMintingParams = PubKeyHashtype AuctionMintingRedeemer = ()- A unit type, since no extra data is needed to authorize minting.
Open src/AuctionMintingPolicy.hs and locate:
{-# INLINEABLE auctionTypedMintingPolicy #-}
auctionTypedMintingPolicy :: AuctionMintingParams -> AuctionMintingRedeemer -> ScriptContext -> Bool
auctionTypedMintingPolicy pkh _ ctx =
txSignedBy txInfo pkh PlutusTx.&& mintedExactlyOneToken
where
txInfo = scriptContextTxInfo ctx
mintedExactlyOneToken = case flattenValue (txInfoMint txInfo) of
[(cs, _tn, q)] ->
cs PlutusTx.== ownCurrencySymbol ctx PlutusTx.&& q PlutusTx.== 1
_ -> FalseStep-by-step:
txSignedBy: ensures the seller’s signature is present.flattenValue: converts mintedValueto a list of triples.- Pattern match: exactly one
(currencySymbol, tokenName, quantity). ownCurrencySymbol: checks policy’s own symbol matches.- Quantity check: must be exactly
1.
Below the typed logic you’ll find:
auctionMintingPolicyScript :: AuctionMintingParams -> CompiledCode (BuiltinData -> BuiltinData -> PlutusTx.BuiltinUnit)
auctionMintingPolicyScript pkh =
$$(PlutusTx.compile [|| auctionUntypedMintingPolicy ||])
`PlutusTx.unsafeApplyCode` PlutusTx.liftCode plcVersion100 pkh-
In REPL:
λ> :browse auctionMintingPolicyScript
Create test/AuctionMintingPolicySpec.hs:
import qualified PlutusTx.AssocMap as AssocMap
import PlutusLedgerApi.V2.Contexts ( ScriptContext(..), TxInfo(..), TxOutRef(..), TxId(..) )
mockMintingContext :: ScriptContext
mockMintingContext = ScriptContext
{ scriptContextTxInfo = TxInfo
{ txInfoInputs = []
, txInfoReferenceInputs = []
, txInfoOutputs = []
, txInfoFee = mempty
, txInfoMint = singleton cs tn 1
, txInfoDCert = []
, txInfoWdrl = AssocMap.empty
, txInfoValidRange = mempty
, txInfoSignatories = []
, txInfoData = AssocMap.empty
, txInfoId = TxId ""
, txInfoRedeemers = AssocMap.empty
}
, scriptContextPurpose = Minting (TxOutRef (TxId "") 0)
}
where
cs = ownCurrencySymbol mockMintingContext
tn = "TOK"import Test.Hspec
import PlutusLedgerApi.V1.Crypto (PubKeyHash(..))
main :: IO ()
main = hspec $
describe "auctionTypedMintingPolicy" $ do
it "allows exactly one token minting by seller" $ do
let pkh = PubKeyHash "seller"
auctionTypedMintingPolicy pkh () mockMintingContext `shouldBe` Truecabal test minting-testsExample in test/AuctionMintingPolicyProperties.hs:
import Test.QuickCheck
prop_onlyOne :: PubKeyHash -> Property
prop_onlyOne pkh =
let ctx = mockMintingContext
in auctionTypedMintingPolicy pkh () ctx === True
main = quickCheck prop_onlyOneRun:
cabal test minting-properties- Extend to allow controlled multiple minting with limits.
- Deploy policy on a testnet and test minting transactions.
- Integrate off-chain code to submit minting transactions.
| Term | Definition |
|---|---|
txSignedBy |
Checks a transaction is signed by a given PubKeyHash. |
flattenValue |
Converts a Value into a list of (CurrencySymbol, TokenName, Integer). |
ownCurrencySymbol |
Retrieves the currency symbol for the currently running minting policy. |
Minting |
A ScriptPurpose constructor indicating a mint operation on a UTXO. |
CompiledCode |
Wrapper for PlutusTx-compiled on-chain code. |
Hspec |
Haskell testing framework for behavior-driven development. |
QuickCheck |
Property-based testing library in Haskell. |