I tried to create a few modification on the NFT minting contract from week 5 of the plutus pioneer program. I wanted to be able to mint a few tokens at once. My policy should require that the token names start with "ABC" + Integer where the integer is less than 100.
Here is my attempt:
{-# INLINABLE mkPolicy #-}
mkPolicy :: TxOutRef -> () -> ScriptContext -> Bool
mkPolicy oref () ctx = traceIfFalse "UTxO not consumed" hasUTxO &&
traceIfFalse "wrong amount minted" checkMintedAmount
where
info :: TxInfo
info = scriptContextTxInfo ctx
hasUTxO :: Bool
hasUTxO = any (\i -> txInInfoOutRef i == oref) $ txInfoInputs info
flattenVal :: [(CurrencySymbol, TokenName, Integer)]
flattenVal = flattenValue (txInfoMint info)
-- Check that TokenName is of the form ABC1 .. ABC99
checkTokenName :: TokenName -> Bool
checkTokenName tn = isPrefixOf "ABC" (show tn) &&
isJust (readMaybe (post tn) :: Maybe Integer) &&
(read (post tn) :: Integer) < 100
where
post tn' = drop 3 $ show tn'
checkMintedAmount :: Bool
checkMintedAmount = all (\(_, tn', amt') -> checkTokenName tn' && amt' == 1) flattenVal
Unfortunately this gives a horrible run time error which would be too long to paste here, so I'll just paste the first few lines:
GHC Core to PLC plugin: E042:Error: Unsupported feature: Int: use Integer instead
Context: Compiling type: GHC.Types.Int
Context: Compiling type: GHC.Types.Int -> a -> GHC.Show.ShowS
Context: Compiling data constructor type: GHC.Show.C:Show
Context: Compiling type: GHC.Show.Show a
Context: Compiling expr: \ ($dShow_a14Ch [Occ=Once*] :: GHC.Show.Show a)
(tn' [Occ=Once*] :: a) ->
let {
n :: GHC.Types.Int
[LclId,
Unf=Unf{Src=<vanilla>, TopLvl=False, Value=True, ConLike=True,
WorkFree=True, Expandable=True, Guidance=IF_ARGS [] 10 20}]
n = GHC.Types.I# 3# } in
letrec {
unsafeDrop [Occ=LoopBreaker]
:: forall a1. GHC.Types.Int -> [a1] -> [a1]
[LclId,
Arity=2,
Unf=Unf{Src=<vanilla>, TopLvl=False, Value=True, ConLike=True,
WorkFree=True, Expandable=True, Guidance=IF_ARGS [20 30] 91 10}]
unsafeDrop
= \ (@ a1)
(ds [Occ=Once!] :: GHC.Types.Int)
(ds1 [Occ=Once!] :: [a1]) ->
case ds of { GHC.Types.I# ipv ->
case ds1 of {
[] -> GHC.Types.[] @ a1;
: _ [Occ=Dead] ipv2 [Occ=Once*] ->
case ipv of {
__DEFAULT ->
unsafeDrop @ a1 (GHC.Types.I# (GHC.Prim.-# ipv 1#)) ipv2;
1# -> ipv2
}
}
}; } in
case GHC.Classes.leInt n (GHC.Types.I# 0#) of {
GHC.Types.False ->
unsafeDrop @ GHC.Types.Char n (GHC.Show.show @ a $dShow_a14Ch tn');
GHC.Types.True -> GHC.Show.show @ a $dShow_a14Ch tn'
}
I saw similar discussion on discord about trying to compare the token name to an empty string. Is this somehow related? I though the above would work because I'm explicitly doing show on the BuiltinByteString
Any idea what I'm doing wrong?