handle effects that mutate params of the governor

This commit is contained in:
fanghr 2022-04-16 18:49:25 +08:00
parent de517fc144
commit 731e714fc3

View file

@ -29,13 +29,34 @@ import Generics.SOP (Generic, I (I))
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
import Agora.Proposal (PProposalId, PProposalThresholds, ProposalId, ProposalThresholds) import Agora.AuthorityToken (authorityTokensValidIn)
import Agora.Utils (findOutputsToAddress, passert, passetClassValueOf', pfindTxInByTxOutRef, findTxOutDatum) import Agora.Proposal (
PProposalId,
PProposalThresholds,
ProposalId,
ProposalThresholds,
)
import Agora.Utils (
allInputs,
findOutputsToAddress,
findTxOutDatum,
passert,
passetClassValueOf',
pfindTxInByTxOutRef,
pisDJust,
psymbolValueOf,
)
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
import Plutarch (popaque) import Plutarch (popaque)
import Plutarch.Api.V1 (PMaybeData (PDJust), PMintingPolicy, PScriptPurpose (PSpending), PValidator, PValue) import Plutarch.Api.V1 (
PCurrencySymbol,
PMintingPolicy,
PScriptPurpose (PSpending),
PValidator,
PValue,
)
import Plutarch.DataRepr ( import Plutarch.DataRepr (
DerivePConstantViaData (..), DerivePConstantViaData (..),
PDataFields, PDataFields,
@ -43,11 +64,11 @@ import Plutarch.DataRepr (
) )
import Plutarch.Lift (PUnsafeLiftDecl (..)) import Plutarch.Lift (PUnsafeLiftDecl (..))
import Plutarch.Monadic qualified as P import Plutarch.Monadic qualified as P
import Plutarch.Unsafe (punsafeCoerce)
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
import Plutarch.Unsafe (punsafeCoerce) import Plutus.V1.Ledger.Value (AssetClass, CurrencySymbol)
import Plutus.V1.Ledger.Value (AssetClass)
import PlutusTx qualified import PlutusTx qualified
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@ -92,6 +113,8 @@ PlutusTx.makeIsDataIndexed
data Governor = Governor data Governor = Governor
{ datumNFT :: AssetClass { datumNFT :: AssetClass
-- ^ NFT that identifies the governor datum. -- ^ NFT that identifies the governor datum.
, gatSymbol :: CurrencySymbol
-- ^ The symbol of Governance Authority Token
} }
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@ -157,43 +180,68 @@ governorValidator params =
ownInput <- pletFields @'["address", "value", "datumHash"] ownInput' ownInput <- pletFields @'["address", "value", "datumHash"] ownInput'
let selfAddress = pfromData $ ownInput.address let selfAddress = pfromData $ ownInput.address
PJust (((pfromData @PGovernorDatum) . punsafeCoerce) -> oldDatum') <- pmatch $ findTxOutDatum # txInfo # ownInput' PJust oldDatum'' <- pmatch $ findTxOutDatum # txInfo # ownInput'
oldDatum <- pletFields @'["proposalThresholds", "nextProposalId"] oldDatum' oldDatum' <- plet $ pto oldDatum''
let oldParams' = pfromData @PGovernorDatum $ punsafeCoerce oldDatum'
oldParams <- pletFields @'["proposalThresholds", "nextProposalId"] oldParams'
let ownInputDatumNFTAmount = datumNFTValueOf # ownInput.value let ownInputDatumNFTAmount = datumNFTValueOf # ownInput.value
passert "own input should have exactly one datum NFT" $ ownInputDatumNFTAmount #== 1 passert "Own input should have exactly one datum NFT" $ ownInputDatumNFTAmount #== 1
ownOutputs <- plet $ findOutputsToAddress # txInfo # selfAddress ownOutputs <- plet $ findOutputsToAddress # txInfo # selfAddress
passert "exactly one utxo should be sent to the governor" $ plength # ownOutputs #== 1 passert "Exactly one utxo should be sent to the governor" $ plength # ownOutputs #== 1
ownOutput <- pletFields @'["value", "datumHash"] $ phead # ownOutputs ownOutput <- pletFields @'["value", "datumHash"] $ phead # ownOutputs
let ownOuputDatumNFTAmount = datumNFTValueOf # ownOutput.value let ownOuputDatumNFTAmount = datumNFTValueOf # ownOutput.value
passert "datum NFT should stay at governor's address" $ ownOuputDatumNFTAmount #== 1 passert "Datum NFT should stay at governor's address" $ ownOuputDatumNFTAmount #== 1
passert "output utxo to governor should have datum" $ pisDJust # ownOutput.datumHash passert "Output utxo to governor should have datum" $ pisDJust # ownOutput.datumHash
-- TODO: use `PTryFrom` and reject bad datum
let newDatum' = pfromData @PGovernorDatum $ punsafeCoerce datum' let newDatum' = pfromData @PGovernorDatum $ punsafeCoerce datum'
newDatum <- pletFields @'["proposalThresholds", "nextProposalId"] newDatum' newParams <- pletFields @'["proposalThresholds", "nextProposalId"] newDatum'
mint <- plet $ pfromData $ pfield @"mint" # txInfo
mint' <- plet $ pto $ pto $ pto $ mint
case redeemer of case redeemer of
PCreateProposal _ -> P.do PCreateProposal _ -> P.do
-- TODO: deriving a PNum instance for PProposalId -- check that nothing is minted
let oldPid = pto $ pfromData $ oldDatum.nextProposalId passert "Nothing should be minted" $ plength # mint' #== 0
newPid = pto $ pfromData $ newDatum.nextProposalId
passert "proposal id should be advanced by 1" $ oldPid + 1 #== newPid
ptraceError "not implemented yet" -- check proposal id +1
PMintGATs _ -> perror -- TODO: deriving a PNum instance for PProposalId
PMutateParams _ -> perror let oldPid = pto $ pfromData $ oldParams.nextProposalId
newPid = pto $ pfromData $ newParams.nextProposalId
passert "Proposal id should be advanced by 1" $
oldPid + 1 #== newPid
-- TODO: waiting for impl of proposal
ptraceError "Not implemented yet"
PMintGATs _ -> P.do
-- check datum is not changed
passert "Datum should not be changed" $ oldDatum' #== datum'
-- check exactly one(?) authority token is minted
-- TODO: waiting for impl of proposal
ptraceError "Not implemented yet"
PMutateParams _ -> P.do
-- check that input has exactly one GAT and will be burnt
let gatAmount = psymbolValueOf # gatS # mint
passert "One GAT should be burnt" $ gatAmount #== -1
-- nothing should be minted/burnt other than GAT
passert "No token should be minted/burnt other than GAT" $ plength # mint' #== 1
-- check that GAT is tagged by the address
passert "all input GATs are valid" $
allInputs @PUnit # txInfo #$ plam $ \txOut _ _ _ ->
authorityTokensValidIn # gatS # txOut
popaque $ pconstant ()
where where
datumNFTValueOf :: Term s (PValue :--> PInteger) datumNFTValueOf :: Term s (PValue :--> PInteger)
datumNFTValueOf = passetClassValueOf' params.datumNFT datumNFTValueOf = passetClassValueOf' params.datumNFT
pisDJust :: Term s (PMaybeData a :--> PBool) gatS :: Term s PCurrencySymbol
pisDJust = phoistAcyclic $ gatS = pconstant params.gatSymbol
plam $ \x ->
pmatch
x
( \case
PDJust _ -> pconstant True
_ -> pconstant False
)