forked from cardano-foundation/CIPs
-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathonchain.hs
109 lines (85 loc) · 4.34 KB
/
onchain.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
-- PlutusTx on-chain code (PlutusV2)
-- NOTE: The asset name labels are not finalized yet. This is only a proof of concept
type Metadata = Map BuiltinData BuiltinData
data DatumMetadata = DatumMetadata {
metadata :: Metadata
, version :: Integer
}
data Action = Mint | Burn
PlutusTx.makeLift ''Action
PlutusTx.makeIsDataIndexed ''Action [('Mint, 0), ('Burn, 1)]
txOutRef :: TxOutRef
txOutRef = TxOutRef "568ea530dfe90b2a0890b340eac46b3c58ce298eb67cee047e2463ea105f4cdd" 0 -- Example out ref (required to mint NFT)
-- | Minting policy (mints user token and reference NFT as pair). It is a one-shot policy.
-- Minting policy depends on reference validator
{-# INLINEABLE mintValidatorControl #-}
mintingPolicy :: Address -> TxOutRef -> Action -> ScriptContext -> Bool
mintingPolicy refAddress oref action ctx = case action of
Mint -> checkMint
Burn -> checkBurn
where
txInfo :: TxInfo
txInfo = scriptContextTxInfo ctx
txMint :: Value
txMint = txInfoMint txInfo
ownSymbol :: CurrencySymbol
ownSymbol = ownCurrencySymbol ctx
prefixLength :: Integer
prefixLength = 5
checkMint :: Bool
checkMint =
let
[(_, refOutValue)] = scriptOutputsAtAddress refAddress txInfo
[(refOutCs, TokenName refOutName,refOutAm)] = flattenValue (noAdaValue refOutValue)
-- | Mint value (reference NFT and user token).
[(userCs, TokenName userName, userAm), (refCs, TokenName refName, refAm)] = flattenValue txMint
in
-- | One shot policy
spendsOutput txInfo (txOutRefId oref) (txOutRefIdx oref) &&
-- | Check if minted reference NFT is sent to reference address
noAdaValue refOutValue == V.singleton refCs (TokenName refName) refAm &&
-- | Check quantity and policy ids
userAm == 1 && refAm == 1 && userCs == ownSymbol && refCs == ownSymbol &&
-- | Check naming
takeByteString prefixLength userName == "(222)" && takeByteString prefixLength refName == "(100)" &&
dropByteString prefixLength userName == dropByteString prefixLength refName
checkBurn :: Bool
checkBurn = all (\(_,_,am) -> am < 0) (flattenValue txMint)
-- | Reference validator (holds the reference NFT with metadata)
{-# INLINEABLE refValidator #-}
refValidator :: DatumMetadata -> () -> ScriptContext -> Bool
refValidator datumMetadata () ctx = checkBurn
where
txInfo :: TxInfo
txInfo = scriptContextTxInfo ctx
txMint :: Value
txMint = txInfoMint txInfo
ownValue :: Value
ownValue = let Just i = findOwnInput ctx
out = txInInfoResolved i
in txOutValue out
prefixLength :: Integer
prefixLength = 5
providesUserToken :: CurrencySymbol -> TokenName -> Integer -> Bool
providesUserToken cs tn am = any (\(TxInInfo _ out) -> valueOf (txOutValue out) cs tn == am) (txInfoInputs txInfo)
checkBurn :: Bool
checkBurn =
let
-- | Allow burning only one pair (reference NFT and user token) at once.
[(userCs, TokenName userName, userAm), (refCs, TokenName refName, refAm)] = flattenValue txMint
[(ownCs, TokenName ownName, _)] = flattenValue (noAdaValue ownValue)
in
-- | Matching policy ids and quantities.
-1 == userAm && -1 == refAm &&
ownCs == userCs && ownCs == refCs &&
-- | Matching asset names.
takeByteString prefixLength userName == "(222)" && takeByteString prefixLength refName == "(100)" &&
dropByteString prefixLength userName == dropByteString prefixLength refName &&
-- | Burned reference NFT needs to match the one in the own script UTxO
ownName == refName
{-# INLINEABLE scriptOutputsAtAddress #-}
scriptOutputsAtAddress :: Address -> TxInfo -> [(OutputDatum, Value)]
scriptOutputsAtAddress address p =
let flt TxOut{txOutDatum=d, txOutAddress=address', txOutValue} | address == address' = Just (d, txOutValue)
flt _ = Nothing
in mapMaybe flt (txInfoOutputs p)