check that all GATs burned in treasury validator are valid
This commit is contained in:
parent
909416df5a
commit
92b3375f5e
3 changed files with 75 additions and 8 deletions
|
|
@ -32,7 +32,7 @@ import Prelude
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
import Agora.Utils (passert, passetClassValueOf, passetClassValueOf', plookup)
|
import Agora.Utils (allOutputs, passert, passetClassValueOf, passetClassValueOf', plookup)
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
@ -113,5 +113,13 @@ authorityTokenPolicy params =
|
||||||
let mintedATs = passetClassValueOf # ownSymbol # pconstant "" # mintedValue
|
let mintedATs = passetClassValueOf # ownSymbol # pconstant "" # mintedValue
|
||||||
pif
|
pif
|
||||||
(0 #< mintedATs)
|
(0 #< mintedATs)
|
||||||
(passert "Authority token did not move in minting GATs" tokenMoved (pconstant ()))
|
( P.do
|
||||||
|
passert "Parent token did not move in minting GATs" tokenMoved
|
||||||
|
passert "All outputs only emit valid GATs" $
|
||||||
|
allOutputs @PUnit # pfromData ctx.txInfo #$ plam $ \txOut _value _address _datum ->
|
||||||
|
authorityTokensValidIn
|
||||||
|
# ownSymbol
|
||||||
|
# txOut
|
||||||
|
pconstant ()
|
||||||
|
)
|
||||||
(pconstant ())
|
(pconstant ())
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,6 @@ treasury.
|
||||||
-}
|
-}
|
||||||
module Agora.Treasury (module Agora.Treasury) where
|
module Agora.Treasury (module Agora.Treasury) where
|
||||||
|
|
||||||
import Agora.Utils (passert, passetClassValueOf)
|
|
||||||
import GHC.Generics qualified as GHC
|
import GHC.Generics qualified as GHC
|
||||||
import Generics.SOP
|
import Generics.SOP
|
||||||
import Plutarch.Api.V1.Contexts (PScriptContext, PScriptPurpose (PMinting))
|
import Plutarch.Api.V1.Contexts (PScriptContext, PScriptPurpose (PMinting))
|
||||||
|
|
@ -18,7 +17,12 @@ import Plutarch.DataRepr (
|
||||||
PIsDataReprInstances (PIsDataReprInstances),
|
PIsDataReprInstances (PIsDataReprInstances),
|
||||||
)
|
)
|
||||||
import Plutarch.Monadic qualified as P
|
import Plutarch.Monadic qualified as P
|
||||||
import Plutus.V1.Ledger.Value (CurrencySymbol, TokenName)
|
import Plutus.V1.Ledger.Value (CurrencySymbol)
|
||||||
|
|
||||||
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
import Agora.AuthorityToken (authorityTokensValidIn)
|
||||||
|
import Agora.Utils (allInputs, passert, psymbolValueOf)
|
||||||
|
|
||||||
{- | Validator ensuring that transactions consuming the treasury
|
{- | Validator ensuring that transactions consuming the treasury
|
||||||
do so in a valid manner.
|
do so in a valid manner.
|
||||||
|
|
@ -26,7 +30,6 @@ import Plutus.V1.Ledger.Value (CurrencySymbol, TokenName)
|
||||||
treasuryV ::
|
treasuryV ::
|
||||||
forall {s :: S}.
|
forall {s :: S}.
|
||||||
CurrencySymbol ->
|
CurrencySymbol ->
|
||||||
TokenName ->
|
|
||||||
Term
|
Term
|
||||||
s
|
s
|
||||||
( PAsData PTreasuryDatum
|
( PAsData PTreasuryDatum
|
||||||
|
|
@ -34,7 +37,7 @@ treasuryV ::
|
||||||
:--> PAsData PScriptContext
|
:--> PAsData PScriptContext
|
||||||
:--> PUnit
|
:--> PUnit
|
||||||
)
|
)
|
||||||
treasuryV cs tn = plam $ \_d r ctx' -> P.do
|
treasuryV cs = plam $ \_d r ctx' -> P.do
|
||||||
-- plet required fields from script context.
|
-- plet required fields from script context.
|
||||||
ctx <- pletFields @["txInfo", "purpose"] ctx'
|
ctx <- pletFields @["txInfo", "purpose"] ctx'
|
||||||
|
|
||||||
|
|
@ -50,10 +53,16 @@ treasuryV cs tn = plam $ \_d r ctx' -> P.do
|
||||||
let mint :: Term s PValue
|
let mint :: Term s PValue
|
||||||
mint = txInfo.mint
|
mint = txInfo.mint
|
||||||
gatAmountMinted :: Term s PInteger
|
gatAmountMinted :: Term s PInteger
|
||||||
gatAmountMinted = passetClassValueOf # pconstant cs # pconstant tn # mint
|
gatAmountMinted = psymbolValueOf # pconstant cs # mint
|
||||||
|
|
||||||
passert "GAT not burned." $ gatAmountMinted #== -1
|
passert "GAT not burned." $ gatAmountMinted #== -1
|
||||||
|
|
||||||
|
passert "All inputs only have valid GATs" $
|
||||||
|
allInputs @PUnit # pfromData ctx.txInfo #$ plam $ \txOut _value _address _datum ->
|
||||||
|
authorityTokensValidIn
|
||||||
|
# pconstant cs
|
||||||
|
# txOut
|
||||||
|
|
||||||
pconstant ()
|
pconstant ()
|
||||||
|
|
||||||
{- | Plutarch level type representing datum of the treasury.
|
{- | Plutarch level type representing datum of the treasury.
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,9 @@ module Agora.Utils (
|
||||||
|
|
||||||
-- * Functions which should (probably) not be upstreamed
|
-- * Functions which should (probably) not be upstreamed
|
||||||
anyOutput,
|
anyOutput,
|
||||||
|
allOutputs,
|
||||||
anyInput,
|
anyInput,
|
||||||
|
allInputs,
|
||||||
) where
|
) where
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
@ -256,7 +258,9 @@ pfindTxInByTxOutRef = phoistAcyclic $
|
||||||
#$ (pfield @"inputs" # txInfo)
|
#$ (pfield @"inputs" # txInfo)
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
-- Functions which should (probably) not be upstreamed
|
{- Functions which should (probably) not be upstreamed
|
||||||
|
All of these functions are quite inefficient.
|
||||||
|
-}
|
||||||
|
|
||||||
-- | Check if any output matches the predicate.
|
-- | Check if any output matches the predicate.
|
||||||
anyOutput ::
|
anyOutput ::
|
||||||
|
|
@ -280,6 +284,28 @@ anyOutput = phoistAcyclic $
|
||||||
)
|
)
|
||||||
# pfromData txInfo.outputs
|
# pfromData txInfo.outputs
|
||||||
|
|
||||||
|
-- | Check if all outputs match the predicate.
|
||||||
|
allOutputs ::
|
||||||
|
forall (datum :: PType) s.
|
||||||
|
( PIsData datum
|
||||||
|
) =>
|
||||||
|
Term s (PTxInfo :--> (PTxOut :--> PValue :--> PAddress :--> datum :--> PBool) :--> PBool)
|
||||||
|
allOutputs = phoistAcyclic $
|
||||||
|
plam $ \txInfo' predicate -> P.do
|
||||||
|
txInfo <- pletFields @'["outputs"] txInfo'
|
||||||
|
pall
|
||||||
|
# plam
|
||||||
|
( \txOut'' -> P.do
|
||||||
|
PTxOut txOut' <- pmatch (pfromData txOut'')
|
||||||
|
txOut <- pletFields @'["value", "datumHash", "address"] txOut'
|
||||||
|
PDJust dh <- pmatch txOut.datumHash
|
||||||
|
pmatch (pfindDatum' @datum # (pfield @"_0" # dh) # txInfo') $ \case
|
||||||
|
PJust datum -> P.do
|
||||||
|
predicate # (pfromData txOut'') # txOut.value # txOut.address # pfromData datum
|
||||||
|
PNothing -> pcon PFalse
|
||||||
|
)
|
||||||
|
# pfromData txInfo.outputs
|
||||||
|
|
||||||
-- | Check if any (resolved) input matches the predicate.
|
-- | Check if any (resolved) input matches the predicate.
|
||||||
anyInput ::
|
anyInput ::
|
||||||
forall (datum :: PType) s.
|
forall (datum :: PType) s.
|
||||||
|
|
@ -304,6 +330,30 @@ anyInput = phoistAcyclic $
|
||||||
)
|
)
|
||||||
# pfromData txInfo.inputs
|
# pfromData txInfo.inputs
|
||||||
|
|
||||||
|
-- | Check if all (resolved) inputs match the predicate.
|
||||||
|
allInputs ::
|
||||||
|
forall (datum :: PType) s.
|
||||||
|
( PIsData datum
|
||||||
|
) =>
|
||||||
|
Term s (PTxInfo :--> (PTxOut :--> PValue :--> PAddress :--> datum :--> PBool) :--> PBool)
|
||||||
|
allInputs = phoistAcyclic $
|
||||||
|
plam $ \txInfo' predicate -> P.do
|
||||||
|
txInfo <- pletFields @'["inputs"] txInfo'
|
||||||
|
pall
|
||||||
|
# plam
|
||||||
|
( \txInInfo'' -> P.do
|
||||||
|
PTxInInfo txInInfo' <- pmatch (pfromData txInInfo'')
|
||||||
|
let txOut'' = pfield @"resolved" # txInInfo'
|
||||||
|
PTxOut txOut' <- pmatch (pfromData txOut'')
|
||||||
|
txOut <- pletFields @'["value", "datumHash", "address"] txOut'
|
||||||
|
PDJust dh <- pmatch txOut.datumHash
|
||||||
|
pmatch (pfindDatum' @datum # (pfield @"_0" # dh) # txInfo') $ \case
|
||||||
|
PJust datum -> P.do
|
||||||
|
predicate # pfromData txOut'' # txOut.value # txOut.address # pfromData datum
|
||||||
|
PNothing -> pcon PFalse
|
||||||
|
)
|
||||||
|
# pfromData txInfo.inputs
|
||||||
|
|
||||||
-- | Create a value with a single asset class.
|
-- | Create a value with a single asset class.
|
||||||
psingletonValue :: forall s. Term s (PCurrencySymbol :--> PTokenName :--> PInteger :--> PValue)
|
psingletonValue :: forall s. Term s (PCurrencySymbol :--> PTokenName :--> PInteger :--> PValue)
|
||||||
psingletonValue = phoistAcyclic $
|
psingletonValue = phoistAcyclic $
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue