encode some enum types as integer on chain
This commit is contained in:
parent
6fe5e2b78a
commit
516f6bacda
6 changed files with 140 additions and 117 deletions
|
|
@ -45,6 +45,11 @@ import Plutarch.DataRepr (
|
|||
PIsDataReprInstances (PIsDataReprInstances),
|
||||
)
|
||||
import Plutarch.Extra.Comonad (pextract)
|
||||
import Plutarch.Extra.IsData (
|
||||
DerivePConstantViaEnum (..),
|
||||
EnumIsData (..),
|
||||
)
|
||||
import Plutarch.Extra.Other (DerivePNewtype' (..))
|
||||
import Plutarch.Extra.TermCont (pletC, pletFieldsC, pmatchC)
|
||||
import Plutarch.Lift (PConstantDecl, PUnsafeLiftDecl (..))
|
||||
import Plutarch.SafeMoney (PDiscrete (..))
|
||||
|
|
@ -92,15 +97,27 @@ data GovernorRedeemer
|
|||
MintGATs
|
||||
| -- | Allows effects to mutate the parameters.
|
||||
MutateGovernor
|
||||
deriving stock (Show, GHC.Generic)
|
||||
|
||||
-- | @since 0.1.0
|
||||
PlutusTx.makeIsDataIndexed
|
||||
''GovernorRedeemer
|
||||
[ ('CreateProposal, 0)
|
||||
, ('MintGATs, 1)
|
||||
, ('MutateGovernor, 2)
|
||||
]
|
||||
deriving stock
|
||||
( -- | @since 0.1.0
|
||||
Show
|
||||
, -- | @since 0.1.0
|
||||
GHC.Generic
|
||||
, -- | @since 0.2.0
|
||||
Enum
|
||||
, -- | @since 0.2.0
|
||||
Bounded
|
||||
)
|
||||
deriving anyclass
|
||||
( -- | @since 0.2.0
|
||||
Generic
|
||||
)
|
||||
deriving
|
||||
( -- | @since 0.1.0
|
||||
PlutusTx.ToData
|
||||
, -- | @since 0.1.0
|
||||
PlutusTx.FromData
|
||||
)
|
||||
via (EnumIsData GovernorRedeemer)
|
||||
|
||||
{- | Parameters for creating Governor scripts.
|
||||
|
||||
|
|
@ -172,10 +189,8 @@ deriving via PAsData (PIsDataReprInstances PGovernorDatum) instance PTryFrom PDa
|
|||
|
||||
@since 0.1.0
|
||||
-}
|
||||
data PGovernorRedeemer (s :: S)
|
||||
= PCreateProposal (Term s (PDataRecord '[]))
|
||||
| PMintGATs (Term s (PDataRecord '[]))
|
||||
| PMutateGovernor (Term s (PDataRecord '[]))
|
||||
newtype PGovernorRedeemer (s :: S)
|
||||
= PGovernorRedeemer (Term s PInteger)
|
||||
deriving stock
|
||||
( -- | @since 0.1.0
|
||||
GHC.Generic
|
||||
|
|
@ -184,26 +199,19 @@ data PGovernorRedeemer (s :: S)
|
|||
( -- | @since 0.1.0
|
||||
Generic
|
||||
)
|
||||
deriving anyclass
|
||||
( -- | @since 0.1.0
|
||||
PIsDataRepr
|
||||
)
|
||||
deriving
|
||||
( -- | @since 0.1.0
|
||||
PlutusType
|
||||
, -- | @since 0.1.0
|
||||
PIsData
|
||||
)
|
||||
via PIsDataReprInstances PGovernorRedeemer
|
||||
via (DerivePNewtype' PGovernorRedeemer)
|
||||
|
||||
-- | @since 0.1.0
|
||||
instance PUnsafeLiftDecl PGovernorRedeemer where type PLifted PGovernorRedeemer = GovernorRedeemer
|
||||
|
||||
-- | @since 0.1.0
|
||||
deriving via (DerivePConstantViaData GovernorRedeemer PGovernorRedeemer) instance (PConstantDecl GovernorRedeemer)
|
||||
|
||||
-- | @since 0.1.0
|
||||
deriving via PAsData (PIsDataReprInstances PGovernorRedeemer) instance PTryFrom PData (PAsData PGovernorRedeemer)
|
||||
deriving via (DerivePConstantViaEnum GovernorRedeemer PGovernorRedeemer) instance (PConstantDecl GovernorRedeemer)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
|
|
|||
|
|
@ -39,18 +39,17 @@ import Agora.AuthorityToken (
|
|||
)
|
||||
import Agora.Governor (
|
||||
Governor (gstOutRef, gtClassRef, maximumCosigners),
|
||||
GovernorRedeemer (..),
|
||||
PGovernorDatum (PGovernorDatum),
|
||||
PGovernorRedeemer (PCreateProposal, PMintGATs, PMutateGovernor),
|
||||
governorDatumValid,
|
||||
pgetNextProposalId,
|
||||
)
|
||||
import Agora.Proposal (
|
||||
PProposalDatum (..),
|
||||
PProposalId (..),
|
||||
PProposalStatus (PFinished),
|
||||
PResultTag,
|
||||
Proposal (..),
|
||||
ProposalStatus (Draft, Locked),
|
||||
ProposalStatus (Draft, Finished, Locked),
|
||||
pemptyVotesFor,
|
||||
pneutralOption,
|
||||
proposalDatumValid,
|
||||
|
|
@ -105,20 +104,20 @@ import Plutarch.Api.V1.AssetClass (
|
|||
passetClass,
|
||||
passetClassValueOf,
|
||||
)
|
||||
import Plutarch.Api.V1.ScriptContext (pfindTxInByTxOutRef, pisUTXOSpent, ptryFindDatum, ptxSignedBy, pvalueSpent)
|
||||
import "liqwid-plutarch-extra" Plutarch.Api.V1.Value (psymbolValueOf)
|
||||
import Plutarch.Extra.IsData (pmatchEnumFromData)
|
||||
import Plutarch.Extra.Map (
|
||||
pkeys,
|
||||
plookup,
|
||||
plookup',
|
||||
)
|
||||
import Plutarch.Extra.Maybe (pisDJust)
|
||||
import Plutarch.Extra.TermCont (pguardC, pletC, pletFieldsC, pmatchC, ptryFromC)
|
||||
import Plutarch.SafeMoney (PDiscrete (..), pvalueDiscrete')
|
||||
import Plutarch.TryFrom ()
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
import Plutarch.Api.V1.ScriptContext (pfindTxInByTxOutRef, pisUTXOSpent, ptryFindDatum, ptxSignedBy, pvalueSpent)
|
||||
import "liqwid-plutarch-extra" Plutarch.Api.V1.Value (psymbolValueOf)
|
||||
import Plutarch.Extra.Maybe (pisDJust)
|
||||
import Plutarch.Extra.TermCont
|
||||
import PlutusLedgerApi.V1 (
|
||||
CurrencySymbol (..),
|
||||
MintingPolicy,
|
||||
|
|
@ -280,7 +279,6 @@ governorPolicy gov =
|
|||
governorValidator :: Governor -> ClosedTerm PValidator
|
||||
governorValidator gov =
|
||||
plam $ \datum' redeemer' ctx' -> unTermCont $ do
|
||||
(pfromData -> redeemer, _) <- ptryFromC redeemer'
|
||||
ctxF <- pletFieldsC @'["txInfo", "purpose"] ctx'
|
||||
|
||||
txInfo' <- pletC $ pfromData $ ctxF.txInfo
|
||||
|
|
@ -330,8 +328,8 @@ governorValidator gov =
|
|||
pguardC "New datum is not valid" $ governorDatumValid # newGovernorDatum
|
||||
|
||||
pure $
|
||||
pmatch redeemer $ \case
|
||||
PCreateProposal _ -> unTermCont $ do
|
||||
pmatchEnumFromData redeemer' $ \case
|
||||
Just CreateProposal -> unTermCont $ do
|
||||
-- Check that the transaction advances proposal id.
|
||||
|
||||
let expectedNextProposalId = pgetNextProposalId # oldGovernorDatumF.nextProposalId
|
||||
|
|
@ -516,7 +514,7 @@ governorValidator gov =
|
|||
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
PMintGATs _ -> unTermCont $ do
|
||||
Just MintGATs -> unTermCont $ do
|
||||
pguardC "Governor state should not be changed" $ newGovernorDatum #== oldGovernorDatum
|
||||
|
||||
-- Filter out proposal inputs and ouputs using PST and the address of proposal validator.
|
||||
|
|
@ -583,7 +581,7 @@ governorValidator gov =
|
|||
PProposalDatum
|
||||
( #proposalId .= proposalInputDatumF.proposalId
|
||||
.& #effects .= proposalInputDatumF.effects
|
||||
.& #status .= pdata (pcon $ PFinished pdnil)
|
||||
.& #status .= pconstantData Finished
|
||||
.& #cosigners .= proposalInputDatumF.cosigners
|
||||
.& #thresholds .= proposalInputDatumF.thresholds
|
||||
.& #votes .= proposalInputDatumF.votes
|
||||
|
|
@ -667,9 +665,12 @@ governorValidator gov =
|
|||
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
PMutateGovernor _ -> unTermCont $ do
|
||||
Just MutateGovernor -> unTermCont $ do
|
||||
-- Check that a GAT is burnt.
|
||||
pure $ popaque $ singleAuthorityTokenBurned patSymbol ctxF.txInfo txInfoF.mint
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
Nothing -> ptraceError "Unknown redeemer"
|
||||
where
|
||||
-- Get th amount of governance tokens in a value.
|
||||
pgtValueOf :: Term s (PValue _ _ :--> PDiscrete GTTag)
|
||||
|
|
|
|||
|
|
@ -51,9 +51,14 @@ import Plutarch.Api.V1 (
|
|||
PValidatorHash,
|
||||
)
|
||||
import Plutarch.DataRepr (DerivePConstantViaData (..), PDataFields, PIsDataReprInstances (..))
|
||||
import Plutarch.Extra.IsData (
|
||||
DerivePConstantViaEnum (..),
|
||||
EnumIsData (..),
|
||||
)
|
||||
import Plutarch.Extra.List (pnotNull)
|
||||
import Plutarch.Extra.Map qualified as PM
|
||||
import Plutarch.Extra.Map.Unsorted qualified as PUM
|
||||
import Plutarch.Extra.Other (DerivePNewtype' (..))
|
||||
import Plutarch.Extra.TermCont (pguardC, pletC, pletFieldsC)
|
||||
import Plutarch.Lift (
|
||||
DerivePConstantViaNewtype (..),
|
||||
|
|
@ -173,10 +178,24 @@ data ProposalStatus
|
|||
Show
|
||||
, -- | @since 0.1.0
|
||||
GHC.Generic
|
||||
, -- | @since 0.2.0
|
||||
Enum
|
||||
, -- | @since 0.2.0
|
||||
Bounded
|
||||
)
|
||||
|
||||
-- | @since 0.1.0
|
||||
PlutusTx.makeIsDataIndexed ''ProposalStatus [('Draft, 0), ('VotingReady, 1), ('Locked, 2), ('Finished, 3)]
|
||||
deriving anyclass
|
||||
( -- | @since 0.2.0
|
||||
Generic
|
||||
)
|
||||
deriving
|
||||
( -- | @since 0.1.0
|
||||
PlutusTx.FromData
|
||||
, -- | @since 0.1.0
|
||||
PlutusTx.ToData
|
||||
, -- | @since 0.1.0
|
||||
PlutusTx.UnsafeFromData
|
||||
)
|
||||
via (EnumIsData ProposalStatus)
|
||||
|
||||
{- | The threshold values for various state transitions to happen.
|
||||
This data is stored centrally (in the 'Agora.Governor.Governor') and copied over
|
||||
|
|
@ -433,13 +452,7 @@ deriving via
|
|||
|
||||
@since 0.1.0
|
||||
-}
|
||||
data PProposalStatus (s :: S)
|
||||
= -- TODO: 'PProposalStatus' ought te be encoded as 'PInteger'.
|
||||
-- e.g. like Tilde used 'pmatchEnum'.
|
||||
PDraft (Term s (PDataRecord '[]))
|
||||
| PVotingReady (Term s (PDataRecord '[]))
|
||||
| PLocked (Term s (PDataRecord '[]))
|
||||
| PFinished (Term s (PDataRecord '[]))
|
||||
newtype PProposalStatus (s :: S) = PProposalStatus (Term s PInteger)
|
||||
deriving stock
|
||||
( -- | @since 0.1.0
|
||||
GHC.Generic
|
||||
|
|
@ -448,10 +461,6 @@ data PProposalStatus (s :: S)
|
|||
( -- | @since 0.1.0
|
||||
Generic
|
||||
)
|
||||
deriving anyclass
|
||||
( -- | @since 0.1.0
|
||||
PIsDataRepr
|
||||
)
|
||||
deriving
|
||||
( -- | @since 0.1.0
|
||||
PlutusType
|
||||
|
|
@ -460,16 +469,16 @@ data PProposalStatus (s :: S)
|
|||
, -- | @since 0.1.0
|
||||
PEq
|
||||
)
|
||||
via PIsDataReprInstances PProposalStatus
|
||||
via (DerivePNewtype' PProposalStatus)
|
||||
|
||||
-- | @since 0.1.0
|
||||
instance PUnsafeLiftDecl PProposalStatus where type PLifted PProposalStatus = ProposalStatus
|
||||
|
||||
-- | @since 0.1.0
|
||||
deriving via PAsData (PIsDataReprInstances PProposalStatus) instance PTryFrom PData (PAsData PProposalStatus)
|
||||
deriving via PAsData (DerivePNewtype' PProposalStatus) instance PTryFrom PData (PAsData PProposalStatus)
|
||||
|
||||
-- | @since 0.1.0
|
||||
deriving via (DerivePConstantViaData ProposalStatus PProposalStatus) instance (PConstantDecl ProposalStatus)
|
||||
deriving via (DerivePConstantViaEnum ProposalStatus PProposalStatus) instance (PConstantDecl ProposalStatus)
|
||||
|
||||
{- | Plutarch-level version of 'ProposalThresholds'.
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@ module Agora.Proposal.Scripts (
|
|||
import Agora.Proposal (
|
||||
PProposalDatum (PProposalDatum),
|
||||
PProposalRedeemer (..),
|
||||
PProposalStatus (..),
|
||||
PProposalVotes (PProposalVotes),
|
||||
Proposal (governorSTAssetClass, stakeSTAssetClass),
|
||||
ProposalStatus (..),
|
||||
|
|
@ -55,6 +54,7 @@ import Plutarch.Api.V1.ScriptContext (
|
|||
)
|
||||
import "liqwid-plutarch-extra" Plutarch.Api.V1.Value (psymbolValueOf)
|
||||
import Plutarch.Extra.Comonad (pextract)
|
||||
import Plutarch.Extra.IsData (pmatchEnum)
|
||||
import Plutarch.Extra.List (pisUniqBy)
|
||||
import Plutarch.Extra.Map (plookup, pupdate)
|
||||
import Plutarch.Extra.Maybe (pisJust)
|
||||
|
|
@ -510,19 +510,21 @@ proposalValidator proposal =
|
|||
inLockedPeriod <- pletC $ isLockingPeriod # proposalF.timingConfig # proposalF.startingTime # currentTime
|
||||
inExecutionPeriod <- pletC $ isExecutionPeriod # proposalF.timingConfig # proposalF.startingTime # currentTime
|
||||
|
||||
proposalStatus <- pletC $ pto $ pfromData proposalF.status
|
||||
|
||||
-- Check the timings.
|
||||
let isFinished = proposalF.status #== pconstantData Finished
|
||||
|
||||
notTooLate = pmatch (pfromData proposalF.status) $ \case
|
||||
PDraft _ -> inDraftPeriod
|
||||
notTooLate = pmatchEnum proposalStatus $ \case
|
||||
Draft -> inDraftPeriod
|
||||
-- Can only advance after the voting period is over.
|
||||
PVotingReady _ -> inLockedPeriod
|
||||
PLocked _ -> inExecutionPeriod
|
||||
VotingReady -> inLockedPeriod
|
||||
Locked -> inExecutionPeriod
|
||||
_ -> pconstant False
|
||||
|
||||
notTooEarly = pmatch (pfromData proposalF.status) $ \case
|
||||
PVotingReady _ -> pnot # inVotingPeriod
|
||||
PLocked _ -> pnot # inLockedPeriod
|
||||
notTooEarly = pmatchEnum (pto $ pfromData proposalF.status) $ \case
|
||||
VotingReady -> pnot # inVotingPeriod
|
||||
Locked -> pnot # inLockedPeriod
|
||||
_ -> pconstant True
|
||||
|
||||
pguardC "Cannot advance ahead of time" notTooEarly
|
||||
|
|
@ -534,8 +536,8 @@ proposalValidator proposal =
|
|||
pif
|
||||
notTooLate
|
||||
-- On time: advance to next status.
|
||||
( pmatch (pfromData proposalF.status) $ \case
|
||||
PDraft _ -> unTermCont $ do
|
||||
( pmatchEnum proposalStatus $ \case
|
||||
Draft -> unTermCont $ do
|
||||
-- TODO: Perform other necessary checks.
|
||||
|
||||
-- 'Draft' -> 'VotingReady'
|
||||
|
|
@ -543,7 +545,7 @@ proposalValidator proposal =
|
|||
proposalOutStatus #== pconstantData VotingReady
|
||||
|
||||
pure $ popaque (pconstant ())
|
||||
PVotingReady _ -> unTermCont $ do
|
||||
VotingReady -> unTermCont $ do
|
||||
-- 'VotingReady' -> 'Locked'
|
||||
pguardC "Proposal status set to Locked" $
|
||||
proposalOutStatus #== pconstantData Locked
|
||||
|
|
@ -554,7 +556,7 @@ proposalValidator proposal =
|
|||
$ pfromData thresholdsF.execute
|
||||
|
||||
pure $ popaque (pconstant ())
|
||||
PLocked _ -> unTermCont $ do
|
||||
Locked -> unTermCont $ do
|
||||
-- 'Locked' -> 'Finished'
|
||||
pguardC "Proposal status set to Finished" $
|
||||
proposalOutStatus #== pconstantData Finished
|
||||
|
|
|
|||
|
|
@ -12,15 +12,13 @@ module Agora.Treasury (module Agora.Treasury) where
|
|||
|
||||
import Agora.AuthorityToken (singleAuthorityTokenBurned)
|
||||
import GHC.Generics qualified as GHC
|
||||
import Generics.SOP (Generic, I (I))
|
||||
import Generics.SOP (Generic)
|
||||
import Plutarch.Api.V1 (PValidator)
|
||||
import Plutarch.Api.V1.Contexts (PScriptPurpose (PMinting))
|
||||
import "plutarch" Plutarch.Api.V1.Value (PValue)
|
||||
import Plutarch.DataRepr (
|
||||
DerivePConstantViaData (..),
|
||||
PIsDataReprInstances (PIsDataReprInstances),
|
||||
)
|
||||
import Plutarch.Extra.TermCont (pguardC, pletC, pletFieldsC, pmatchC, ptryFromC)
|
||||
import Plutarch.Extra.IsData (DerivePConstantViaEnum (..), EnumIsData (..), pmatchEnumFromData)
|
||||
import Plutarch.Extra.Other (DerivePNewtype' (..))
|
||||
import Plutarch.Extra.TermCont (pguardC, pletC, pletFieldsC, pmatchC)
|
||||
import Plutarch.Lift (PConstantDecl (..), PLifted (..), PUnsafeLiftDecl)
|
||||
import Plutarch.TryFrom ()
|
||||
import PlutusLedgerApi.V1.Value (CurrencySymbol)
|
||||
|
|
@ -40,13 +38,22 @@ data TreasuryRedeemer
|
|||
Show
|
||||
, -- | @since 0.1.0
|
||||
GHC.Generic
|
||||
, -- | @since 0.2.0
|
||||
Enum
|
||||
, -- | @since 0.2.0
|
||||
Bounded
|
||||
)
|
||||
|
||||
-- | @since 0.1.0
|
||||
PlutusTx.makeIsDataIndexed
|
||||
''TreasuryRedeemer
|
||||
[ ('SpendTreasuryGAT, 0)
|
||||
]
|
||||
deriving anyclass
|
||||
( -- | @since 0.2.0
|
||||
Generic
|
||||
)
|
||||
deriving
|
||||
( -- | @since 0.1.0
|
||||
PlutusTx.ToData
|
||||
, -- | @since 0.1.0
|
||||
PlutusTx.FromData
|
||||
)
|
||||
via (EnumIsData TreasuryRedeemer)
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
|
|
@ -56,9 +63,7 @@ PlutusTx.makeIsDataIndexed
|
|||
@since 0.1.0
|
||||
-}
|
||||
newtype PTreasuryRedeemer (s :: S)
|
||||
= -- | Alters treasury parameters, subject to the burning of a
|
||||
-- governance authority token.
|
||||
PSpendTreasuryGAT (Term s (PDataRecord '[]))
|
||||
= PTreasuryRedeemer (Term s PInteger)
|
||||
deriving stock
|
||||
( -- | @since 0.1.0
|
||||
GHC.Generic
|
||||
|
|
@ -66,8 +71,6 @@ newtype PTreasuryRedeemer (s :: S)
|
|||
deriving anyclass
|
||||
( -- | @since 0.1.0
|
||||
Generic
|
||||
, -- | @since 0.1.0
|
||||
PIsDataRepr
|
||||
)
|
||||
deriving
|
||||
( -- | @since 0.1.0
|
||||
|
|
@ -75,13 +78,7 @@ newtype PTreasuryRedeemer (s :: S)
|
|||
, -- | @since 0.1.0
|
||||
PIsData
|
||||
)
|
||||
via PIsDataReprInstances PTreasuryRedeemer
|
||||
|
||||
-- | @since 0.1.0
|
||||
deriving via
|
||||
PAsData (PIsDataReprInstances PTreasuryRedeemer)
|
||||
instance
|
||||
PTryFrom PData (PAsData PTreasuryRedeemer)
|
||||
via (DerivePNewtype' PTreasuryRedeemer)
|
||||
|
||||
-- | @since 0.1.0
|
||||
instance PUnsafeLiftDecl PTreasuryRedeemer where
|
||||
|
|
@ -89,7 +86,7 @@ instance PUnsafeLiftDecl PTreasuryRedeemer where
|
|||
|
||||
-- | @since 0.1.0
|
||||
deriving via
|
||||
(DerivePConstantViaData TreasuryRedeemer PTreasuryRedeemer)
|
||||
(DerivePConstantViaEnum TreasuryRedeemer PTreasuryRedeemer)
|
||||
instance
|
||||
(PConstantDecl TreasuryRedeemer)
|
||||
|
||||
|
|
@ -105,8 +102,6 @@ treasuryValidator ::
|
|||
CurrencySymbol ->
|
||||
ClosedTerm PValidator
|
||||
treasuryValidator gatCs' = plam $ \_datum redeemer ctx' -> unTermCont $ do
|
||||
(treasuryRedeemer, _) <- ptryFromC redeemer
|
||||
|
||||
-- plet required fields from script context.
|
||||
ctx <- pletFieldsC @["txInfo", "purpose"] ctx'
|
||||
|
||||
|
|
@ -114,7 +109,15 @@ treasuryValidator gatCs' = plam $ \_datum redeemer ctx' -> unTermCont $ do
|
|||
PMinting _ <- pmatchC ctx.purpose
|
||||
|
||||
-- Ensure redeemer type is valid.
|
||||
PSpendTreasuryGAT _ <- pmatchC $ pfromData treasuryRedeemer
|
||||
let redeemerValid =
|
||||
pmatchEnumFromData
|
||||
redeemer
|
||||
( \case
|
||||
Just SpendTreasuryGAT -> pconstant True
|
||||
_ -> pconstant False
|
||||
)
|
||||
|
||||
pguardC "Redeemer should be SpendTreasuryGAT" redeemerValid
|
||||
|
||||
-- Get the minted value from txInfo.
|
||||
txInfo' <- pletC ctx.txInfo
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue