add @since tags to everything
This commit is contained in:
parent
9f98653ca6
commit
c9ec0d05c4
19 changed files with 1213 additions and 445 deletions
|
|
@ -2,4 +2,8 @@
|
||||||
|
|
||||||
This format is based on [Keep A Changelog](https://keepachangelog.com/en/1.0.0).
|
This format is based on [Keep A Changelog](https://keepachangelog.com/en/1.0.0).
|
||||||
|
|
||||||
## Unreleased
|
## 0.1.0 -- 2022-06-22
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
* First release
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
cabal-version: 3.0
|
cabal-version: 3.0
|
||||||
name: agora
|
name: agora
|
||||||
version: 0.1
|
version: 0.1.0
|
||||||
extra-source-files: CHANGELOG.md
|
extra-source-files: CHANGELOG.md
|
||||||
author: Emily Martins <emi@haskell.fyi>
|
author: Emily Martins <emi@haskell.fyi>
|
||||||
license: Apache-2.0
|
license: Apache-2.0
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
Module : Agora.AuthorityToken
|
Module : Agora.AuthorityToken
|
||||||
Maintainer : emi@haskell.fyi
|
Maintainer : emi@haskell.fyi
|
||||||
Description: Tokens acting as redeemable proofs of DAO authority.
|
Description: Tokens acting as redeemable proofs of DAO authority.
|
||||||
|
|
||||||
Tokens acting as redeemable proofs of DAO authority.
|
Tokens acting as redeemable proofs of DAO authority.
|
||||||
-}
|
-}
|
||||||
module Agora.AuthorityToken (
|
module Agora.AuthorityToken (
|
||||||
|
|
@ -11,8 +12,7 @@ module Agora.AuthorityToken (
|
||||||
AuthorityToken (..),
|
AuthorityToken (..),
|
||||||
) where
|
) where
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
import GHC.Generics qualified as GHC
|
||||||
|
|
||||||
import Plutarch.Api.V1 (
|
import Plutarch.Api.V1 (
|
||||||
AmountGuarantees,
|
AmountGuarantees,
|
||||||
KeyGuarantees,
|
KeyGuarantees,
|
||||||
|
|
@ -38,21 +38,23 @@ import PlutusLedgerApi.V1.Value (AssetClass (AssetClass))
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
import GHC.Generics qualified as GHC
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
{- | An AuthorityToken represents a proof that a particular token
|
{- | An AuthorityToken represents a proof that a particular token
|
||||||
moved while this token was minted. In effect, this means that
|
spent in the same transaction the AuthorityToken was minted.
|
||||||
the validator that locked such a token must have approved
|
In effect, this means that the validator that locked such a token
|
||||||
said transaction. Said validator should be made aware of
|
must have approved the transaction in which an AuthorityToken is minted.
|
||||||
*this* token's existence in order to prevent incorrect minting.
|
Said validator should be made aware of an AuthorityToken token's existence
|
||||||
|
in order to prevent incorrect minting.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
-}
|
-}
|
||||||
newtype AuthorityToken = AuthorityToken
|
newtype AuthorityToken = AuthorityToken
|
||||||
{ authority :: AssetClass
|
{ authority :: AssetClass
|
||||||
-- ^ Token that must move in order for minting this to be valid.
|
-- ^ Token that must move in order for minting this to be valid.
|
||||||
}
|
}
|
||||||
deriving stock (GHC.Generic)
|
deriving stock
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
GHC.Generic
|
||||||
|
)
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
@ -64,6 +66,8 @@ newtype AuthorityToken = AuthorityToken
|
||||||
it was sent to, this is enough to prove validity.
|
it was sent to, this is enough to prove validity.
|
||||||
In other words, check that all assets of a particular currency symbol
|
In other words, check that all assets of a particular currency symbol
|
||||||
are tagged with a TokenName that matches where they live.
|
are tagged with a TokenName that matches where they live.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
-}
|
-}
|
||||||
authorityTokensValidIn :: Term s (PCurrencySymbol :--> PTxOut :--> PBool)
|
authorityTokensValidIn :: Term s (PCurrencySymbol :--> PTxOut :--> PBool)
|
||||||
authorityTokensValidIn = phoistAcyclic $
|
authorityTokensValidIn = phoistAcyclic $
|
||||||
|
|
@ -94,7 +98,10 @@ authorityTokensValidIn = phoistAcyclic $
|
||||||
-- No GATs exist at this output!
|
-- No GATs exist at this output!
|
||||||
pconstant True
|
pconstant True
|
||||||
|
|
||||||
-- | Assert that a single authority token has been burned.
|
{- | Assert that a single authority token has been burned.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
singleAuthorityTokenBurned ::
|
singleAuthorityTokenBurned ::
|
||||||
forall (keys :: KeyGuarantees) (amounts :: AmountGuarantees) (s :: S).
|
forall (keys :: KeyGuarantees) (amounts :: AmountGuarantees) (s :: S).
|
||||||
Term s PCurrencySymbol ->
|
Term s PCurrencySymbol ->
|
||||||
|
|
@ -122,7 +129,10 @@ singleAuthorityTokenBurned gatCs txInfo mint = unTermCont $ do
|
||||||
# txInfoF.inputs
|
# txInfoF.inputs
|
||||||
]
|
]
|
||||||
|
|
||||||
-- | Policy given 'AuthorityToken' params.
|
{- | Policy given 'AuthorityToken' params.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
authorityTokenPolicy :: AuthorityToken -> ClosedTerm PMintingPolicy
|
authorityTokenPolicy :: AuthorityToken -> ClosedTerm PMintingPolicy
|
||||||
authorityTokenPolicy params =
|
authorityTokenPolicy params =
|
||||||
plam $ \_redeemer ctx' ->
|
plam $ \_redeemer ctx' ->
|
||||||
|
|
|
||||||
|
|
@ -13,13 +13,13 @@ import Plutarch.Extra.TermCont (pguardC, pletC, pmatchC, ptryFromC)
|
||||||
import Plutarch.TryFrom ()
|
import Plutarch.TryFrom ()
|
||||||
import PlutusLedgerApi.V1.Value (CurrencySymbol)
|
import PlutusLedgerApi.V1.Value (CurrencySymbol)
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
{- | Helper "template" for creating effect validator.
|
{- | Helper "template" for creating effect validator.
|
||||||
|
|
||||||
In some situations, it may be the case that we need more control over how
|
In some situations, it may be the case that we need more control over how
|
||||||
an effect is implemented. In such situations, it's okay to not use this
|
an effect is implemented. In such situations, it's okay to not use this
|
||||||
helper.
|
helper.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
-}
|
-}
|
||||||
makeEffect ::
|
makeEffect ::
|
||||||
forall (datum :: PType).
|
forall (datum :: PType).
|
||||||
|
|
|
||||||
|
|
@ -18,39 +18,6 @@ module Agora.Effect.GovernorMutation (
|
||||||
mutateGovernorValidator,
|
mutateGovernorValidator,
|
||||||
) where
|
) where
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
import Control.Applicative (Const)
|
|
||||||
import GHC.Generics qualified as GHC
|
|
||||||
import Generics.SOP (Generic, I (I))
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
import Plutarch.Api.V1 (
|
|
||||||
PTxOutRef,
|
|
||||||
PValidator,
|
|
||||||
PValue,
|
|
||||||
)
|
|
||||||
import Plutarch.Api.V1.ScriptContext (ptryFindDatum)
|
|
||||||
import "liqwid-plutarch-extra" Plutarch.Api.V1.Value (pvalueOf)
|
|
||||||
import Plutarch.DataRepr (
|
|
||||||
DerivePConstantViaData (..),
|
|
||||||
PDataFields,
|
|
||||||
PIsDataReprInstances (PIsDataReprInstances),
|
|
||||||
)
|
|
||||||
import Plutarch.Extra.TermCont (pguardC)
|
|
||||||
import Plutarch.Lift (PConstantDecl, PLifted, PUnsafeLiftDecl)
|
|
||||||
import Plutarch.TryFrom (PTryFrom (..))
|
|
||||||
import Plutarch.Unsafe (punsafeCoerce)
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
import PlutusLedgerApi.V1 (TxOutRef)
|
|
||||||
import PlutusLedgerApi.V1.Value (AssetClass (..))
|
|
||||||
import PlutusTx qualified
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
import Agora.Effect (makeEffect)
|
import Agora.Effect (makeEffect)
|
||||||
import Agora.Governor (
|
import Agora.Governor (
|
||||||
Governor,
|
Governor,
|
||||||
|
|
@ -67,10 +34,35 @@ import Agora.Utils (
|
||||||
mustBePDJust,
|
mustBePDJust,
|
||||||
mustBePJust,
|
mustBePJust,
|
||||||
)
|
)
|
||||||
|
import Control.Applicative (Const)
|
||||||
|
import GHC.Generics qualified as GHC
|
||||||
|
import Generics.SOP (Generic, I (I))
|
||||||
|
import Plutarch.Api.V1 (
|
||||||
|
PTxOutRef,
|
||||||
|
PValidator,
|
||||||
|
PValue,
|
||||||
|
)
|
||||||
|
import Plutarch.Api.V1.ScriptContext (ptryFindDatum)
|
||||||
|
import "liqwid-plutarch-extra" Plutarch.Api.V1.Value (pvalueOf)
|
||||||
|
import Plutarch.DataRepr (
|
||||||
|
DerivePConstantViaData (..),
|
||||||
|
PDataFields,
|
||||||
|
PIsDataReprInstances (PIsDataReprInstances),
|
||||||
|
)
|
||||||
|
import Plutarch.Extra.TermCont (pguardC)
|
||||||
|
import Plutarch.Lift (PConstantDecl, PLifted, PUnsafeLiftDecl)
|
||||||
|
import Plutarch.TryFrom (PTryFrom (..))
|
||||||
|
import Plutarch.Unsafe (punsafeCoerce)
|
||||||
|
import PlutusLedgerApi.V1 (TxOutRef)
|
||||||
|
import PlutusLedgerApi.V1.Value (AssetClass (..))
|
||||||
|
import PlutusTx qualified
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
-- | Haskell-level datum for the governor mutation effect script.
|
{- | Haskell-level datum for the governor mutation effect script.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
data MutateGovernorDatum = MutateGovernorDatum
|
data MutateGovernorDatum = MutateGovernorDatum
|
||||||
{ governorRef :: TxOutRef
|
{ governorRef :: TxOutRef
|
||||||
-- ^ Referenced governor state UTXO should be updated by the effect.
|
-- ^ Referenced governor state UTXO should be updated by the effect.
|
||||||
|
|
@ -84,7 +76,10 @@ PlutusTx.makeIsDataIndexed ''MutateGovernorDatum [('MutateGovernorDatum, 0)]
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
-- | Plutarch-level version of 'MutateGovernorDatum'.
|
{- | Plutarch-level version of 'MutateGovernorDatum'.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
newtype PMutateGovernorDatum (s :: S)
|
newtype PMutateGovernorDatum (s :: S)
|
||||||
= PMutateGovernorDatum
|
= PMutateGovernorDatum
|
||||||
( Term
|
( Term
|
||||||
|
|
@ -95,17 +90,39 @@ newtype PMutateGovernorDatum (s :: S)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
deriving stock (GHC.Generic)
|
deriving stock
|
||||||
deriving anyclass (Generic)
|
( -- | @since 0.1.0
|
||||||
deriving anyclass (PIsDataRepr)
|
GHC.Generic
|
||||||
|
)
|
||||||
|
deriving anyclass
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
Generic
|
||||||
|
)
|
||||||
|
deriving anyclass
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
PIsDataRepr
|
||||||
|
)
|
||||||
deriving
|
deriving
|
||||||
(PlutusType, PIsData, PDataFields, PEq)
|
( -- | @since 0.1.0
|
||||||
|
PlutusType
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PIsData
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PDataFields
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PEq
|
||||||
|
)
|
||||||
via (PIsDataReprInstances PMutateGovernorDatum)
|
via (PIsDataReprInstances PMutateGovernorDatum)
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
instance PUnsafeLiftDecl PMutateGovernorDatum where type PLifted PMutateGovernorDatum = MutateGovernorDatum
|
instance PUnsafeLiftDecl PMutateGovernorDatum where type PLifted PMutateGovernorDatum = MutateGovernorDatum
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
deriving via (DerivePConstantViaData MutateGovernorDatum PMutateGovernorDatum) instance (PConstantDecl MutateGovernorDatum)
|
deriving via (DerivePConstantViaData MutateGovernorDatum PMutateGovernorDatum) instance (PConstantDecl MutateGovernorDatum)
|
||||||
|
|
||||||
-- TODO: Derive this.
|
-- TODO: Derive this.
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
instance PTryFrom PData (PAsData PMutateGovernorDatum) where
|
instance PTryFrom PData (PAsData PMutateGovernorDatum) where
|
||||||
type PTryFromExcess PData (PAsData PMutateGovernorDatum) = Const ()
|
type PTryFromExcess PData (PAsData PMutateGovernorDatum) = Const ()
|
||||||
ptryFrom' d k =
|
ptryFrom' d k =
|
||||||
|
|
@ -115,26 +132,28 @@ instance PTryFrom PData (PAsData PMutateGovernorDatum) where
|
||||||
|
|
||||||
{- | Validator for the governor mutation effect.
|
{- | Validator for the governor mutation effect.
|
||||||
|
|
||||||
This effect is implemented using the 'Agora.Effect.makeEffect' wrapper,
|
This effect is implemented using the 'Agora.Effect.makeEffect' wrapper,
|
||||||
meaning that the burning of GAT is checked in said wrapper.
|
meaning that the burning of GAT is checked in said wrapper.
|
||||||
|
|
||||||
In order to locate the governor, the validator is parametrized with a 'Agora.Governor.Governor'.
|
In order to locate the governor, the validator is parametrized with a 'Agora.Governor.Governor'.
|
||||||
|
|
||||||
All the information it needs to validate the effect is encoded in the 'MutateGovernorDatum',
|
All the information it needs to validate the effect is encoded in the 'MutateGovernorDatum',
|
||||||
so regardless what redeemer it's given, it will check:
|
so regardless what redeemer it's given, it will check:
|
||||||
|
|
||||||
- No token is minted/burnt other than GAT.
|
- No token is minted/burnt other than GAT.
|
||||||
- Nothing is being paid to the the effect validator.
|
- Nothing is being paid to the the effect validator.
|
||||||
- The governor's state UTXO must be spent:
|
- The governor's state UTXO must be spent:
|
||||||
|
|
||||||
* It carries exactly one GST.
|
* It carries exactly one GST.
|
||||||
* It's referenced by 'governorRef' in the effect's datum.
|
* It's referenced by 'governorRef' in the effect's datum.
|
||||||
|
|
||||||
- A new state UTXO is paid to the governor:
|
- A new state UTXO is paid to the governor:
|
||||||
|
|
||||||
* It contains the GST.
|
* It contains the GST.
|
||||||
* It has valid governor state datum.
|
* It has valid governor state datum.
|
||||||
* The datum is exactly the same as the 'newDatum'.
|
* The datum is exactly the same as the 'newDatum'.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
-}
|
-}
|
||||||
mutateGovernorValidator :: Governor -> ClosedTerm PValidator
|
mutateGovernorValidator :: Governor -> ClosedTerm PValidator
|
||||||
mutateGovernorValidator gov = makeEffect (authorityTokenSymbolFromGovernor gov) $
|
mutateGovernorValidator gov = makeEffect (authorityTokenSymbolFromGovernor gov) $
|
||||||
|
|
|
||||||
|
|
@ -14,10 +14,20 @@ import Plutarch.Api.V1 (PValidator)
|
||||||
import Plutarch.TryFrom (PTryFrom (..))
|
import Plutarch.TryFrom (PTryFrom (..))
|
||||||
import PlutusLedgerApi.V1.Value (CurrencySymbol)
|
import PlutusLedgerApi.V1.Value (CurrencySymbol)
|
||||||
|
|
||||||
-- | Dummy datum for NoOp effect.
|
{- | Dummy datum for NoOp effect.
|
||||||
newtype PNoOp (s :: S) = PNoOp (Term s PUnit)
|
|
||||||
deriving (PlutusType, PIsData) via (DerivePNewtype PNoOp PUnit)
|
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
|
newtype PNoOp (s :: S) = PNoOp (Term s PUnit)
|
||||||
|
deriving
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
PlutusType
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PIsData
|
||||||
|
)
|
||||||
|
via (DerivePNewtype PNoOp PUnit)
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
instance PTryFrom PData (PAsData PNoOp) where
|
instance PTryFrom PData (PAsData PNoOp) where
|
||||||
type PTryFromExcess PData (PAsData PNoOp) = Const ()
|
type PTryFromExcess PData (PAsData PNoOp) = Const ()
|
||||||
ptryFrom' _ cont =
|
ptryFrom' _ cont =
|
||||||
|
|
@ -26,7 +36,10 @@ instance PTryFrom PData (PAsData PNoOp) where
|
||||||
-- It should always be reduced to Unit.
|
-- It should always be reduced to Unit.
|
||||||
cont (pdata $ pcon $ PNoOp (pconstant ()), ())
|
cont (pdata $ pcon $ PNoOp (pconstant ()), ())
|
||||||
|
|
||||||
-- | Dummy effect which can only burn its GAT.
|
{- | Dummy effect which can only burn its GAT.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
noOpValidator :: CurrencySymbol -> ClosedTerm PValidator
|
noOpValidator :: CurrencySymbol -> ClosedTerm PValidator
|
||||||
noOpValidator curr = makeEffect curr $
|
noOpValidator curr = makeEffect curr $
|
||||||
\_ (_datum :: Term s PNoOp) _ _ -> popaque (pconstant ())
|
\_ (_datum :: Term s PNoOp) _ _ -> popaque (pconstant ())
|
||||||
|
|
|
||||||
|
|
@ -13,12 +13,11 @@ module Agora.Effect.TreasuryWithdrawal (
|
||||||
treasuryWithdrawalValidator,
|
treasuryWithdrawalValidator,
|
||||||
) where
|
) where
|
||||||
|
|
||||||
|
import Agora.Effect (makeEffect)
|
||||||
|
import Agora.Utils (isPubKey)
|
||||||
import Control.Applicative (Const)
|
import Control.Applicative (Const)
|
||||||
import GHC.Generics qualified as GHC
|
import GHC.Generics qualified as GHC
|
||||||
import Generics.SOP (Generic, I (I))
|
import Generics.SOP (Generic, I (I))
|
||||||
|
|
||||||
import Agora.Effect (makeEffect)
|
|
||||||
import Agora.Utils (isPubKey)
|
|
||||||
import Plutarch.Api.V1 (
|
import Plutarch.Api.V1 (
|
||||||
AmountGuarantees (Positive),
|
AmountGuarantees (Positive),
|
||||||
KeyGuarantees (Sorted),
|
KeyGuarantees (Sorted),
|
||||||
|
|
@ -28,8 +27,6 @@ import Plutarch.Api.V1 (
|
||||||
PValue,
|
PValue,
|
||||||
ptuple,
|
ptuple,
|
||||||
)
|
)
|
||||||
import Plutarch.Internal (punsafeCoerce)
|
|
||||||
|
|
||||||
import Plutarch.Api.V1.ScriptContext (pfindTxInByTxOutRef)
|
import Plutarch.Api.V1.ScriptContext (pfindTxInByTxOutRef)
|
||||||
import "plutarch" Plutarch.Api.V1.Value (pnormalize)
|
import "plutarch" Plutarch.Api.V1.Value (pnormalize)
|
||||||
import Plutarch.DataRepr (
|
import Plutarch.DataRepr (
|
||||||
|
|
@ -38,6 +35,7 @@ import Plutarch.DataRepr (
|
||||||
PIsDataReprInstances (..),
|
PIsDataReprInstances (..),
|
||||||
)
|
)
|
||||||
import Plutarch.Extra.TermCont (pguardC, pletC, pmatchC)
|
import Plutarch.Extra.TermCont (pguardC, pletC, pmatchC)
|
||||||
|
import Plutarch.Internal (punsafeCoerce)
|
||||||
import Plutarch.Lift (PConstantDecl, PUnsafeLiftDecl (..))
|
import Plutarch.Lift (PConstantDecl, PUnsafeLiftDecl (..))
|
||||||
import Plutarch.TryFrom (PTryFrom (..))
|
import Plutarch.TryFrom (PTryFrom (..))
|
||||||
import PlutusLedgerApi.V1.Credential (Credential)
|
import PlutusLedgerApi.V1.Credential (Credential)
|
||||||
|
|
@ -46,9 +44,11 @@ import PlutusTx qualified
|
||||||
|
|
||||||
{- | Datum that encodes behavior of Treasury Withdrawal effect.
|
{- | Datum that encodes behavior of Treasury Withdrawal effect.
|
||||||
|
|
||||||
Note: This Datum acts like a "predefined redeemer". Which is to say that
|
Note: This Datum acts like a "predefined redeemer". Which is to say that
|
||||||
it encodes the properties a redeemer would, but is locked in-place until
|
it encodes the properties a redeemer would, but is locked in-place until
|
||||||
spend.
|
spend.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
-}
|
-}
|
||||||
data TreasuryWithdrawalDatum = TreasuryWithdrawalDatum
|
data TreasuryWithdrawalDatum = TreasuryWithdrawalDatum
|
||||||
{ receivers :: [(Credential, Value)]
|
{ receivers :: [(Credential, Value)]
|
||||||
|
|
@ -56,13 +56,27 @@ data TreasuryWithdrawalDatum = TreasuryWithdrawalDatum
|
||||||
, treasuries :: [Credential]
|
, treasuries :: [Credential]
|
||||||
-- ^ What Credentials is spending from legal.
|
-- ^ What Credentials is spending from legal.
|
||||||
}
|
}
|
||||||
deriving stock (Show, GHC.Generic)
|
deriving stock
|
||||||
deriving anyclass (Generic)
|
( -- | @since 0.1.0
|
||||||
|
Show
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
GHC.Generic
|
||||||
|
)
|
||||||
|
deriving anyclass
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
Generic
|
||||||
|
)
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
PlutusTx.makeLift ''TreasuryWithdrawalDatum
|
PlutusTx.makeLift ''TreasuryWithdrawalDatum
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
PlutusTx.makeIsDataIndexed ''TreasuryWithdrawalDatum [('TreasuryWithdrawalDatum, 0)]
|
PlutusTx.makeIsDataIndexed ''TreasuryWithdrawalDatum [('TreasuryWithdrawalDatum, 0)]
|
||||||
|
|
||||||
-- | Haskell-level version of 'TreasuryWithdrawalDatum'.
|
{- | Haskell-level version of 'TreasuryWithdrawalDatum'.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
newtype PTreasuryWithdrawalDatum (s :: S)
|
newtype PTreasuryWithdrawalDatum (s :: S)
|
||||||
= PTreasuryWithdrawalDatum
|
= PTreasuryWithdrawalDatum
|
||||||
( Term
|
( Term
|
||||||
|
|
@ -73,20 +87,37 @@ newtype PTreasuryWithdrawalDatum (s :: S)
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
deriving stock (GHC.Generic)
|
deriving stock
|
||||||
deriving anyclass (Generic, PIsDataRepr)
|
( -- | @since 0.1.0
|
||||||
|
GHC.Generic
|
||||||
|
)
|
||||||
|
deriving anyclass
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
Generic
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PIsDataRepr
|
||||||
|
)
|
||||||
deriving
|
deriving
|
||||||
(PlutusType, PIsData, PDataFields)
|
( -- | @since 0.1.0
|
||||||
|
PlutusType
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PIsData
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PDataFields
|
||||||
|
)
|
||||||
via PIsDataReprInstances PTreasuryWithdrawalDatum
|
via PIsDataReprInstances PTreasuryWithdrawalDatum
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
instance PUnsafeLiftDecl PTreasuryWithdrawalDatum where
|
instance PUnsafeLiftDecl PTreasuryWithdrawalDatum where
|
||||||
type PLifted PTreasuryWithdrawalDatum = TreasuryWithdrawalDatum
|
type PLifted PTreasuryWithdrawalDatum = TreasuryWithdrawalDatum
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
deriving via
|
deriving via
|
||||||
(DerivePConstantViaData TreasuryWithdrawalDatum PTreasuryWithdrawalDatum)
|
(DerivePConstantViaData TreasuryWithdrawalDatum PTreasuryWithdrawalDatum)
|
||||||
instance
|
instance
|
||||||
(PConstantDecl TreasuryWithdrawalDatum)
|
(PConstantDecl TreasuryWithdrawalDatum)
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
instance PTryFrom PData (PAsData PTreasuryWithdrawalDatum) where
|
instance PTryFrom PData (PAsData PTreasuryWithdrawalDatum) where
|
||||||
type PTryFromExcess PData (PAsData PTreasuryWithdrawalDatum) = Const ()
|
type PTryFromExcess PData (PAsData PTreasuryWithdrawalDatum) = Const ()
|
||||||
ptryFrom' opq cont =
|
ptryFrom' opq cont =
|
||||||
|
|
@ -101,12 +132,17 @@ instance PTryFrom PData (PAsData PTreasuryWithdrawalDatum) where
|
||||||
The validator does not accept any Redeemer as all "parameters" are provided
|
The validator does not accept any Redeemer as all "parameters" are provided
|
||||||
via encoded Datum.
|
via encoded Datum.
|
||||||
|
|
||||||
Note:
|
NOTE: It should check...
|
||||||
It should check...
|
|
||||||
1. Transaction outputs should contain all of what Datum specified
|
1. Transaction outputs should contain all of what Datum specified
|
||||||
2. Left over assets should be redirected back to Treasury
|
|
||||||
|
2. Left over assets should be redirected back to Treasury
|
||||||
|
|
||||||
It can be more flexiable over...
|
It can be more flexiable over...
|
||||||
|
|
||||||
- The number of outputs themselves
|
- The number of outputs themselves
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
-}
|
-}
|
||||||
treasuryWithdrawalValidator :: forall {s :: S}. CurrencySymbol -> Term s PValidator
|
treasuryWithdrawalValidator :: forall {s :: S}. CurrencySymbol -> Term s PValidator
|
||||||
treasuryWithdrawalValidator currSymbol = makeEffect currSymbol $
|
treasuryWithdrawalValidator currSymbol = makeEffect currSymbol $
|
||||||
|
|
|
||||||
|
|
@ -23,15 +23,6 @@ module Agora.Governor (
|
||||||
governorDatumValid,
|
governorDatumValid,
|
||||||
) where
|
) where
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
import Control.Applicative (Const)
|
|
||||||
import Data.Tagged (Tagged (..))
|
|
||||||
import GHC.Generics qualified as GHC
|
|
||||||
import Generics.SOP (Generic, I (I))
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
import Agora.Proposal (
|
import Agora.Proposal (
|
||||||
PProposalId (..),
|
PProposalId (..),
|
||||||
PProposalThresholds (..),
|
PProposalThresholds (..),
|
||||||
|
|
@ -45,9 +36,10 @@ import Agora.Proposal.Time (
|
||||||
ProposalTimingConfig,
|
ProposalTimingConfig,
|
||||||
)
|
)
|
||||||
import Agora.SafeMoney (GTTag)
|
import Agora.SafeMoney (GTTag)
|
||||||
|
import Control.Applicative (Const)
|
||||||
--------------------------------------------------------------------------------
|
import Data.Tagged (Tagged (..))
|
||||||
|
import GHC.Generics qualified as GHC
|
||||||
|
import Generics.SOP (Generic, I (I))
|
||||||
import Plutarch.DataRepr (
|
import Plutarch.DataRepr (
|
||||||
DerivePConstantViaData (..),
|
DerivePConstantViaData (..),
|
||||||
PDataFields,
|
PDataFields,
|
||||||
|
|
@ -59,16 +51,16 @@ import Plutarch.Lift (PConstantDecl, PUnsafeLiftDecl (..))
|
||||||
import Plutarch.SafeMoney (PDiscrete (..))
|
import Plutarch.SafeMoney (PDiscrete (..))
|
||||||
import Plutarch.TryFrom (PTryFrom (..))
|
import Plutarch.TryFrom (PTryFrom (..))
|
||||||
import Plutarch.Unsafe (punsafeCoerce)
|
import Plutarch.Unsafe (punsafeCoerce)
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
import PlutusLedgerApi.V1 (TxOutRef)
|
import PlutusLedgerApi.V1 (TxOutRef)
|
||||||
import PlutusLedgerApi.V1.Value (AssetClass (..))
|
import PlutusLedgerApi.V1.Value (AssetClass (..))
|
||||||
import PlutusTx qualified
|
import PlutusTx qualified
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
-- | Datum for the Governor script.
|
{- | Datum for the Governor script.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
data GovernorDatum = GovernorDatum
|
data GovernorDatum = GovernorDatum
|
||||||
{ proposalThresholds :: ProposalThresholds
|
{ proposalThresholds :: ProposalThresholds
|
||||||
-- ^ Gets copied over upon creation of a 'Agora.Proposal.ProposalDatum'.
|
-- ^ Gets copied over upon creation of a 'Agora.Proposal.ProposalDatum'.
|
||||||
|
|
@ -82,6 +74,7 @@ data GovernorDatum = GovernorDatum
|
||||||
}
|
}
|
||||||
deriving stock (Show, GHC.Generic)
|
deriving stock (Show, GHC.Generic)
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
PlutusTx.makeIsDataIndexed ''GovernorDatum [('GovernorDatum, 0)]
|
PlutusTx.makeIsDataIndexed ''GovernorDatum [('GovernorDatum, 0)]
|
||||||
|
|
||||||
{- | Redeemer for Governor script. The governor has two primary
|
{- | Redeemer for Governor script. The governor has two primary
|
||||||
|
|
@ -91,6 +84,8 @@ PlutusTx.makeIsDataIndexed ''GovernorDatum [('GovernorDatum, 0)]
|
||||||
2. The gating of minting authority tokens.
|
2. The gating of minting authority tokens.
|
||||||
|
|
||||||
Parameters of the governor can also be mutated by an effect.
|
Parameters of the governor can also be mutated by an effect.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
-}
|
-}
|
||||||
data GovernorRedeemer
|
data GovernorRedeemer
|
||||||
= -- | Checks that a proposal was created lawfully, and allows it.
|
= -- | Checks that a proposal was created lawfully, and allows it.
|
||||||
|
|
@ -102,6 +97,7 @@ data GovernorRedeemer
|
||||||
MutateGovernor
|
MutateGovernor
|
||||||
deriving stock (Show, GHC.Generic)
|
deriving stock (Show, GHC.Generic)
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
PlutusTx.makeIsDataIndexed
|
PlutusTx.makeIsDataIndexed
|
||||||
''GovernorRedeemer
|
''GovernorRedeemer
|
||||||
[ ('CreateProposal, 0)
|
[ ('CreateProposal, 0)
|
||||||
|
|
@ -109,7 +105,10 @@ PlutusTx.makeIsDataIndexed
|
||||||
, ('MutateGovernor, 2)
|
, ('MutateGovernor, 2)
|
||||||
]
|
]
|
||||||
|
|
||||||
-- | Parameters for creating Governor scripts.
|
{- | Parameters for creating Governor scripts.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
data Governor = Governor
|
data Governor = Governor
|
||||||
{ gstOutRef :: TxOutRef
|
{ gstOutRef :: TxOutRef
|
||||||
-- ^ Referenced utxo will be spent to mint the GST.
|
-- ^ Referenced utxo will be spent to mint the GST.
|
||||||
|
|
@ -123,7 +122,10 @@ data Governor = Governor
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
-- | Plutarch-level datum for the Governor script.
|
{- | Plutarch-level datum for the Governor script.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
newtype PGovernorDatum (s :: S) = PGovernorDatum
|
newtype PGovernorDatum (s :: S) = PGovernorDatum
|
||||||
{ getGovernorDatum ::
|
{ getGovernorDatum ::
|
||||||
Term
|
Term
|
||||||
|
|
@ -136,53 +138,104 @@ newtype PGovernorDatum (s :: S) = PGovernorDatum
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
deriving stock (GHC.Generic)
|
deriving stock
|
||||||
deriving anyclass (Generic)
|
( -- | @since 0.1.0
|
||||||
deriving anyclass (PIsDataRepr)
|
GHC.Generic
|
||||||
|
)
|
||||||
|
deriving anyclass
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
Generic
|
||||||
|
)
|
||||||
|
deriving anyclass
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
PIsDataRepr
|
||||||
|
)
|
||||||
deriving
|
deriving
|
||||||
(PlutusType, PIsData, PDataFields, PEq)
|
( -- | @since 0.1.0
|
||||||
|
PlutusType
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PIsData
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PDataFields
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PEq
|
||||||
|
)
|
||||||
via PIsDataReprInstances PGovernorDatum
|
via PIsDataReprInstances PGovernorDatum
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
instance PUnsafeLiftDecl PGovernorDatum where type PLifted PGovernorDatum = GovernorDatum
|
instance PUnsafeLiftDecl PGovernorDatum where type PLifted PGovernorDatum = GovernorDatum
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
deriving via (DerivePConstantViaData GovernorDatum PGovernorDatum) instance (PConstantDecl GovernorDatum)
|
deriving via (DerivePConstantViaData GovernorDatum PGovernorDatum) instance (PConstantDecl GovernorDatum)
|
||||||
|
|
||||||
-- FIXME: derive this via 'PIsDataReprInstances'
|
-- FIXME: derive this via 'PIsDataReprInstances'
|
||||||
-- Blocked by: PProposalThresholds
|
-- Blocked by: PProposalThresholds
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
instance PTryFrom PData (PAsData PGovernorDatum) where
|
instance PTryFrom PData (PAsData PGovernorDatum) where
|
||||||
type PTryFromExcess PData (PAsData PGovernorDatum) = Const ()
|
type PTryFromExcess PData (PAsData PGovernorDatum) = Const ()
|
||||||
|
|
||||||
ptryFrom' d k = k (punsafeCoerce d, ())
|
ptryFrom' d k = k (punsafeCoerce d, ())
|
||||||
|
|
||||||
-- | Plutarch-level version of 'GovernorRedeemer'.
|
{- | Plutarch-level version of 'GovernorRedeemer'.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
data PGovernorRedeemer (s :: S)
|
data PGovernorRedeemer (s :: S)
|
||||||
= PCreateProposal (Term s (PDataRecord '[]))
|
= PCreateProposal (Term s (PDataRecord '[]))
|
||||||
| PMintGATs (Term s (PDataRecord '[]))
|
| PMintGATs (Term s (PDataRecord '[]))
|
||||||
| PMutateGovernor (Term s (PDataRecord '[]))
|
| PMutateGovernor (Term s (PDataRecord '[]))
|
||||||
deriving stock (GHC.Generic)
|
deriving stock
|
||||||
deriving anyclass (Generic)
|
( -- | @since 0.1.0
|
||||||
deriving anyclass (PIsDataRepr)
|
GHC.Generic
|
||||||
|
)
|
||||||
|
deriving anyclass
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
Generic
|
||||||
|
)
|
||||||
|
deriving anyclass
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
PIsDataRepr
|
||||||
|
)
|
||||||
deriving
|
deriving
|
||||||
(PlutusType, PIsData)
|
( -- | @since 0.1.0
|
||||||
|
PlutusType
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PIsData
|
||||||
|
)
|
||||||
via PIsDataReprInstances PGovernorRedeemer
|
via PIsDataReprInstances PGovernorRedeemer
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
instance PUnsafeLiftDecl PGovernorRedeemer where type PLifted PGovernorRedeemer = GovernorRedeemer
|
instance PUnsafeLiftDecl PGovernorRedeemer where type PLifted PGovernorRedeemer = GovernorRedeemer
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
deriving via (DerivePConstantViaData GovernorRedeemer PGovernorRedeemer) instance (PConstantDecl GovernorRedeemer)
|
deriving via (DerivePConstantViaData GovernorRedeemer PGovernorRedeemer) instance (PConstantDecl GovernorRedeemer)
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
deriving via PAsData (PIsDataReprInstances PGovernorRedeemer) instance PTryFrom PData (PAsData PGovernorRedeemer)
|
deriving via PAsData (PIsDataReprInstances PGovernorRedeemer) instance PTryFrom PData (PAsData PGovernorRedeemer)
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
-- | Plutrach version of 'getNextProposalId'.
|
{- | Plutrach version of 'getNextProposalId'.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
pgetNextProposalId :: Term s (PProposalId :--> PProposalId)
|
pgetNextProposalId :: Term s (PProposalId :--> PProposalId)
|
||||||
pgetNextProposalId = phoistAcyclic $ plam $ \(pto -> pid) -> pcon $ PProposalId $ pid + 1
|
pgetNextProposalId = phoistAcyclic $ plam $ \(pto -> pid) -> pcon $ PProposalId $ pid + 1
|
||||||
|
|
||||||
-- | Get next proposal id.
|
{- | Get next proposal id.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
getNextProposalId :: ProposalId -> ProposalId
|
getNextProposalId :: ProposalId -> ProposalId
|
||||||
getNextProposalId (ProposalId pid) = ProposalId $ pid + 1
|
getNextProposalId (ProposalId pid) = ProposalId $ pid + 1
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
-- | Check whether a particular 'PGovernorDatum' is well-formed.
|
{- | Check whether a particular 'PGovernorDatum' is well-formed.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
governorDatumValid :: Term s (PGovernorDatum :--> PBool)
|
governorDatumValid :: Term s (PGovernorDatum :--> PBool)
|
||||||
governorDatumValid = phoistAcyclic $
|
governorDatumValid = phoistAcyclic $
|
||||||
plam $ \datum -> unTermCont $ do
|
plam $ \datum -> unTermCont $ do
|
||||||
|
|
|
||||||
|
|
@ -154,6 +154,8 @@ import PlutusLedgerApi.V1.Value (
|
||||||
|
|
||||||
NOTE: It's user's responsibility to make sure the token is sent to the corresponding governor validator.
|
NOTE: It's user's responsibility to make sure the token is sent to the corresponding governor validator.
|
||||||
We /can't/ really check this in the policy, otherwise we create a cyclic reference issue.
|
We /can't/ really check this in the policy, otherwise we create a cyclic reference issue.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
-}
|
-}
|
||||||
governorPolicy :: Governor -> ClosedTerm PMintingPolicy
|
governorPolicy :: Governor -> ClosedTerm PMintingPolicy
|
||||||
governorPolicy gov =
|
governorPolicy gov =
|
||||||
|
|
@ -191,87 +193,89 @@ governorPolicy gov =
|
||||||
|
|
||||||
{- | Validator for Governors.
|
{- | Validator for Governors.
|
||||||
|
|
||||||
== Common checks
|
== Common checks
|
||||||
|
|
||||||
The validator always ensures:
|
The validator always ensures:
|
||||||
|
|
||||||
- The UTXO which holds the GST must be spent.
|
- The UTXO which holds the GST must be spent.
|
||||||
- The GST always stays at the validator's address.
|
- The GST always stays at the validator's address.
|
||||||
- The new state UTXO has a valid datum of type 'Agora.Governor.GovernorDatum'.
|
- The new state UTXO has a valid datum of type 'Agora.Governor.GovernorDatum'.
|
||||||
|
|
||||||
== Creating a Proposal
|
== Creating a Proposal
|
||||||
|
|
||||||
When the redeemer is 'Agora.Governor.CreateProposal', the script will check:
|
When the redeemer is 'Agora.Governor.CreateProposal', the script will check:
|
||||||
|
|
||||||
- For governor's state datum:
|
- For governor's state datum:
|
||||||
|
|
||||||
* 'Agora.Governor.nextProposalId' is advanced.
|
* 'Agora.Governor.nextProposalId' is advanced.
|
||||||
* Nothing is changed other that that.
|
* Nothing is changed other that that.
|
||||||
|
|
||||||
- Exactly one stake (the "input stake") must be provided in the input:
|
- Exactly one stake (the "input stake") must be provided in the input:
|
||||||
* At least 'Agora.Stake.stackedAmount' of GT must be spent in the transaction.
|
* At least 'Agora.Stake.stackedAmount' of GT must be spent in the transaction.
|
||||||
* The transaction must be signed by the stake owner.
|
* The transaction must be signed by the stake owner.
|
||||||
|
|
||||||
- Exactly one new proposal state token is minted.
|
- Exactly one new proposal state token is minted.
|
||||||
- An UTXO which holds the newly minted proposal state token is sent to the proposal validator.
|
- An UTXO which holds the newly minted proposal state token is sent to the proposal validator.
|
||||||
This UTXO must have a valid datum of type 'Agora.Proposal.ProposalDatum', the datum must:
|
This UTXO must have a valid datum of type 'Agora.Proposal.ProposalDatum', the datum must:
|
||||||
|
|
||||||
* Copy its id and thresholds from the governor's state.
|
* Copy its id and thresholds from the governor's state.
|
||||||
* Have status set to 'Proposal.Draft'.
|
* Have status set to 'Proposal.Draft'.
|
||||||
* Have zero votes.
|
* Have zero votes.
|
||||||
* Have exactly one cosigner - the stake owner
|
* Have exactly one cosigner - the stake owner
|
||||||
|
|
||||||
- An UTXO which holds the stake state token is sent back to the stake validator.
|
- An UTXO which holds the stake state token is sent back to the stake validator.
|
||||||
This UTXO must have a valid datum of type 'Agora.Stake.StakeDatum':
|
This UTXO must have a valid datum of type 'Agora.Stake.StakeDatum':
|
||||||
|
|
||||||
* The 'Agora.Stake.stakedAmount' and 'Agora.Stake.owner' should not be changed,
|
* The 'Agora.Stake.stakedAmount' and 'Agora.Stake.owner' should not be changed,
|
||||||
comparing to the input stake.
|
comparing to the input stake.
|
||||||
* The new proposal locks must be appended to the 'Agora.Stake.lockedBy'.
|
* The new proposal locks must be appended to the 'Agora.Stake.lockedBy'.
|
||||||
|
|
||||||
== Minting GATs
|
== Minting GATs
|
||||||
|
|
||||||
When the redeemer is 'Agora.Governor.MintGATs', the script will check:
|
When the redeemer is 'Agora.Governor.MintGATs', the script will check:
|
||||||
|
|
||||||
- Governor's state is not changed.
|
- Governor's state is not changed.
|
||||||
- Exactly only one proposal is in the inputs. Let's call this the /input proposal/.
|
- Exactly only one proposal is in the inputs. Let's call this the /input proposal/.
|
||||||
- The proposal is in the 'Proposal.Executable' state.
|
- The proposal is in the 'Proposal.Executable' state.
|
||||||
|
|
||||||
NOTE: The input proposal is found by looking for the UTXO with a proposal state token in the inputs.
|
NOTE: The input proposal is found by looking for the UTXO with a proposal state token in the inputs.
|
||||||
|
|
||||||
=== Effect Group Selection
|
=== Effect Group Selection
|
||||||
|
|
||||||
Currently a proposal can have two or more than two options to vote on,
|
Currently a proposal can have two or more than two options to vote on,
|
||||||
meaning that it can contains two or more effect groups,
|
meaning that it can contains two or more effect groups,
|
||||||
according to [#39](https://github.com/Liqwid-Labs/agora/issues/39).
|
according to [#39](https://github.com/Liqwid-Labs/agora/issues/39).
|
||||||
|
|
||||||
Either way, the shapes of 'Proposal.votes' and 'Proposal.effects' should be the same.
|
Either way, the shapes of 'Proposal.votes' and 'Proposal.effects' should be the same.
|
||||||
This is checked by 'Proposal.proposalDatumValid'.
|
This is checked by 'Proposal.proposalDatumValid'.
|
||||||
|
|
||||||
The script will look at the the 'Proposal.votes' to determine which group has the highest votes,
|
The script will look at the the 'Proposal.votes' to determine which group has the highest votes,
|
||||||
said group shoud be executed.
|
said group shoud be executed.
|
||||||
|
|
||||||
During the process, minimum votes requirement will also be enforced.
|
During the process, minimum votes requirement will also be enforced.
|
||||||
|
|
||||||
Next, the script will:
|
Next, the script will:
|
||||||
|
|
||||||
- Ensure that for every effect in the said effect group,
|
- Ensure that for every effect in the said effect group,
|
||||||
exactly one valid GAT is minted and sent to the effect.
|
exactly one valid GAT is minted and sent to the effect.
|
||||||
- The amount of GAT minted in the transaction should be equal to the number of effects.
|
- The amount of GAT minted in the transaction should be equal to the number of effects.
|
||||||
- A new UTXO is sent to the proposal validator, this UTXO should:
|
- A new UTXO is sent to the proposal validator, this UTXO should:
|
||||||
|
|
||||||
* Include the one proposal state token.
|
* Include the one proposal state token.
|
||||||
* Have a valid datum of type 'Proposal.ProposalDatum'.
|
* Have a valid datum of type 'Proposal.ProposalDatum'.
|
||||||
This datum should be as same as the one of the input proposal,
|
This datum should be as same as the one of the input proposal,
|
||||||
except its status should be 'Proposal.Finished'.
|
except its status should be 'Proposal.Finished'.
|
||||||
|
|
||||||
== Changing the State
|
== Changing the State
|
||||||
|
|
||||||
Redeemer 'Agora.Governor.MutateGovernor' allows the state datum to be changed by an external effect.
|
Redeemer 'Agora.Governor.MutateGovernor' allows the state datum to be changed by an external effect.
|
||||||
|
|
||||||
In this case, the script will check
|
In this case, the script will check
|
||||||
|
|
||||||
- Exactly one GAT is burnt in the transaction.
|
- Exactly one GAT is burnt in the transaction.
|
||||||
- Said GAT is tagged by the effect.
|
- Said GAT is tagged by the effect.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
-}
|
-}
|
||||||
governorValidator :: Governor -> ClosedTerm PValidator
|
governorValidator :: Governor -> ClosedTerm PValidator
|
||||||
governorValidator gov =
|
governorValidator gov =
|
||||||
|
|
@ -718,21 +722,30 @@ governorValidator gov =
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
-- | Get the 'CurrencySymbol' of GST.
|
{- | Get the 'CurrencySymbol' of GST.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
governorSTSymbolFromGovernor :: Governor -> CurrencySymbol
|
governorSTSymbolFromGovernor :: Governor -> CurrencySymbol
|
||||||
governorSTSymbolFromGovernor gov = mintingPolicySymbol policy
|
governorSTSymbolFromGovernor gov = mintingPolicySymbol policy
|
||||||
where
|
where
|
||||||
policy :: MintingPolicy
|
policy :: MintingPolicy
|
||||||
policy = mkMintingPolicy $ governorPolicy gov
|
policy = mkMintingPolicy $ governorPolicy gov
|
||||||
|
|
||||||
-- | Get the 'AssetClass' of GST.
|
{- | Get the 'AssetClass' of GST.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
governorSTAssetClassFromGovernor :: Governor -> AssetClass
|
governorSTAssetClassFromGovernor :: Governor -> AssetClass
|
||||||
governorSTAssetClassFromGovernor gov = AssetClass (symbol, "")
|
governorSTAssetClassFromGovernor gov = AssetClass (symbol, "")
|
||||||
where
|
where
|
||||||
symbol :: CurrencySymbol
|
symbol :: CurrencySymbol
|
||||||
symbol = governorSTSymbolFromGovernor gov
|
symbol = governorSTSymbolFromGovernor gov
|
||||||
|
|
||||||
-- | Get the 'CurrencySymbol' of the proposal state token.
|
{- | Get the 'CurrencySymbol' of the proposal state token.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
proposalSTSymbolFromGovernor :: Governor -> CurrencySymbol
|
proposalSTSymbolFromGovernor :: Governor -> CurrencySymbol
|
||||||
proposalSTSymbolFromGovernor gov = symbol
|
proposalSTSymbolFromGovernor gov = symbol
|
||||||
where
|
where
|
||||||
|
|
@ -740,13 +753,19 @@ proposalSTSymbolFromGovernor gov = symbol
|
||||||
policy = mkMintingPolicy $ proposalPolicy gstAC
|
policy = mkMintingPolicy $ proposalPolicy gstAC
|
||||||
symbol = mintingPolicySymbol policy
|
symbol = mintingPolicySymbol policy
|
||||||
|
|
||||||
-- | Get the 'AssetClass' of the proposal state token.
|
{- | Get the 'AssetClass' of the proposal state token.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
proposalSTAssetClassFromGovernor :: Governor -> AssetClass
|
proposalSTAssetClassFromGovernor :: Governor -> AssetClass
|
||||||
proposalSTAssetClassFromGovernor gov = AssetClass (symbol, "")
|
proposalSTAssetClassFromGovernor gov = AssetClass (symbol, "")
|
||||||
where
|
where
|
||||||
symbol = proposalSTSymbolFromGovernor gov
|
symbol = proposalSTSymbolFromGovernor gov
|
||||||
|
|
||||||
-- | Get the 'CurrencySymbol' of the stake token/
|
{- | Get the 'CurrencySymbol' of the stake token/
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
stakeSTSymbolFromGovernor :: Governor -> CurrencySymbol
|
stakeSTSymbolFromGovernor :: Governor -> CurrencySymbol
|
||||||
stakeSTSymbolFromGovernor gov = mintingPolicySymbol policy
|
stakeSTSymbolFromGovernor gov = mintingPolicySymbol policy
|
||||||
where
|
where
|
||||||
|
|
@ -756,6 +775,8 @@ stakeSTSymbolFromGovernor gov = mintingPolicySymbol policy
|
||||||
|
|
||||||
Note that the token is tagged with the hash of the stake validator.
|
Note that the token is tagged with the hash of the stake validator.
|
||||||
See 'Agora.Stake.Script.stakePolicy'.
|
See 'Agora.Stake.Script.stakePolicy'.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
-}
|
-}
|
||||||
stakeSTAssetClassFromGovernor :: Governor -> AssetClass
|
stakeSTAssetClassFromGovernor :: Governor -> AssetClass
|
||||||
stakeSTAssetClassFromGovernor gov = AssetClass (symbol, tokenName)
|
stakeSTAssetClassFromGovernor gov = AssetClass (symbol, tokenName)
|
||||||
|
|
@ -765,20 +786,29 @@ stakeSTAssetClassFromGovernor gov = AssetClass (symbol, tokenName)
|
||||||
-- Tag with the address where the token is being sent to.
|
-- Tag with the address where the token is being sent to.
|
||||||
tokenName = validatorHashToTokenName $ stakeValidatorHashFromGovernor gov
|
tokenName = validatorHashToTokenName $ stakeValidatorHashFromGovernor gov
|
||||||
|
|
||||||
-- | Get the 'Stake' parameter, given the 'Governor' parameter.
|
{- | Get the 'Stake' parameter, given the 'Governor' parameter.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
stakeFromGovernor :: Governor -> Stake
|
stakeFromGovernor :: Governor -> Stake
|
||||||
stakeFromGovernor gov =
|
stakeFromGovernor gov =
|
||||||
Stake gov.gtClassRef $
|
Stake gov.gtClassRef $
|
||||||
proposalSTAssetClassFromGovernor gov
|
proposalSTAssetClassFromGovernor gov
|
||||||
|
|
||||||
-- | Get the hash of 'Agora.Stake.Script.stakePolicy'.
|
{- | Get the hash of 'Agora.Stake.Script.stakePolicy'.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
stakeValidatorHashFromGovernor :: Governor -> ValidatorHash
|
stakeValidatorHashFromGovernor :: Governor -> ValidatorHash
|
||||||
stakeValidatorHashFromGovernor gov = validatorHash validator
|
stakeValidatorHashFromGovernor gov = validatorHash validator
|
||||||
where
|
where
|
||||||
params = stakeFromGovernor gov
|
params = stakeFromGovernor gov
|
||||||
validator = mkValidator $ stakeValidator params
|
validator = mkValidator $ stakeValidator params
|
||||||
|
|
||||||
-- | Get the 'Proposal' parameter, given the 'Governor' parameter.
|
{- | Get the 'Proposal' parameter, given the 'Governor' parameter.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
proposalFromGovernor :: Governor -> Proposal
|
proposalFromGovernor :: Governor -> Proposal
|
||||||
proposalFromGovernor gov = Proposal gstAC sstAC mc
|
proposalFromGovernor gov = Proposal gstAC sstAC mc
|
||||||
where
|
where
|
||||||
|
|
@ -786,24 +816,36 @@ proposalFromGovernor gov = Proposal gstAC sstAC mc
|
||||||
mc = gov.maximumCosigners
|
mc = gov.maximumCosigners
|
||||||
sstAC = stakeSTAssetClassFromGovernor gov
|
sstAC = stakeSTAssetClassFromGovernor gov
|
||||||
|
|
||||||
-- | Get the hash of 'Agora.Proposal.proposalPolicy'.
|
{- | Get the hash of 'Agora.Proposal.proposalPolicy'.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
proposalValidatorHashFromGovernor :: Governor -> ValidatorHash
|
proposalValidatorHashFromGovernor :: Governor -> ValidatorHash
|
||||||
proposalValidatorHashFromGovernor gov = validatorHash validator
|
proposalValidatorHashFromGovernor gov = validatorHash validator
|
||||||
where
|
where
|
||||||
params = proposalFromGovernor gov
|
params = proposalFromGovernor gov
|
||||||
validator = mkValidator $ proposalValidator params
|
validator = mkValidator $ proposalValidator params
|
||||||
|
|
||||||
-- | Get the hash of 'Agora.Proposal.proposalValidator'.
|
{- | Get the hash of 'Agora.Proposal.proposalValidator'.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
governorValidatorHash :: Governor -> ValidatorHash
|
governorValidatorHash :: Governor -> ValidatorHash
|
||||||
governorValidatorHash gov = validatorHash validator
|
governorValidatorHash gov = validatorHash validator
|
||||||
where
|
where
|
||||||
validator = mkValidator $ governorValidator gov
|
validator = mkValidator $ governorValidator gov
|
||||||
|
|
||||||
-- | Get the 'AuthorityToken' parameter given the 'Governor' parameter.
|
{- | Get the 'AuthorityToken' parameter given the 'Governor' parameter.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
authorityTokenFromGovernor :: Governor -> AuthorityToken
|
authorityTokenFromGovernor :: Governor -> AuthorityToken
|
||||||
authorityTokenFromGovernor gov = AuthorityToken $ governorSTAssetClassFromGovernor gov
|
authorityTokenFromGovernor gov = AuthorityToken $ governorSTAssetClassFromGovernor gov
|
||||||
|
|
||||||
-- | Get the 'CurrencySymbol' of the authority token.
|
{- | Get the 'CurrencySymbol' of the authority token.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
authorityTokenSymbolFromGovernor :: Governor -> CurrencySymbol
|
authorityTokenSymbolFromGovernor :: Governor -> CurrencySymbol
|
||||||
authorityTokenSymbolFromGovernor gov = mintingPolicySymbol policy
|
authorityTokenSymbolFromGovernor gov = mintingPolicySymbol policy
|
||||||
where
|
where
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,8 @@ module Agora.MultiSig (
|
||||||
MultiSig (..),
|
MultiSig (..),
|
||||||
) where
|
) where
|
||||||
|
|
||||||
|
import GHC.Generics qualified as GHC
|
||||||
|
import Generics.SOP (Generic, I (I))
|
||||||
import Plutarch.Api.V1 (
|
import Plutarch.Api.V1 (
|
||||||
PPubKeyHash,
|
PPubKeyHash,
|
||||||
PTxInfo (..),
|
PTxInfo (..),
|
||||||
|
|
@ -28,33 +30,42 @@ import Plutarch.Lift (
|
||||||
PLifted,
|
PLifted,
|
||||||
PUnsafeLiftDecl,
|
PUnsafeLiftDecl,
|
||||||
)
|
)
|
||||||
|
|
||||||
import PlutusLedgerApi.V1.Crypto (PubKeyHash)
|
import PlutusLedgerApi.V1.Crypto (PubKeyHash)
|
||||||
import PlutusTx qualified
|
import PlutusTx qualified
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
import GHC.Generics qualified as GHC
|
|
||||||
import Generics.SOP (Generic, I (I))
|
|
||||||
import Prelude
|
import Prelude
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
{- | A MultiSig represents a proof that a particular set of signatures
|
{- | A MultiSig represents a proof that a particular set of signatures
|
||||||
are present on a transaction.
|
are present on a transaction.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
-}
|
-}
|
||||||
data MultiSig = MultiSig
|
data MultiSig = MultiSig
|
||||||
{ keys :: [PubKeyHash]
|
{ keys :: [PubKeyHash]
|
||||||
-- ^ List of PubKeyHashes that must be present in the list of signatories.
|
-- ^ List of PubKeyHashes that must be present in the list of signatories.
|
||||||
, minSigs :: Integer
|
, minSigs :: Integer
|
||||||
}
|
}
|
||||||
deriving stock (GHC.Generic, Eq, Show)
|
deriving stock
|
||||||
deriving anyclass (Generic)
|
( -- | @since 0.1.0
|
||||||
|
GHC.Generic
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
Eq
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
Show
|
||||||
|
)
|
||||||
|
deriving anyclass
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
Generic
|
||||||
|
)
|
||||||
|
|
||||||
PlutusTx.makeLift ''MultiSig
|
PlutusTx.makeLift ''MultiSig
|
||||||
PlutusTx.unstableMakeIsData ''MultiSig
|
PlutusTx.unstableMakeIsData ''MultiSig
|
||||||
|
|
||||||
-- | Plutarch-level MultiSig
|
{- | Plutarch-level MultiSig
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
newtype PMultiSig (s :: S) = PMultiSig
|
newtype PMultiSig (s :: S) = PMultiSig
|
||||||
{ getMultiSig ::
|
{ getMultiSig ::
|
||||||
Term
|
Term
|
||||||
|
|
@ -65,25 +76,49 @@ newtype PMultiSig (s :: S) = PMultiSig
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
deriving stock (GHC.Generic)
|
deriving stock
|
||||||
deriving anyclass (Generic)
|
( -- | @since 0.1.0
|
||||||
deriving anyclass (PIsDataRepr)
|
GHC.Generic
|
||||||
|
)
|
||||||
|
deriving anyclass
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
Generic
|
||||||
|
)
|
||||||
|
deriving anyclass
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
PIsDataRepr
|
||||||
|
)
|
||||||
deriving
|
deriving
|
||||||
(PlutusType, PIsData, PDataFields)
|
( -- | @since 0.1.0
|
||||||
|
PlutusType
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PIsData
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PDataFields
|
||||||
|
)
|
||||||
via (PIsDataReprInstances PMultiSig)
|
via (PIsDataReprInstances PMultiSig)
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
instance PUnsafeLiftDecl PMultiSig where type PLifted PMultiSig = MultiSig
|
instance PUnsafeLiftDecl PMultiSig where type PLifted PMultiSig = MultiSig
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
deriving via (DerivePConstantViaData MultiSig PMultiSig) instance (PConstantDecl MultiSig)
|
deriving via (DerivePConstantViaData MultiSig PMultiSig) instance (PConstantDecl MultiSig)
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
-- | Check if a Haskell-level MultiSig signs this transaction.
|
{- | Check if a Haskell-level MultiSig signs this transaction.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
validatedByMultisig :: MultiSig -> Term s (PTxInfo :--> PBool)
|
validatedByMultisig :: MultiSig -> Term s (PTxInfo :--> PBool)
|
||||||
validatedByMultisig params =
|
validatedByMultisig params =
|
||||||
phoistAcyclic $
|
phoistAcyclic $
|
||||||
pvalidatedByMultisig # pconstant params
|
pvalidatedByMultisig # pconstant params
|
||||||
|
|
||||||
-- | Check if a Plutarch-level MultiSig signs this transaction.
|
{- | Check if a Plutarch-level MultiSig signs this transaction.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
pvalidatedByMultisig :: Term s (PMultiSig :--> PTxInfo :--> PBool)
|
pvalidatedByMultisig :: Term s (PMultiSig :--> PTxInfo :--> PBool)
|
||||||
pvalidatedByMultisig =
|
pvalidatedByMultisig =
|
||||||
phoistAcyclic $
|
phoistAcyclic $
|
||||||
|
|
|
||||||
|
|
@ -36,23 +36,14 @@ module Agora.Proposal (
|
||||||
pretractVotes,
|
pretractVotes,
|
||||||
) where
|
) where
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
import Agora.Proposal.Time (PProposalStartingTime, PProposalTimingConfig, ProposalStartingTime, ProposalTimingConfig)
|
||||||
|
import Agora.SafeMoney (GTTag)
|
||||||
|
import Agora.Utils (mustBePJust)
|
||||||
import Control.Applicative (Const)
|
import Control.Applicative (Const)
|
||||||
import Control.Arrow (first)
|
import Control.Arrow (first)
|
||||||
import Data.Tagged (Tagged)
|
import Data.Tagged (Tagged)
|
||||||
import GHC.Generics qualified as GHC
|
import GHC.Generics qualified as GHC
|
||||||
import Generics.SOP (Generic, I (I))
|
import Generics.SOP (Generic, I (I))
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
import PlutusLedgerApi.V1 (DatumHash, PubKeyHash, ValidatorHash)
|
|
||||||
import PlutusLedgerApi.V1.Value (AssetClass)
|
|
||||||
import PlutusTx qualified
|
|
||||||
import PlutusTx.AssocMap qualified as AssocMap
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
import Plutarch.Api.V1 (
|
import Plutarch.Api.V1 (
|
||||||
KeyGuarantees (Unsorted),
|
KeyGuarantees (Unsorted),
|
||||||
PDatumHash,
|
PDatumHash,
|
||||||
|
|
@ -73,12 +64,10 @@ import Plutarch.Lift (
|
||||||
import Plutarch.SafeMoney (PDiscrete)
|
import Plutarch.SafeMoney (PDiscrete)
|
||||||
import Plutarch.TryFrom (PTryFrom (PTryFromExcess, ptryFrom'))
|
import Plutarch.TryFrom (PTryFrom (PTryFromExcess, ptryFrom'))
|
||||||
import Plutarch.Unsafe (punsafeCoerce)
|
import Plutarch.Unsafe (punsafeCoerce)
|
||||||
|
import PlutusLedgerApi.V1 (DatumHash, PubKeyHash, ValidatorHash)
|
||||||
--------------------------------------------------------------------------------
|
import PlutusLedgerApi.V1.Value (AssetClass)
|
||||||
|
import PlutusTx qualified
|
||||||
import Agora.Proposal.Time (PProposalStartingTime, PProposalTimingConfig, ProposalStartingTime, ProposalTimingConfig)
|
import PlutusTx.AssocMap qualified as AssocMap
|
||||||
import Agora.SafeMoney (GTTag)
|
|
||||||
import Agora.Utils (mustBePJust)
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
-- Haskell-land
|
-- Haskell-land
|
||||||
|
|
@ -88,21 +77,55 @@ import Agora.Utils (mustBePJust)
|
||||||
The 100th proposal will be @'ProposalId' 99@. This counter lives
|
The 100th proposal will be @'ProposalId' 99@. This counter lives
|
||||||
in the 'Agora.Governor.Governor'. See 'Agora.Governor.nextProposalId', and
|
in the 'Agora.Governor.Governor'. See 'Agora.Governor.nextProposalId', and
|
||||||
'Agora.Governor.pgetNextProposalId'.
|
'Agora.Governor.pgetNextProposalId'.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
-}
|
-}
|
||||||
newtype ProposalId = ProposalId {proposalTag :: Integer}
|
newtype ProposalId = ProposalId {proposalTag :: Integer}
|
||||||
deriving newtype (PlutusTx.ToData, PlutusTx.FromData, PlutusTx.UnsafeFromData)
|
deriving newtype
|
||||||
deriving stock (Eq, Show, GHC.Generic)
|
( -- | @since 0.1.0
|
||||||
|
PlutusTx.ToData
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PlutusTx.FromData
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PlutusTx.UnsafeFromData
|
||||||
|
)
|
||||||
|
deriving stock
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
Eq
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
Show
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
GHC.Generic
|
||||||
|
)
|
||||||
|
|
||||||
{- | Encodes a result. Typically, for a Yes/No proposal, we encode it like this:
|
{- | Encodes a result. Typically, for a Yes/No proposal, we encode it like this:
|
||||||
|
|
||||||
@
|
@
|
||||||
"No" ~ 'ResultTag' 0
|
"No" ~ 'ResultTag' 0
|
||||||
"Yes" ~ 'ResultTag' 1
|
"Yes" ~ 'ResultTag' 1
|
||||||
@
|
@
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
-}
|
-}
|
||||||
newtype ResultTag = ResultTag {getResultTag :: Integer}
|
newtype ResultTag = ResultTag {getResultTag :: Integer}
|
||||||
deriving stock (Eq, Show, Ord, GHC.Generic)
|
deriving stock
|
||||||
deriving newtype (PlutusTx.ToData, PlutusTx.FromData, PlutusTx.UnsafeFromData)
|
( -- | @since 0.1.0
|
||||||
|
Eq
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
Show
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
Ord
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
GHC.Generic
|
||||||
|
)
|
||||||
|
deriving newtype
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
PlutusTx.ToData
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PlutusTx.FromData
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PlutusTx.UnsafeFromData
|
||||||
|
)
|
||||||
|
|
||||||
{- | The "status" of the proposal. This is only useful for state transitions that
|
{- | The "status" of the proposal. This is only useful for state transitions that
|
||||||
need to happen as a result of a transaction as opposed to time-based "periods".
|
need to happen as a result of a transaction as opposed to time-based "periods".
|
||||||
|
|
@ -111,6 +134,8 @@ newtype ResultTag = ResultTag {getResultTag :: Integer}
|
||||||
|
|
||||||
If the proposal is 'VotingReady', for instance, that doesn't necessarily
|
If the proposal is 'VotingReady', for instance, that doesn't necessarily
|
||||||
mean that voting is possible, as this also requires the timing to be right.
|
mean that voting is possible, as this also requires the timing to be right.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
-}
|
-}
|
||||||
data ProposalStatus
|
data ProposalStatus
|
||||||
= -- | A draft proposal represents a proposal that has yet to be realized.
|
= -- | A draft proposal represents a proposal that has yet to be realized.
|
||||||
|
|
@ -144,13 +169,23 @@ data ProposalStatus
|
||||||
--
|
--
|
||||||
-- TODO: The owner of the proposal may choose to reclaim their proposal.
|
-- TODO: The owner of the proposal may choose to reclaim their proposal.
|
||||||
Finished
|
Finished
|
||||||
deriving stock (Eq, Show, GHC.Generic)
|
deriving stock
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
Eq
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
Show
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
GHC.Generic
|
||||||
|
)
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
PlutusTx.makeIsDataIndexed ''ProposalStatus [('Draft, 0), ('VotingReady, 1), ('Locked, 2), ('Finished, 3)]
|
PlutusTx.makeIsDataIndexed ''ProposalStatus [('Draft, 0), ('VotingReady, 1), ('Locked, 2), ('Finished, 3)]
|
||||||
|
|
||||||
{- | The threshold values for various state transitions to happen.
|
{- | The threshold values for various state transitions to happen.
|
||||||
This data is stored centrally (in the 'Agora.Governor.Governor') and copied over
|
This data is stored centrally (in the 'Agora.Governor.Governor') and copied over
|
||||||
to 'Proposal's when they are created.
|
to 'Proposal's when they are created.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
-}
|
-}
|
||||||
data ProposalThresholds = ProposalThresholds
|
data ProposalThresholds = ProposalThresholds
|
||||||
{ execute :: Tagged GTTag Integer
|
{ execute :: Tagged GTTag Integer
|
||||||
|
|
@ -164,32 +199,62 @@ data ProposalThresholds = ProposalThresholds
|
||||||
-- ^ How much GT required to allow voting to happen.
|
-- ^ How much GT required to allow voting to happen.
|
||||||
-- (i.e. to move into 'VotingReady')
|
-- (i.e. to move into 'VotingReady')
|
||||||
}
|
}
|
||||||
deriving stock (Eq, Show, GHC.Generic)
|
deriving stock
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
Eq
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
Show
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
GHC.Generic
|
||||||
|
)
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
PlutusTx.makeIsDataIndexed ''ProposalThresholds [('ProposalThresholds, 0)]
|
PlutusTx.makeIsDataIndexed ''ProposalThresholds [('ProposalThresholds, 0)]
|
||||||
|
|
||||||
{- | Map which encodes the total tally for each result.
|
{- | Map which encodes the total tally for each result.
|
||||||
It's important that the "shape" is consistent with the shape of 'effects'.
|
It's important that the "shape" is consistent with the shape of 'effects'.
|
||||||
|
|
||||||
e.g. if the 'effects' field looks like the following:
|
e.g. if the 'effects' field looks like the following:
|
||||||
|
|
||||||
@[('ResultTag' 0, []), ('ResultTag' 1, [(vh, dh)])]@
|
@[('ResultTag' 0, []), ('ResultTag' 1, [(vh, dh)])]@
|
||||||
|
|
||||||
Then 'ProposalVotes' needs be of the shape:
|
Then 'ProposalVotes' needs be of the shape:
|
||||||
|
|
||||||
@[('ResultTag' 0, n), ('ResultTag' 1, m)]@
|
@[('ResultTag' 0, n), ('ResultTag' 1, m)]@
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
-}
|
-}
|
||||||
newtype ProposalVotes = ProposalVotes
|
newtype ProposalVotes = ProposalVotes
|
||||||
{ getProposalVotes :: AssocMap.Map ResultTag Integer
|
{ getProposalVotes :: AssocMap.Map ResultTag Integer
|
||||||
}
|
}
|
||||||
deriving newtype (PlutusTx.ToData, PlutusTx.FromData, PlutusTx.UnsafeFromData)
|
deriving newtype
|
||||||
deriving stock (Eq, Show, GHC.Generic)
|
( -- | @since 0.1.0
|
||||||
|
PlutusTx.ToData
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PlutusTx.FromData
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PlutusTx.UnsafeFromData
|
||||||
|
)
|
||||||
|
deriving stock
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
Eq
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
Show
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
GHC.Generic
|
||||||
|
)
|
||||||
|
|
||||||
-- | Create a 'ProposalVotes' that has the same shape as the 'effects' field.
|
{- | Create a 'ProposalVotes' that has the same shape as the 'effects' field.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
emptyVotesFor :: forall a. AssocMap.Map ResultTag a -> ProposalVotes
|
emptyVotesFor :: forall a. AssocMap.Map ResultTag a -> ProposalVotes
|
||||||
emptyVotesFor = ProposalVotes . AssocMap.mapWithKey (const . const 0)
|
emptyVotesFor = ProposalVotes . AssocMap.mapWithKey (const . const 0)
|
||||||
|
|
||||||
-- | Haskell-level datum for Proposal scripts.
|
{- | Haskell-level datum for Proposal scripts.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
data ProposalDatum = ProposalDatum
|
data ProposalDatum = ProposalDatum
|
||||||
{ proposalId :: ProposalId
|
{ proposalId :: ProposalId
|
||||||
-- ^ Identification of the proposal.
|
-- ^ Identification of the proposal.
|
||||||
|
|
@ -211,11 +276,21 @@ data ProposalDatum = ProposalDatum
|
||||||
, startingTime :: ProposalStartingTime
|
, startingTime :: ProposalStartingTime
|
||||||
-- ^ The time upon the creation of the proposal.
|
-- ^ The time upon the creation of the proposal.
|
||||||
}
|
}
|
||||||
deriving stock (Eq, Show, GHC.Generic)
|
deriving stock
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
Eq
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
Show
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
GHC.Generic
|
||||||
|
)
|
||||||
|
|
||||||
PlutusTx.makeIsDataIndexed ''ProposalDatum [('ProposalDatum, 0)]
|
PlutusTx.makeIsDataIndexed ''ProposalDatum [('ProposalDatum, 0)]
|
||||||
|
|
||||||
-- | Haskell-level redeemer for Proposal scripts.
|
{- | Haskell-level redeemer for Proposal scripts.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
data ProposalRedeemer
|
data ProposalRedeemer
|
||||||
= -- | Cast one or more votes towards a particular 'ResultTag'.
|
= -- | Cast one or more votes towards a particular 'ResultTag'.
|
||||||
Vote ResultTag
|
Vote ResultTag
|
||||||
|
|
@ -253,8 +328,16 @@ data ProposalRedeemer
|
||||||
-- If the proposal has run out of time for the current 'ProposalStatus', it will always be possible
|
-- If the proposal has run out of time for the current 'ProposalStatus', it will always be possible
|
||||||
-- to transition into 'Finished' status, because it has expired (and failed).
|
-- to transition into 'Finished' status, because it has expired (and failed).
|
||||||
AdvanceProposal
|
AdvanceProposal
|
||||||
deriving stock (Eq, Show, GHC.Generic)
|
deriving stock
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
Eq
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
Show
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
GHC.Generic
|
||||||
|
)
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
PlutusTx.makeIsDataIndexed
|
PlutusTx.makeIsDataIndexed
|
||||||
''ProposalRedeemer
|
''ProposalRedeemer
|
||||||
[ ('Vote, 0)
|
[ ('Vote, 0)
|
||||||
|
|
@ -263,23 +346,49 @@ PlutusTx.makeIsDataIndexed
|
||||||
, ('AdvanceProposal, 3)
|
, ('AdvanceProposal, 3)
|
||||||
]
|
]
|
||||||
|
|
||||||
-- | Parameters that identify the Proposal validator script.
|
{- | Parameters that identify the Proposal validator script.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
data Proposal = Proposal
|
data Proposal = Proposal
|
||||||
{ governorSTAssetClass :: AssetClass
|
{ governorSTAssetClass :: AssetClass
|
||||||
, stakeSTAssetClass :: AssetClass
|
, stakeSTAssetClass :: AssetClass
|
||||||
, maximumCosigners :: Integer
|
, maximumCosigners :: Integer
|
||||||
-- ^ Arbitrary limit for maximum amount of cosigners on a proposal.
|
-- ^ Arbitrary limit for maximum amount of cosigners on a proposal.
|
||||||
}
|
}
|
||||||
deriving stock (Show, Eq, GHC.Generic)
|
deriving stock
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
Show
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
Eq
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
GHC.Generic
|
||||||
|
)
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
-- Plutarch-land
|
-- Plutarch-land
|
||||||
|
|
||||||
-- | Plutarch-level version of 'ResultTag'.
|
{- | Plutarch-level version of 'ResultTag'.
|
||||||
newtype PResultTag (s :: S) = PResultTag (Term s PInteger)
|
|
||||||
deriving (PlutusType, PIsData, PEq, POrd) via (DerivePNewtype PResultTag PInteger)
|
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
|
newtype PResultTag (s :: S) = PResultTag (Term s PInteger)
|
||||||
|
deriving
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
PlutusType
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PIsData
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PEq
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
POrd
|
||||||
|
)
|
||||||
|
via (DerivePNewtype PResultTag PInteger)
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
instance PUnsafeLiftDecl PResultTag where type PLifted PResultTag = ResultTag
|
instance PUnsafeLiftDecl PResultTag where type PLifted PResultTag = ResultTag
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
deriving via
|
deriving via
|
||||||
(DerivePConstantViaNewtype ResultTag PResultTag PInteger)
|
(DerivePConstantViaNewtype ResultTag PResultTag PInteger)
|
||||||
instance
|
instance
|
||||||
|
|
@ -287,6 +396,8 @@ deriving via
|
||||||
|
|
||||||
-- FIXME: This instance and the one below, for 'PProposalId', should be derived.
|
-- FIXME: This instance and the one below, for 'PProposalId', should be derived.
|
||||||
-- Soon this will be possible through 'DerivePNewtype'.
|
-- Soon this will be possible through 'DerivePNewtype'.
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
instance PTryFrom PData (PAsData PResultTag) where
|
instance PTryFrom PData (PAsData PResultTag) where
|
||||||
type PTryFromExcess PData (PAsData PResultTag) = PTryFromExcess PData (PAsData PInteger)
|
type PTryFromExcess PData (PAsData PResultTag) = PTryFromExcess PData (PAsData PInteger)
|
||||||
ptryFrom' d k =
|
ptryFrom' d k =
|
||||||
|
|
@ -300,10 +411,24 @@ instance PTryFrom PData (PAsData PResultTag) where
|
||||||
-- Since 'PResultTag' is a simple newtype, their shape is the same.
|
-- Since 'PResultTag' is a simple newtype, their shape is the same.
|
||||||
k . first punsafeCoerce
|
k . first punsafeCoerce
|
||||||
|
|
||||||
-- | Plutarch-level version of 'PProposalId'.
|
{- | Plutarch-level version of 'PProposalId'.
|
||||||
newtype PProposalId (s :: S) = PProposalId (Term s PInteger)
|
|
||||||
deriving (PlutusType, PIsData, PEq, POrd) via (DerivePNewtype PProposalId PInteger)
|
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
|
newtype PProposalId (s :: S) = PProposalId (Term s PInteger)
|
||||||
|
deriving
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
PlutusType
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PIsData
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PEq
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
POrd
|
||||||
|
)
|
||||||
|
via (DerivePNewtype PProposalId PInteger)
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
instance PTryFrom PData (PAsData PProposalId) where
|
instance PTryFrom PData (PAsData PProposalId) where
|
||||||
type PTryFromExcess PData (PAsData PProposalId) = PTryFromExcess PData (PAsData PInteger)
|
type PTryFromExcess PData (PAsData PProposalId) = PTryFromExcess PData (PAsData PInteger)
|
||||||
ptryFrom' d k =
|
ptryFrom' d k =
|
||||||
|
|
@ -317,13 +442,19 @@ instance PTryFrom PData (PAsData PProposalId) where
|
||||||
-- Since 'PProposalId' is a simple newtype, their shape is the same.
|
-- Since 'PProposalId' is a simple newtype, their shape is the same.
|
||||||
k . first punsafeCoerce
|
k . first punsafeCoerce
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
instance PUnsafeLiftDecl PProposalId where type PLifted PProposalId = ProposalId
|
instance PUnsafeLiftDecl PProposalId where type PLifted PProposalId = ProposalId
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
deriving via
|
deriving via
|
||||||
(DerivePConstantViaNewtype ProposalId PProposalId PInteger)
|
(DerivePConstantViaNewtype ProposalId PProposalId PInteger)
|
||||||
instance
|
instance
|
||||||
(PConstantDecl ProposalId)
|
(PConstantDecl ProposalId)
|
||||||
|
|
||||||
-- | Plutarch-level version of 'ProposalStatus'.
|
{- | Plutarch-level version of 'ProposalStatus'.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
data PProposalStatus (s :: S)
|
data PProposalStatus (s :: S)
|
||||||
= -- TODO: 'PProposalStatus' ought te be encoded as 'PInteger'.
|
= -- TODO: 'PProposalStatus' ought te be encoded as 'PInteger'.
|
||||||
-- e.g. like Tilde used 'pmatchEnum'.
|
-- e.g. like Tilde used 'pmatchEnum'.
|
||||||
|
|
@ -331,17 +462,38 @@ data PProposalStatus (s :: S)
|
||||||
| PVotingReady (Term s (PDataRecord '[]))
|
| PVotingReady (Term s (PDataRecord '[]))
|
||||||
| PLocked (Term s (PDataRecord '[]))
|
| PLocked (Term s (PDataRecord '[]))
|
||||||
| PFinished (Term s (PDataRecord '[]))
|
| PFinished (Term s (PDataRecord '[]))
|
||||||
deriving stock (GHC.Generic)
|
deriving stock
|
||||||
deriving anyclass (Generic)
|
( -- | @since 0.1.0
|
||||||
deriving anyclass (PIsDataRepr)
|
GHC.Generic
|
||||||
|
)
|
||||||
|
deriving anyclass
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
Generic
|
||||||
|
)
|
||||||
|
deriving anyclass
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
PIsDataRepr
|
||||||
|
)
|
||||||
deriving
|
deriving
|
||||||
(PlutusType, PIsData, PEq)
|
( -- | @since 0.1.0
|
||||||
|
PlutusType
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PIsData
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PEq
|
||||||
|
)
|
||||||
via PIsDataReprInstances PProposalStatus
|
via PIsDataReprInstances PProposalStatus
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
instance PUnsafeLiftDecl PProposalStatus where type PLifted PProposalStatus = ProposalStatus
|
instance PUnsafeLiftDecl PProposalStatus where type PLifted PProposalStatus = ProposalStatus
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
deriving via (DerivePConstantViaData ProposalStatus PProposalStatus) instance (PConstantDecl ProposalStatus)
|
deriving via (DerivePConstantViaData ProposalStatus PProposalStatus) instance (PConstantDecl ProposalStatus)
|
||||||
|
|
||||||
-- | Plutarch-level version of 'ProposalThresholds'.
|
{- | Plutarch-level version of 'ProposalThresholds'.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
newtype PProposalThresholds (s :: S) = PProposalThresholds
|
newtype PProposalThresholds (s :: S) = PProposalThresholds
|
||||||
{ getProposalThresholds ::
|
{ getProposalThresholds ::
|
||||||
Term
|
Term
|
||||||
|
|
@ -353,22 +505,52 @@ newtype PProposalThresholds (s :: S) = PProposalThresholds
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
deriving stock (GHC.Generic)
|
deriving stock
|
||||||
deriving anyclass (Generic)
|
( -- | @since 0.1.0
|
||||||
deriving anyclass (PIsDataRepr)
|
GHC.Generic
|
||||||
|
)
|
||||||
|
deriving anyclass
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
Generic
|
||||||
|
)
|
||||||
|
deriving anyclass
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
PIsDataRepr
|
||||||
|
)
|
||||||
deriving
|
deriving
|
||||||
(PlutusType, PIsData, PDataFields)
|
( -- | @since 0.1.0
|
||||||
|
PlutusType
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PIsData
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PDataFields
|
||||||
|
)
|
||||||
via (PIsDataReprInstances PProposalThresholds)
|
via (PIsDataReprInstances PProposalThresholds)
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
instance PUnsafeLiftDecl PProposalThresholds where type PLifted PProposalThresholds = ProposalThresholds
|
instance PUnsafeLiftDecl PProposalThresholds where type PLifted PProposalThresholds = ProposalThresholds
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
deriving via (DerivePConstantViaData ProposalThresholds PProposalThresholds) instance (PConstantDecl ProposalThresholds)
|
deriving via (DerivePConstantViaData ProposalThresholds PProposalThresholds) instance (PConstantDecl ProposalThresholds)
|
||||||
|
|
||||||
-- | Plutarch-level version of 'ProposalVotes'.
|
{- | Plutarch-level version of 'ProposalVotes'.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
newtype PProposalVotes (s :: S)
|
newtype PProposalVotes (s :: S)
|
||||||
= PProposalVotes (Term s (PMap 'Unsorted PResultTag PInteger))
|
= PProposalVotes (Term s (PMap 'Unsorted PResultTag PInteger))
|
||||||
deriving (PlutusType, PIsData) via (DerivePNewtype PProposalVotes (PMap 'Unsorted PResultTag PInteger))
|
deriving
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
PlutusType
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PIsData
|
||||||
|
)
|
||||||
|
via (DerivePNewtype PProposalVotes (PMap 'Unsorted PResultTag PInteger))
|
||||||
|
|
||||||
-- | Retract votes given the option and the amount of votes.
|
{- | Retract votes given the option and the amount of votes.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
pretractVotes :: Term s (PResultTag :--> PInteger :--> PProposalVotes :--> PProposalVotes)
|
pretractVotes :: Term s (PResultTag :--> PInteger :--> PProposalVotes :--> PProposalVotes)
|
||||||
pretractVotes = phoistAcyclic $
|
pretractVotes = phoistAcyclic $
|
||||||
plam $ \rt count votes ->
|
plam $ \rt count votes ->
|
||||||
|
|
@ -386,13 +568,19 @@ pretractVotes = phoistAcyclic $
|
||||||
# rt
|
# rt
|
||||||
# voteMap
|
# voteMap
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
instance PUnsafeLiftDecl PProposalVotes where type PLifted PProposalVotes = ProposalVotes
|
instance PUnsafeLiftDecl PProposalVotes where type PLifted PProposalVotes = ProposalVotes
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
deriving via
|
deriving via
|
||||||
(DerivePConstantViaNewtype ProposalVotes PProposalVotes (PMap 'Unsorted PResultTag PInteger))
|
(DerivePConstantViaNewtype ProposalVotes PProposalVotes (PMap 'Unsorted PResultTag PInteger))
|
||||||
instance
|
instance
|
||||||
(PConstantDecl ProposalVotes)
|
(PConstantDecl ProposalVotes)
|
||||||
|
|
||||||
-- | Plutarch-level version of 'emptyVotesFor'.
|
{- | Plutarch-level version of 'emptyVotesFor'.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
pemptyVotesFor :: forall s a. (PIsData a) => Term s (PMap 'Unsorted PResultTag a :--> PProposalVotes)
|
pemptyVotesFor :: forall s a. (PIsData a) => Term s (PMap 'Unsorted PResultTag a :--> PProposalVotes)
|
||||||
pemptyVotesFor =
|
pemptyVotesFor =
|
||||||
phoistAcyclic $
|
phoistAcyclic $
|
||||||
|
|
@ -402,7 +590,10 @@ pemptyVotesFor =
|
||||||
PProposalVotes $ PM.pmap # plam (const $ pconstant 0) # m
|
PProposalVotes $ PM.pmap # plam (const $ pconstant 0) # m
|
||||||
)
|
)
|
||||||
|
|
||||||
-- | Plutarch-level version of 'ProposalDatum'.
|
{- | Plutarch-level version of 'ProposalDatum'.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
newtype PProposalDatum (s :: S) = PProposalDatum
|
newtype PProposalDatum (s :: S) = PProposalDatum
|
||||||
{ getProposalDatum ::
|
{ getProposalDatum ::
|
||||||
Term
|
Term
|
||||||
|
|
@ -419,36 +610,76 @@ newtype PProposalDatum (s :: S) = PProposalDatum
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
deriving stock (GHC.Generic)
|
deriving stock
|
||||||
deriving anyclass (Generic)
|
( -- | @since 0.1.0
|
||||||
deriving anyclass (PIsDataRepr)
|
GHC.Generic
|
||||||
|
)
|
||||||
|
deriving anyclass
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
Generic
|
||||||
|
)
|
||||||
|
deriving anyclass
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
PIsDataRepr
|
||||||
|
)
|
||||||
deriving
|
deriving
|
||||||
(PlutusType, PIsData, PDataFields, PEq)
|
( -- | @since 0.1.0
|
||||||
|
PlutusType
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PIsData
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PDataFields
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PEq
|
||||||
|
)
|
||||||
via (PIsDataReprInstances PProposalDatum)
|
via (PIsDataReprInstances PProposalDatum)
|
||||||
|
|
||||||
-- TODO: Derive this.
|
-- TODO: Derive this.
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
instance PTryFrom PData (PAsData PProposalDatum) where
|
instance PTryFrom PData (PAsData PProposalDatum) where
|
||||||
type PTryFromExcess PData (PAsData PProposalDatum) = Const ()
|
type PTryFromExcess PData (PAsData PProposalDatum) = Const ()
|
||||||
ptryFrom' d k =
|
ptryFrom' d k =
|
||||||
k (punsafeCoerce d, ())
|
k (punsafeCoerce d, ())
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
instance PUnsafeLiftDecl PProposalDatum where type PLifted PProposalDatum = ProposalDatum
|
instance PUnsafeLiftDecl PProposalDatum where type PLifted PProposalDatum = ProposalDatum
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
deriving via (DerivePConstantViaData ProposalDatum PProposalDatum) instance (PConstantDecl ProposalDatum)
|
deriving via (DerivePConstantViaData ProposalDatum PProposalDatum) instance (PConstantDecl ProposalDatum)
|
||||||
|
|
||||||
-- | Plutarch-level version of 'ProposalRedeemer'.
|
{- | Plutarch-level version of 'ProposalRedeemer'.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
data PProposalRedeemer (s :: S)
|
data PProposalRedeemer (s :: S)
|
||||||
= PVote (Term s (PDataRecord '["resultTag" ':= PResultTag]))
|
= PVote (Term s (PDataRecord '["resultTag" ':= PResultTag]))
|
||||||
| PCosign (Term s (PDataRecord '["newCosigners" ':= PBuiltinList (PAsData PPubKeyHash)]))
|
| PCosign (Term s (PDataRecord '["newCosigners" ':= PBuiltinList (PAsData PPubKeyHash)]))
|
||||||
| PUnlock (Term s (PDataRecord '["resultTag" ':= PResultTag]))
|
| PUnlock (Term s (PDataRecord '["resultTag" ':= PResultTag]))
|
||||||
| PAdvanceProposal (Term s (PDataRecord '[]))
|
| PAdvanceProposal (Term s (PDataRecord '[]))
|
||||||
deriving stock (GHC.Generic)
|
deriving stock
|
||||||
deriving anyclass (Generic)
|
( -- | @since 0.1.0
|
||||||
deriving anyclass (PIsDataRepr)
|
GHC.Generic
|
||||||
|
)
|
||||||
|
deriving anyclass
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
Generic
|
||||||
|
)
|
||||||
|
deriving anyclass
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
PIsDataRepr
|
||||||
|
)
|
||||||
deriving
|
deriving
|
||||||
(PlutusType, PIsData)
|
( -- | @since 0.1.0
|
||||||
|
PlutusType
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PIsData
|
||||||
|
)
|
||||||
via PIsDataReprInstances PProposalRedeemer
|
via PIsDataReprInstances PProposalRedeemer
|
||||||
|
|
||||||
-- See below.
|
-- See below.
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
instance PTryFrom PData (PAsData PProposalRedeemer) where
|
instance PTryFrom PData (PAsData PProposalRedeemer) where
|
||||||
type PTryFromExcess PData (PAsData PProposalRedeemer) = Const ()
|
type PTryFromExcess PData (PAsData PProposalRedeemer) = Const ()
|
||||||
ptryFrom' d k =
|
ptryFrom' d k =
|
||||||
|
|
@ -460,7 +691,10 @@ instance PTryFrom PData (PAsData PProposalRedeemer) where
|
||||||
-- instance
|
-- instance
|
||||||
-- PTryFrom PData (PAsData PProposalRedeemer)
|
-- PTryFrom PData (PAsData PProposalRedeemer)
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
instance PUnsafeLiftDecl PProposalRedeemer where type PLifted PProposalRedeemer = ProposalRedeemer
|
instance PUnsafeLiftDecl PProposalRedeemer where type PLifted PProposalRedeemer = ProposalRedeemer
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
deriving via (DerivePConstantViaData ProposalRedeemer PProposalRedeemer) instance (PConstantDecl ProposalRedeemer)
|
deriving via (DerivePConstantViaData ProposalRedeemer PProposalRedeemer) instance (PConstantDecl ProposalRedeemer)
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
@ -468,6 +702,8 @@ deriving via (DerivePConstantViaData ProposalRedeemer PProposalRedeemer) instanc
|
||||||
{- | Check for various invariants a proposal must uphold.
|
{- | Check for various invariants a proposal must uphold.
|
||||||
This can be used to check both upon creation and
|
This can be used to check both upon creation and
|
||||||
upon any following state transitions in the proposal.
|
upon any following state transitions in the proposal.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
-}
|
-}
|
||||||
proposalDatumValid :: Proposal -> Term s (Agora.Proposal.PProposalDatum :--> PBool)
|
proposalDatumValid :: Proposal -> Term s (Agora.Proposal.PProposalDatum :--> PBool)
|
||||||
proposalDatumValid proposal =
|
proposalDatumValid proposal =
|
||||||
|
|
@ -493,8 +729,10 @@ proposalDatumValid proposal =
|
||||||
|
|
||||||
{- | Find the winner result tag, given the votes, the quorum the "neutral" result tag.
|
{- | Find the winner result tag, given the votes, the quorum the "neutral" result tag.
|
||||||
|
|
||||||
The winner should be unambiguous, meaning that if two options have the same highest votes,
|
The winner should be unambiguous, meaning that if two options have the same highest votes,
|
||||||
the "neutral" option will be the winner.
|
the "neutral" option will be the winner.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
-}
|
-}
|
||||||
pwinner ::
|
pwinner ::
|
||||||
Term
|
Term
|
||||||
|
|
@ -540,7 +778,10 @@ pwinner = phoistAcyclic $
|
||||||
winnerResultTag
|
winnerResultTag
|
||||||
neutral
|
neutral
|
||||||
|
|
||||||
-- | Find the winning outcome (and the corresponding vote count) given the votes.
|
{- | Find the winning outcome (and the corresponding vote count) given the votes.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
phighestVotes ::
|
phighestVotes ::
|
||||||
Term
|
Term
|
||||||
s
|
s
|
||||||
|
|
@ -566,7 +807,10 @@ phighestVotes = phoistAcyclic $
|
||||||
in pif (lastVotes #< thisVotes) this last
|
in pif (lastVotes #< thisVotes) this last
|
||||||
in pfoldr # f # (phead # l) # l
|
in pfoldr # f # (phead # l) # l
|
||||||
|
|
||||||
-- | Find the "neutral" option (a dummy outcome with no effect) given the effects.
|
{- | Find the "neutral" option (a dummy outcome with no effect) given the effects.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
pneutralOption ::
|
pneutralOption ::
|
||||||
Term
|
Term
|
||||||
s
|
s
|
||||||
|
|
|
||||||
|
|
@ -70,21 +70,23 @@ import PlutusLedgerApi.V1.Value (AssetClass (AssetClass))
|
||||||
|
|
||||||
{- | Policy for Proposals.
|
{- | Policy for Proposals.
|
||||||
|
|
||||||
== What this policy does
|
== What this policy does
|
||||||
|
|
||||||
=== For minting:
|
=== For minting:
|
||||||
|
|
||||||
- Governor is happy with mint.
|
- Governor is happy with mint.
|
||||||
|
|
||||||
* The governor must do most of the checking for the validity of the
|
* The governor must do most of the checking for the validity of the
|
||||||
transaction. For example, the governor must check that the datum
|
transaction. For example, the governor must check that the datum
|
||||||
is correct, and that the ST is correctly paid to the right validator.
|
is correct, and that the ST is correctly paid to the right validator.
|
||||||
|
|
||||||
- Exactly 1 token is minted.
|
- Exactly 1 token is minted.
|
||||||
|
|
||||||
=== For burning:
|
=== For burning:
|
||||||
|
|
||||||
- This policy cannot be burned.
|
- This policy cannot be burned.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
-}
|
-}
|
||||||
proposalPolicy ::
|
proposalPolicy ::
|
||||||
-- | The assetclass of GST, see 'Agora.Governor.Scripts.governorPolicy'.
|
-- | The assetclass of GST, see 'Agora.Governor.Scripts.governorPolicy'.
|
||||||
|
|
@ -119,29 +121,31 @@ proposalPolicy (AssetClass (govCs, govTn)) =
|
||||||
|
|
||||||
{- | The validator for Proposals.
|
{- | The validator for Proposals.
|
||||||
|
|
||||||
The documentation for various of the redeemers lives at 'Agora.Proposal.ProposalRedeemer'.
|
The documentation for various of the redeemers lives at 'Agora.Proposal.ProposalRedeemer'.
|
||||||
|
|
||||||
== What this validator does
|
== What this validator does
|
||||||
|
|
||||||
=== Voting/unlocking
|
=== Voting/unlocking
|
||||||
|
|
||||||
When voting and unlocking, the proposal must witness a state transition
|
When voting and unlocking, the proposal must witness a state transition
|
||||||
occuring in the relevant Stake. This transition must place a lock on
|
occuring in the relevant Stake. This transition must place a lock on
|
||||||
the stake that is tagged with the right 'Agora.Proposal.ResultTag', and 'Agora.Proposal.ProposalId'.
|
the stake that is tagged with the right 'Agora.Proposal.ResultTag', and 'Agora.Proposal.ProposalId'.
|
||||||
|
|
||||||
=== Periods
|
=== Periods
|
||||||
|
|
||||||
Most redeemers are time-sensitive.
|
Most redeemers are time-sensitive.
|
||||||
|
|
||||||
A list of all time-sensitive redeemers and their requirements:
|
A list of all time-sensitive redeemers and their requirements:
|
||||||
|
|
||||||
- 'Agora.Proposal.Vote' can only be used when both the status is in 'Agora.Proposal.VotingReady',
|
- 'Agora.Proposal.Vote' can only be used when both the status is in 'Agora.Proposal.VotingReady',
|
||||||
and 'Agora.Proposal.Time.isVotingPeriod' is true.
|
and 'Agora.Proposal.Time.isVotingPeriod' is true.
|
||||||
- 'Agora.Proposal.Cosign' can only be used when both the status is in 'Agora.Proposal.Draft',
|
- 'Agora.Proposal.Cosign' can only be used when both the status is in 'Agora.Proposal.Draft',
|
||||||
and 'Agora.Proposal.Time.isDraftPeriod' is true.
|
and 'Agora.Proposal.Time.isDraftPeriod' is true.
|
||||||
- 'Agora.Proposal.AdvanceProposal' can only be used when the status can be advanced
|
- 'Agora.Proposal.AdvanceProposal' can only be used when the status can be advanced
|
||||||
(see 'Agora.Proposal.AdvanceProposal' docs).
|
(see 'Agora.Proposal.AdvanceProposal' docs).
|
||||||
- 'Agora.Proposal.Unlock' is always valid.
|
- 'Agora.Proposal.Unlock' is always valid.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
-}
|
-}
|
||||||
proposalValidator :: Proposal -> ClosedTerm PValidator
|
proposalValidator :: Proposal -> ClosedTerm PValidator
|
||||||
proposalValidator proposal =
|
proposalValidator proposal =
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,10 @@ import Prelude hiding ((+))
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
-- | Represents the starting time of the proposal.
|
{- | Represents the starting time of the proposal.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
newtype ProposalStartingTime = ProposalStartingTime
|
newtype ProposalStartingTime = ProposalStartingTime
|
||||||
{ getProposalStartingTime :: POSIXTime
|
{ getProposalStartingTime :: POSIXTime
|
||||||
}
|
}
|
||||||
|
|
@ -67,7 +70,9 @@ newtype ProposalStartingTime = ProposalStartingTime
|
||||||
|
|
||||||
{- | Configuration of proposal timings.
|
{- | Configuration of proposal timings.
|
||||||
|
|
||||||
See: https://github.com/Liqwid-Labs/agora/blob/master/docs/tech-design/proposals.md#when-may-interactions-occur
|
See: https://liqwid.notion.site/Proposals-589853145a994057aa77f397079f75e4#d25ea378768d4c76b52dd4c1b6bc0fcd
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
-}
|
-}
|
||||||
data ProposalTimingConfig = ProposalTimingConfig
|
data ProposalTimingConfig = ProposalTimingConfig
|
||||||
{ draftTime :: POSIXTime
|
{ draftTime :: POSIXTime
|
||||||
|
|
@ -79,61 +84,115 @@ data ProposalTimingConfig = ProposalTimingConfig
|
||||||
, executingTime :: POSIXTime
|
, executingTime :: POSIXTime
|
||||||
-- ^ "E": the length of the execution period.
|
-- ^ "E": the length of the execution period.
|
||||||
}
|
}
|
||||||
deriving stock (Eq, Show, GHC.Generic)
|
deriving stock
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
Eq
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
Show
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
GHC.Generic
|
||||||
|
)
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
PlutusTx.makeIsDataIndexed ''ProposalTimingConfig [('ProposalTimingConfig, 0)]
|
PlutusTx.makeIsDataIndexed ''ProposalTimingConfig [('ProposalTimingConfig, 0)]
|
||||||
|
|
||||||
-- | Represents the maximum width of a 'PlutusLedgerApi.V1.Time.POSIXTimeRange'.
|
-- | Represents the maximum width of a 'PlutusLedgerApi.V1.Time.POSIXTimeRange'.
|
||||||
newtype MaxTimeRangeWidth = MaxTimeRangeWidth {getMaxWidth :: POSIXTime}
|
newtype MaxTimeRangeWidth = MaxTimeRangeWidth {getMaxWidth :: POSIXTime}
|
||||||
deriving stock (Eq, Show, Ord, GHC.Generic)
|
deriving stock
|
||||||
deriving newtype (PlutusTx.ToData, PlutusTx.FromData, PlutusTx.UnsafeFromData)
|
( -- | @since 0.1.0
|
||||||
|
Eq
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
Show
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
Ord
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
GHC.Generic
|
||||||
|
)
|
||||||
|
deriving newtype
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
PlutusTx.ToData
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PlutusTx.FromData
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PlutusTx.UnsafeFromData
|
||||||
|
)
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
{- | == Establishing timing in Proposal interactions.
|
{- | == Establishing timing in Proposal interactions.
|
||||||
|
|
||||||
In Plutus, it's impossible to determine time exactly. It's also impossible
|
In Plutus, it's impossible to determine time exactly. It's also impossible
|
||||||
to get a single point in time, yet often we need to check
|
to get a single point in time, yet often we need to check
|
||||||
various constraints on time.
|
various constraints on time.
|
||||||
|
|
||||||
For the purposes of proposals, there's a single most important feature:
|
For the purposes of proposals, there's a single most important feature:
|
||||||
The ability to determine if we can perform an action. In order to correctly
|
The ability to determine if we can perform an action. In order to correctly
|
||||||
determine if we are able to perform certain actions, we need to know what
|
determine if we are able to perform certain actions, we need to know what
|
||||||
time it roughly is, compared to when the proposal was created.
|
time it roughly is, compared to when the proposal was created.
|
||||||
|
|
||||||
'PProposalTime' represents "the time according to the proposal".
|
'PProposalTime' represents "the time according to the proposal".
|
||||||
Its representation is opaque, and doesn't matter.
|
Its representation is opaque, and doesn't matter.
|
||||||
|
|
||||||
Various functions work simply on 'PProposalTime' and 'ProposalTimingConfig'.
|
Various functions work simply on 'PProposalTime' and 'ProposalTimingConfig'.
|
||||||
In particular, 'currentProposalTime' is useful for extracting the time
|
In particular, 'currentProposalTime' is useful for extracting the time
|
||||||
from the 'PlutusLedgerApi.V1.txInfoValidPeriod' field
|
from the 'PlutusLedgerApi.V1.txInfoValidPeriod' field
|
||||||
of 'PlutusLedgerApi.V1.TxInfo'.
|
of 'PlutusLedgerApi.V1.TxInfo'.
|
||||||
|
|
||||||
We avoid 'PPOSIXTimeRange' where we can in order to save on operations.
|
We avoid 'PPOSIXTimeRange' where we can in order to save on operations.
|
||||||
|
|
||||||
Note: 'PProposalTime' doesn't need a Haskell-level equivalent because it
|
Note: 'PProposalTime' doesn't need a Haskell-level equivalent because it
|
||||||
is only used in scripts, and does not go in datums. It is also scott-encoded
|
is only used in scripts, and does not go in datums. It is also scott-encoded
|
||||||
which is more efficient in usage.
|
which is more efficient in usage.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
-}
|
-}
|
||||||
data PProposalTime (s :: S) = PProposalTime
|
data PProposalTime (s :: S) = PProposalTime
|
||||||
{ lowerBound :: Term s PPOSIXTime
|
{ lowerBound :: Term s PPOSIXTime
|
||||||
, upperBound :: Term s PPOSIXTime
|
, upperBound :: Term s PPOSIXTime
|
||||||
}
|
}
|
||||||
deriving stock (GHC.Generic)
|
deriving stock
|
||||||
deriving anyclass (Generic, PlutusType, HasDatatypeInfo, PEq)
|
( -- | @since 0.1.0
|
||||||
|
GHC.Generic
|
||||||
|
)
|
||||||
|
deriving anyclass
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
Generic
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PlutusType
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
HasDatatypeInfo
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PEq
|
||||||
|
)
|
||||||
|
|
||||||
-- | Plutarch-level version of 'ProposalStartingTime'.
|
-- | Plutarch-level version of 'ProposalStartingTime'.
|
||||||
newtype PProposalStartingTime (s :: S) = PProposalStartingTime (Term s PPOSIXTime)
|
newtype PProposalStartingTime (s :: S) = PProposalStartingTime (Term s PPOSIXTime)
|
||||||
deriving (PlutusType, PIsData, PEq, POrd) via (DerivePNewtype PProposalStartingTime PPOSIXTime)
|
deriving
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
PlutusType
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PIsData
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PEq
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
POrd
|
||||||
|
)
|
||||||
|
via (DerivePNewtype PProposalStartingTime PPOSIXTime)
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
instance PUnsafeLiftDecl PProposalStartingTime where
|
instance PUnsafeLiftDecl PProposalStartingTime where
|
||||||
type PLifted PProposalStartingTime = ProposalStartingTime
|
type PLifted PProposalStartingTime = ProposalStartingTime
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
deriving via
|
deriving via
|
||||||
(DerivePConstantViaNewtype ProposalStartingTime PProposalStartingTime PPOSIXTime)
|
(DerivePConstantViaNewtype ProposalStartingTime PProposalStartingTime PPOSIXTime)
|
||||||
instance
|
instance
|
||||||
(PConstantDecl ProposalStartingTime)
|
(PConstantDecl ProposalStartingTime)
|
||||||
|
|
||||||
-- | Plutarch-level version of 'ProposalTimingConfig'.
|
{- | Plutarch-level version of 'ProposalTimingConfig'.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
newtype PProposalTimingConfig (s :: S) = PProposalTimingConfig
|
newtype PProposalTimingConfig (s :: S) = PProposalTimingConfig
|
||||||
{ getProposalTimingConfig ::
|
{ getProposalTimingConfig ::
|
||||||
Term
|
Term
|
||||||
|
|
@ -146,15 +205,33 @@ newtype PProposalTimingConfig (s :: S) = PProposalTimingConfig
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
deriving stock (GHC.Generic)
|
deriving stock
|
||||||
deriving anyclass (Generic)
|
( -- | @since 0.1.0
|
||||||
deriving anyclass (PIsDataRepr)
|
GHC.Generic
|
||||||
|
)
|
||||||
|
deriving anyclass
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
Generic
|
||||||
|
)
|
||||||
|
deriving anyclass
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
PIsDataRepr
|
||||||
|
)
|
||||||
deriving
|
deriving
|
||||||
(PlutusType, PIsData, PDataFields)
|
( -- | @since 0.1.0
|
||||||
|
PlutusType
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PIsData
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PDataFields
|
||||||
|
)
|
||||||
via (PIsDataReprInstances PProposalTimingConfig)
|
via (PIsDataReprInstances PProposalTimingConfig)
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
instance PUnsafeLiftDecl PProposalTimingConfig where
|
instance PUnsafeLiftDecl PProposalTimingConfig where
|
||||||
type PLifted PProposalTimingConfig = ProposalTimingConfig
|
type PLifted PProposalTimingConfig = ProposalTimingConfig
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
deriving via
|
deriving via
|
||||||
(DerivePConstantViaData ProposalTimingConfig PProposalTimingConfig)
|
(DerivePConstantViaData ProposalTimingConfig PProposalTimingConfig)
|
||||||
instance
|
instance
|
||||||
|
|
@ -163,9 +240,22 @@ deriving via
|
||||||
-- | Plutarch-level version of 'MaxTimeRangeWidth'.
|
-- | Plutarch-level version of 'MaxTimeRangeWidth'.
|
||||||
newtype PMaxTimeRangeWidth (s :: S)
|
newtype PMaxTimeRangeWidth (s :: S)
|
||||||
= PMaxTimeRangeWidth (Term s PPOSIXTime)
|
= PMaxTimeRangeWidth (Term s PPOSIXTime)
|
||||||
deriving (PlutusType, PIsData, PEq, POrd) via (DerivePNewtype PMaxTimeRangeWidth PPOSIXTime)
|
deriving
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
PlutusType
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PIsData
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PEq
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
POrd
|
||||||
|
)
|
||||||
|
via (DerivePNewtype PMaxTimeRangeWidth PPOSIXTime)
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
instance PUnsafeLiftDecl PMaxTimeRangeWidth where type PLifted PMaxTimeRangeWidth = MaxTimeRangeWidth
|
instance PUnsafeLiftDecl PMaxTimeRangeWidth where type PLifted PMaxTimeRangeWidth = MaxTimeRangeWidth
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
deriving via
|
deriving via
|
||||||
(DerivePConstantViaNewtype MaxTimeRangeWidth PMaxTimeRangeWidth PPOSIXTime)
|
(DerivePConstantViaNewtype MaxTimeRangeWidth PMaxTimeRangeWidth PPOSIXTime)
|
||||||
instance
|
instance
|
||||||
|
|
@ -174,12 +264,16 @@ deriving via
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
-- FIXME: Orphan instance, move this to plutarch-extra.
|
-- FIXME: Orphan instance, move this to plutarch-extra.
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
instance AdditiveSemigroup (Term s PPOSIXTime) where
|
instance AdditiveSemigroup (Term s PPOSIXTime) where
|
||||||
(punsafeCoerce @_ @_ @PInteger -> x) + (punsafeCoerce @_ @_ @PInteger -> y) = punsafeCoerce $ x + y
|
(punsafeCoerce @_ @_ @PInteger -> x) + (punsafeCoerce @_ @_ @PInteger -> y) = punsafeCoerce $ x + y
|
||||||
|
|
||||||
{- | Get the starting time of a proposal, from the 'PlutusLedgerApi.V1.txInfoValidPeriod' field.
|
{- | Get the starting time of a proposal, from the 'PlutusLedgerApi.V1.txInfoValidPeriod' field.
|
||||||
For every proposal, this is only meant to run once upon creation. Given time range should be
|
For every proposal, this is only meant to run once upon creation. Given time range should be
|
||||||
tight enough, meaning that the width of the time range should be less than the maximum value.
|
tight enough, meaning that the width of the time range should be less than the maximum value.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
-}
|
-}
|
||||||
createProposalStartingTime :: forall (s :: S). Term s (PMaxTimeRangeWidth :--> PPOSIXTimeRange :--> PProposalStartingTime)
|
createProposalStartingTime :: forall (s :: S). Term s (PMaxTimeRangeWidth :--> PPOSIXTimeRange :--> PProposalStartingTime)
|
||||||
createProposalStartingTime = phoistAcyclic $
|
createProposalStartingTime = phoistAcyclic $
|
||||||
|
|
@ -201,8 +295,10 @@ createProposalStartingTime = phoistAcyclic $
|
||||||
|
|
||||||
{- | Get the current proposal time, from the 'PlutusLedgerApi.V1.txInfoValidPeriod' field.
|
{- | Get the current proposal time, from the 'PlutusLedgerApi.V1.txInfoValidPeriod' field.
|
||||||
|
|
||||||
If it's impossible to get a fully-bounded time, (e.g. either end of the 'PPOSIXTimeRange' is
|
If it's impossible to get a fully-bounded time, (e.g. either end of the 'PPOSIXTimeRange' is
|
||||||
an infinity) then we error out.
|
an infinity) then we error out.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
-}
|
-}
|
||||||
currentProposalTime :: forall (s :: S). Term s (PPOSIXTimeRange :--> PProposalTime)
|
currentProposalTime :: forall (s :: S). Term s (PPOSIXTimeRange :--> PProposalTime)
|
||||||
currentProposalTime = phoistAcyclic $
|
currentProposalTime = phoistAcyclic $
|
||||||
|
|
@ -232,7 +328,10 @@ currentProposalTime = phoistAcyclic $
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
-- | Check if 'PProposalTime' is within two 'PPOSIXTime'. Inclusive.
|
{- | Check if 'PProposalTime' is within two 'PPOSIXTime'. Inclusive.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
proposalTimeWithin ::
|
proposalTimeWithin ::
|
||||||
Term
|
Term
|
||||||
s
|
s
|
||||||
|
|
@ -251,7 +350,10 @@ proposalTimeWithin = phoistAcyclic $
|
||||||
, ut #<= h
|
, ut #<= h
|
||||||
]
|
]
|
||||||
|
|
||||||
-- | True if the 'PProposalTime' is in the draft period.
|
{- | True if the 'PProposalTime' is in the draft period.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
isDraftPeriod ::
|
isDraftPeriod ::
|
||||||
forall (s :: S).
|
forall (s :: S).
|
||||||
Term
|
Term
|
||||||
|
|
@ -265,7 +367,10 @@ isDraftPeriod = phoistAcyclic $
|
||||||
plam $ \config s' -> pmatch s' $ \(PProposalStartingTime s) ->
|
plam $ \config s' -> pmatch s' $ \(PProposalStartingTime s) ->
|
||||||
proposalTimeWithin # s # (s + (pfield @"draftTime" # config))
|
proposalTimeWithin # s # (s + (pfield @"draftTime" # config))
|
||||||
|
|
||||||
-- | True if the 'PProposalTime' is in the voting period.
|
{- | True if the 'PProposalTime' is in the voting period.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
isVotingPeriod ::
|
isVotingPeriod ::
|
||||||
forall (s :: S).
|
forall (s :: S).
|
||||||
Term
|
Term
|
||||||
|
|
@ -280,7 +385,10 @@ isVotingPeriod = phoistAcyclic $
|
||||||
pletFields @'["draftTime", "votingTime"] config $ \f ->
|
pletFields @'["draftTime", "votingTime"] config $ \f ->
|
||||||
proposalTimeWithin # s # (s + f.draftTime + f.votingTime)
|
proposalTimeWithin # s # (s + f.draftTime + f.votingTime)
|
||||||
|
|
||||||
-- | True if the 'PProposalTime' is in the locking period.
|
{- | True if the 'PProposalTime' is in the locking period.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
isLockingPeriod ::
|
isLockingPeriod ::
|
||||||
forall (s :: S).
|
forall (s :: S).
|
||||||
Term
|
Term
|
||||||
|
|
@ -295,7 +403,10 @@ isLockingPeriod = phoistAcyclic $
|
||||||
pletFields @'["draftTime", "votingTime", "lockingTime"] config $ \f ->
|
pletFields @'["draftTime", "votingTime", "lockingTime"] config $ \f ->
|
||||||
proposalTimeWithin # s # (s + f.draftTime + f.votingTime + f.lockingTime)
|
proposalTimeWithin # s # (s + f.draftTime + f.votingTime + f.lockingTime)
|
||||||
|
|
||||||
-- | True if the 'PProposalTime' is in the execution period.
|
{- | True if the 'PProposalTime' is in the execution period.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
isExecutionPeriod ::
|
isExecutionPeriod ::
|
||||||
forall (s :: S).
|
forall (s :: S).
|
||||||
Term
|
Term
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{- |
|
{- |
|
||||||
Module : Agora.SafeMoney
|
Module : Agora.SafeMoney
|
||||||
Maintainer : emi@haskell.fyi
|
Maintainer : emi@haskell.fyi
|
||||||
Description: Tags and bonuses for Plutarch.SafeMoney.
|
Description: Tags and extras for "Plutarch.SafeMoney".
|
||||||
|
|
||||||
Tags and extras for "Plutarch.SafeMoney".
|
Tags and extras for "Plutarch.SafeMoney".
|
||||||
-}
|
-}
|
||||||
|
|
@ -14,32 +14,42 @@ module Agora.SafeMoney (
|
||||||
adaRef,
|
adaRef,
|
||||||
) where
|
) where
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
import Data.Tagged (Tagged (Tagged))
|
||||||
|
|
||||||
import PlutusLedgerApi.V1.Value (AssetClass (AssetClass))
|
import PlutusLedgerApi.V1.Value (AssetClass (AssetClass))
|
||||||
|
|
||||||
import Data.Tagged (Tagged (Tagged))
|
{- | Governance token.
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
@since 0.1.0
|
||||||
-- Tags
|
-}
|
||||||
|
|
||||||
-- | Governance token.
|
|
||||||
data GTTag
|
data GTTag
|
||||||
|
|
||||||
-- | ADA.
|
{- | ADA.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
data ADATag
|
data ADATag
|
||||||
|
|
||||||
-- | Governor ST token.
|
{- | Governor ST token.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
data GovernorSTTag
|
data GovernorSTTag
|
||||||
|
|
||||||
-- | Stake ST token.
|
{- | Stake ST token.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
data StakeSTTag
|
data StakeSTTag
|
||||||
|
|
||||||
-- | Proposal ST token.
|
{- | Proposal ST token.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
data ProposalSTTag
|
data ProposalSTTag
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
{- | Resolves ada tags.
|
||||||
|
|
||||||
-- | Resolves ada tags.
|
@since 0.1.0
|
||||||
|
-}
|
||||||
adaRef :: Tagged ADATag AssetClass
|
adaRef :: Tagged ADATag AssetClass
|
||||||
adaRef = Tagged (AssetClass ("", ""))
|
adaRef = Tagged (AssetClass ("", ""))
|
||||||
|
|
|
||||||
|
|
@ -22,17 +22,35 @@ import Plutarch.Api.V1 (PMintingPolicy, PValidator, mintingPolicySymbol, mkMinti
|
||||||
import PlutusLedgerApi.V1 (MintingPolicy, Validator, ValidatorHash)
|
import PlutusLedgerApi.V1 (MintingPolicy, Validator, ValidatorHash)
|
||||||
import PlutusLedgerApi.V1.Value (CurrencySymbol)
|
import PlutusLedgerApi.V1.Value (CurrencySymbol)
|
||||||
|
|
||||||
-- | Bundle containing a 'Validator' and its hash.
|
{- | Bundle containing a 'Validator' and its hash.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
data ValidatorInfo = ValidatorInfo
|
data ValidatorInfo = ValidatorInfo
|
||||||
{ script :: Validator
|
{ script :: Validator
|
||||||
-- ^ The validator script.
|
-- ^ The validator script.
|
||||||
, hash :: ValidatorHash
|
, hash :: ValidatorHash
|
||||||
-- ^ Hash of the validator.
|
-- ^ Hash of the validator.
|
||||||
}
|
}
|
||||||
deriving stock (Show, Eq, GHC.Generic)
|
deriving stock
|
||||||
deriving anyclass (Aeson.ToJSON, Aeson.FromJSON)
|
( -- | @since 0.1.0
|
||||||
|
Show
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
Eq
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
GHC.Generic
|
||||||
|
)
|
||||||
|
deriving anyclass
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
Aeson.ToJSON
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
Aeson.FromJSON
|
||||||
|
)
|
||||||
|
|
||||||
-- | Create a 'ValidatorInfo' given a Plutarch term.
|
{- | Create a 'ValidatorInfo' given a Plutarch term.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
mkValidatorInfo :: ClosedTerm PValidator -> ValidatorInfo
|
mkValidatorInfo :: ClosedTerm PValidator -> ValidatorInfo
|
||||||
mkValidatorInfo term =
|
mkValidatorInfo term =
|
||||||
ValidatorInfo
|
ValidatorInfo
|
||||||
|
|
@ -42,17 +60,35 @@ mkValidatorInfo term =
|
||||||
where
|
where
|
||||||
validator = mkValidator term
|
validator = mkValidator term
|
||||||
|
|
||||||
-- | Bundle containing a 'MintingPolicy' and its symbol.
|
{- | Bundle containing a 'MintingPolicy' and its symbol.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
data PolicyInfo = PolicyInfo
|
data PolicyInfo = PolicyInfo
|
||||||
{ policy :: MintingPolicy
|
{ policy :: MintingPolicy
|
||||||
-- ^ The minting policy.
|
-- ^ The minting policy.
|
||||||
, currencySymbol :: CurrencySymbol
|
, currencySymbol :: CurrencySymbol
|
||||||
-- ^ The symbol given by the minting policy.
|
-- ^ The symbol given by the minting policy.
|
||||||
}
|
}
|
||||||
deriving stock (Show, Eq, GHC.Generic)
|
deriving stock
|
||||||
deriving anyclass (Aeson.ToJSON, Aeson.FromJSON)
|
( -- | @since 0.1.0
|
||||||
|
Show
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
Eq
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
GHC.Generic
|
||||||
|
)
|
||||||
|
deriving anyclass
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
Aeson.ToJSON
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
Aeson.FromJSON
|
||||||
|
)
|
||||||
|
|
||||||
-- | Create a 'PolicyInfo' given a Plutarch term.
|
{- | Create a 'PolicyInfo' given a Plutarch term.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
mkPolicyInfo :: ClosedTerm PMintingPolicy -> PolicyInfo
|
mkPolicyInfo :: ClosedTerm PMintingPolicy -> PolicyInfo
|
||||||
mkPolicyInfo term =
|
mkPolicyInfo term =
|
||||||
PolicyInfo
|
PolicyInfo
|
||||||
|
|
|
||||||
|
|
@ -72,13 +72,19 @@ import Agora.SafeMoney (GTTag)
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
-- | Parameters for creating Stake scripts.
|
{- | Parameters for creating Stake scripts.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
data Stake = Stake
|
data Stake = Stake
|
||||||
{ gtClassRef :: Tagged GTTag AssetClass
|
{ gtClassRef :: Tagged GTTag AssetClass
|
||||||
-- ^ Used when inlining the AssetClass of a 'PDiscrete' in the script code.
|
-- ^ Used when inlining the AssetClass of a 'PDiscrete' in the script code.
|
||||||
, proposalSTClass :: AssetClass
|
, proposalSTClass :: AssetClass
|
||||||
}
|
}
|
||||||
deriving stock (GHC.Generic)
|
deriving stock
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
GHC.Generic
|
||||||
|
)
|
||||||
|
|
||||||
{- | A lock placed on a Stake datum in order to prevent
|
{- | A lock placed on a Stake datum in order to prevent
|
||||||
depositing and withdrawing when votes are in place.
|
depositing and withdrawing when votes are in place.
|
||||||
|
|
@ -105,6 +111,8 @@ data Stake = Stake
|
||||||
│ Stake Policy │◄─┘ └►│ Proposal Policy │
|
│ Stake Policy │◄─┘ └►│ Proposal Policy │
|
||||||
└──────────────┘ └─────────────────┘
|
└──────────────┘ └─────────────────┘
|
||||||
@
|
@
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
-}
|
-}
|
||||||
data ProposalLock = ProposalLock
|
data ProposalLock = ProposalLock
|
||||||
{ vote :: ResultTag
|
{ vote :: ResultTag
|
||||||
|
|
@ -114,11 +122,19 @@ data ProposalLock = ProposalLock
|
||||||
-- ^ Identifies the proposal. See 'ProposalId' for further
|
-- ^ Identifies the proposal. See 'ProposalId' for further
|
||||||
-- comments on its significance.
|
-- comments on its significance.
|
||||||
}
|
}
|
||||||
deriving stock (Show, GHC.Generic)
|
deriving stock
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
Show
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
GHC.Generic
|
||||||
|
)
|
||||||
|
|
||||||
PlutusTx.makeIsDataIndexed ''ProposalLock [('ProposalLock, 0)]
|
PlutusTx.makeIsDataIndexed ''ProposalLock [('ProposalLock, 0)]
|
||||||
|
|
||||||
-- | Haskell-level redeemer for Stake scripts.
|
{- | Haskell-level redeemer for Stake scripts.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
data StakeRedeemer
|
data StakeRedeemer
|
||||||
= -- | Deposit or withdraw a discrete amount of the staked governance token.
|
= -- | Deposit or withdraw a discrete amount of the staked governance token.
|
||||||
-- Stake must be unlocked.
|
-- Stake must be unlocked.
|
||||||
|
|
@ -151,7 +167,10 @@ PlutusTx.makeIsDataIndexed
|
||||||
, ('WitnessStake, 4)
|
, ('WitnessStake, 4)
|
||||||
]
|
]
|
||||||
|
|
||||||
-- | Haskell-level datum for Stake scripts.
|
{- | Haskell-level datum for Stake scripts.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
data StakeDatum = StakeDatum
|
data StakeDatum = StakeDatum
|
||||||
{ stakedAmount :: Tagged GTTag Integer
|
{ stakedAmount :: Tagged GTTag Integer
|
||||||
-- ^ Tracks the amount of governance token staked in the datum.
|
-- ^ Tracks the amount of governance token staked in the datum.
|
||||||
|
|
@ -171,7 +190,10 @@ PlutusTx.makeIsDataIndexed ''StakeDatum [('StakeDatum, 0)]
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
-- | Plutarch-level datum for Stake scripts.
|
{- | Plutarch-level datum for Stake scripts.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
newtype PStakeDatum (s :: S) = PStakeDatum
|
newtype PStakeDatum (s :: S) = PStakeDatum
|
||||||
{ getStakeDatum ::
|
{ getStakeDatum ::
|
||||||
Term
|
Term
|
||||||
|
|
@ -183,11 +205,28 @@ newtype PStakeDatum (s :: S) = PStakeDatum
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
deriving stock (GHC.Generic)
|
deriving stock
|
||||||
deriving anyclass (Generic)
|
( -- | @since 0.1.0
|
||||||
deriving anyclass (PIsDataRepr)
|
GHC.Generic
|
||||||
|
)
|
||||||
|
deriving anyclass
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
Generic
|
||||||
|
)
|
||||||
|
deriving anyclass
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
PIsDataRepr
|
||||||
|
)
|
||||||
deriving
|
deriving
|
||||||
(PlutusType, PIsData, PDataFields, PEq)
|
( -- | @since 0.1.0
|
||||||
|
PlutusType
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PIsData
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PDataFields
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PEq
|
||||||
|
)
|
||||||
via (PIsDataReprInstances PStakeDatum)
|
via (PIsDataReprInstances PStakeDatum)
|
||||||
|
|
||||||
instance PTryFrom PData (PAsData PStakeDatum) where
|
instance PTryFrom PData (PAsData PStakeDatum) where
|
||||||
|
|
@ -198,7 +237,10 @@ instance PTryFrom PData (PAsData PStakeDatum) where
|
||||||
instance PUnsafeLiftDecl PStakeDatum where type PLifted PStakeDatum = StakeDatum
|
instance PUnsafeLiftDecl PStakeDatum where type PLifted PStakeDatum = StakeDatum
|
||||||
deriving via (DerivePConstantViaData StakeDatum PStakeDatum) instance (PConstantDecl StakeDatum)
|
deriving via (DerivePConstantViaData StakeDatum PStakeDatum) instance (PConstantDecl StakeDatum)
|
||||||
|
|
||||||
-- | Plutarch-level redeemer for Stake scripts.
|
{- | Plutarch-level redeemer for Stake scripts.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
data PStakeRedeemer (s :: S)
|
data PStakeRedeemer (s :: S)
|
||||||
= -- | Deposit or withdraw a discrete amount of the staked governance token.
|
= -- | Deposit or withdraw a discrete amount of the staked governance token.
|
||||||
PDepositWithdraw (Term s (PDataRecord '["delta" ':= PDiscrete GTTag]))
|
PDepositWithdraw (Term s (PDataRecord '["delta" ':= PDiscrete GTTag]))
|
||||||
|
|
@ -207,11 +249,24 @@ data PStakeRedeemer (s :: S)
|
||||||
| PPermitVote (Term s (PDataRecord '["lock" ':= PProposalLock]))
|
| PPermitVote (Term s (PDataRecord '["lock" ':= PProposalLock]))
|
||||||
| PRetractVotes (Term s (PDataRecord '["locks" ':= PBuiltinList (PAsData PProposalLock)]))
|
| PRetractVotes (Term s (PDataRecord '["locks" ':= PBuiltinList (PAsData PProposalLock)]))
|
||||||
| PWitnessStake (Term s (PDataRecord '[]))
|
| PWitnessStake (Term s (PDataRecord '[]))
|
||||||
deriving stock (GHC.Generic)
|
deriving stock
|
||||||
deriving anyclass (Generic)
|
( -- | @since 0.1.0
|
||||||
deriving anyclass (PIsDataRepr)
|
GHC.Generic
|
||||||
|
)
|
||||||
|
deriving anyclass
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
Generic
|
||||||
|
)
|
||||||
|
deriving anyclass
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
PIsDataRepr
|
||||||
|
)
|
||||||
deriving
|
deriving
|
||||||
(PlutusType, PIsData)
|
( -- | @since 0.1.0
|
||||||
|
PlutusType
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PIsData
|
||||||
|
)
|
||||||
via PIsDataReprInstances PStakeRedeemer
|
via PIsDataReprInstances PStakeRedeemer
|
||||||
|
|
||||||
deriving via
|
deriving via
|
||||||
|
|
@ -222,7 +277,10 @@ deriving via
|
||||||
instance PUnsafeLiftDecl PStakeRedeemer where type PLifted PStakeRedeemer = StakeRedeemer
|
instance PUnsafeLiftDecl PStakeRedeemer where type PLifted PStakeRedeemer = StakeRedeemer
|
||||||
deriving via (DerivePConstantViaData StakeRedeemer PStakeRedeemer) instance (PConstantDecl StakeRedeemer)
|
deriving via (DerivePConstantViaData StakeRedeemer PStakeRedeemer) instance (PConstantDecl StakeRedeemer)
|
||||||
|
|
||||||
-- | Plutarch-level version of 'ProposalLock'.
|
{- | Plutarch-level version of 'ProposalLock'.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
newtype PProposalLock (s :: S) = PProposalLock
|
newtype PProposalLock (s :: S) = PProposalLock
|
||||||
{ getProposalLock ::
|
{ getProposalLock ::
|
||||||
Term
|
Term
|
||||||
|
|
@ -250,7 +308,10 @@ deriving via (DerivePConstantViaData ProposalLock PProposalLock) instance (PCons
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
-- | Check whether a Stake is locked. If it is locked, various actions are unavailable.
|
{- | Check whether a Stake is locked. If it is locked, various actions are unavailable.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
stakeLocked :: forall (s :: S). Term s (PStakeDatum :--> PBool)
|
stakeLocked :: forall (s :: S). Term s (PStakeDatum :--> PBool)
|
||||||
stakeLocked = phoistAcyclic $
|
stakeLocked = phoistAcyclic $
|
||||||
plam $ \stakeDatum ->
|
plam $ \stakeDatum ->
|
||||||
|
|
@ -258,7 +319,10 @@ stakeLocked = phoistAcyclic $
|
||||||
locks = pfield @"lockedBy" # stakeDatum
|
locks = pfield @"lockedBy" # stakeDatum
|
||||||
in pnotNull # locks
|
in pnotNull # locks
|
||||||
|
|
||||||
-- | Find a stake owned by a particular PK.
|
{- | Find a stake owned by a particular PK.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
findStakeOwnedBy ::
|
findStakeOwnedBy ::
|
||||||
Term
|
Term
|
||||||
s
|
s
|
||||||
|
|
@ -281,6 +345,10 @@ findStakeOwnedBy = phoistAcyclic $
|
||||||
PDJust ((pfield @"_0" #) -> dh) ->
|
PDJust ((pfield @"_0" #) -> dh) ->
|
||||||
ptryFindDatum @(PAsData PStakeDatum) # dh # datums
|
ptryFindDatum @(PAsData PStakeDatum) # dh # datums
|
||||||
|
|
||||||
|
{- | Check if a StakeDatum is owned by a particular public key.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
stakeDatumOwnedBy :: Term _ (PPubKeyHash :--> PStakeDatum :--> PBool)
|
stakeDatumOwnedBy :: Term _ (PPubKeyHash :--> PStakeDatum :--> PBool)
|
||||||
stakeDatumOwnedBy =
|
stakeDatumOwnedBy =
|
||||||
phoistAcyclic $
|
phoistAcyclic $
|
||||||
|
|
@ -288,7 +356,10 @@ stakeDatumOwnedBy =
|
||||||
pletFields @'["owner"] (pto stakeDatum) $ \stakeDatumF ->
|
pletFields @'["owner"] (pto stakeDatum) $ \stakeDatumF ->
|
||||||
stakeDatumF.owner #== pdata pk
|
stakeDatumF.owner #== pdata pk
|
||||||
|
|
||||||
-- | Does the input have a `Stake` owned by a particular PK?
|
{- | Does the input have a `Stake` owned by a particular PK?
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
isInputStakeOwnedBy ::
|
isInputStakeOwnedBy ::
|
||||||
Term
|
Term
|
||||||
_
|
_
|
||||||
|
|
@ -317,16 +388,32 @@ isInputStakeOwnedBy =
|
||||||
|
|
||||||
{- | Represent the usage of a stake on a particular proposal.
|
{- | Represent the usage of a stake on a particular proposal.
|
||||||
A stake can be used to either create or vote on a proposal.
|
A stake can be used to either create or vote on a proposal.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
-}
|
-}
|
||||||
data PStakeUsage (s :: S)
|
data PStakeUsage (s :: S)
|
||||||
= PVotedFor (Term s PResultTag)
|
= PVotedFor (Term s PResultTag)
|
||||||
| PCreated
|
| PCreated
|
||||||
| PDidNothing
|
| PDidNothing
|
||||||
deriving stock (GHC.Generic)
|
deriving stock
|
||||||
deriving anyclass (Generic, PlutusType, HasDatatypeInfo, PEq)
|
( -- | @since 0.1.0
|
||||||
|
GHC.Generic
|
||||||
|
)
|
||||||
|
deriving anyclass
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
Generic
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PlutusType
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
HasDatatypeInfo
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PEq
|
||||||
|
)
|
||||||
|
|
||||||
{- | / O(n) /.Return the usage of a stake on a particular proposal,
|
{- | / O(n) /.Return the usage of a stake on a particular proposal,
|
||||||
given the 'lockedBy' field of a stake and the target proposal.
|
given the 'lockedBy' field of a stake and the target proposal.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
-}
|
-}
|
||||||
pgetStakeUsage ::
|
pgetStakeUsage ::
|
||||||
Term
|
Term
|
||||||
|
|
|
||||||
|
|
@ -57,6 +57,8 @@ import Prelude hiding (Num (..))
|
||||||
|
|
||||||
- Check that exactly one state thread is burned.
|
- Check that exactly one state thread is burned.
|
||||||
- Check that datum at state thread is valid and not locked.
|
- Check that datum at state thread is valid and not locked.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
-}
|
-}
|
||||||
stakePolicy ::
|
stakePolicy ::
|
||||||
-- | The (governance) token that a Stake can store.
|
-- | The (governance) token that a Stake can store.
|
||||||
|
|
@ -153,53 +155,55 @@ stakePolicy gtClassRef =
|
||||||
|
|
||||||
{- | Validator intended for Stake UTXOs to be locked by.
|
{- | Validator intended for Stake UTXOs to be locked by.
|
||||||
|
|
||||||
== What this Validator does:
|
== What this Validator does:
|
||||||
|
|
||||||
=== 'DepositWithdraw'
|
=== 'DepositWithdraw'
|
||||||
|
|
||||||
Deposit or withdraw some GT to the stake.
|
Deposit or withdraw some GT to the stake.
|
||||||
|
|
||||||
- Tx must be signed by the owner.
|
- Tx must be signed by the owner.
|
||||||
- The 'stakedAmount' field must be updated.
|
- The 'stakedAmount' field must be updated.
|
||||||
- The stake must not be locked.
|
- The stake must not be locked.
|
||||||
- The new UTXO must have the previous value plus the difference
|
- The new UTXO must have the previous value plus the difference
|
||||||
as stated by the redeemer.
|
as stated by the redeemer.
|
||||||
|
|
||||||
=== 'PermitVote'
|
=== 'PermitVote'
|
||||||
|
|
||||||
Allow a 'ProposalLock' to be put on the stake in order to vote
|
Allow a 'ProposalLock' to be put on the stake in order to vote
|
||||||
on a proposal.
|
on a proposal.
|
||||||
|
|
||||||
- A proposal token must be spent alongside the stake.
|
- A proposal token must be spent alongside the stake.
|
||||||
|
|
||||||
* Its total votes must be correctly updated to include this stake's
|
* Its total votes must be correctly updated to include this stake's
|
||||||
contribution.
|
contribution.
|
||||||
|
|
||||||
- Tx must be signed by the owner.
|
- Tx must be signed by the owner.
|
||||||
|
|
||||||
=== 'RetractVotes'
|
=== 'RetractVotes'
|
||||||
|
|
||||||
Remove a 'ProposalLock' set when voting on a proposal.
|
Remove a 'ProposalLock' set when voting on a proposal.
|
||||||
|
|
||||||
- A proposal token must be spent alongside the stake.
|
- A proposal token must be spent alongside the stake.
|
||||||
- Tx must be signed by the owner.
|
- Tx must be signed by the owner.
|
||||||
|
|
||||||
=== 'Destroy'
|
=== 'Destroy'
|
||||||
|
|
||||||
Destroy the stake in order to reclaim the min ADA.
|
Destroy the stake in order to reclaim the min ADA.
|
||||||
|
|
||||||
- The stake must not be locked.
|
- The stake must not be locked.
|
||||||
- Tx must be signed by the owner.
|
- Tx must be signed by the owner.
|
||||||
|
|
||||||
=== 'WitnessStake'
|
=== 'WitnessStake'
|
||||||
|
|
||||||
Allow this Stake to be included in a transaction without making
|
Allow this Stake to be included in a transaction without making
|
||||||
any changes to it. In the future,
|
any changes to it. In the future,
|
||||||
this could use [CIP-31](https://cips.cardano.org/cips/cip31/) instead.
|
this could use [CIP-31](https://cips.cardano.org/cips/cip31/) instead.
|
||||||
|
|
||||||
- Tx must be signed by the owner __or__ a proposal ST token must be spent
|
- Tx must be signed by the owner __or__ a proposal ST token must be spent
|
||||||
alongside the stake.
|
alongside the stake.
|
||||||
- The datum and value must remain unchanged.
|
- The datum and value must remain unchanged.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
-}
|
-}
|
||||||
stakeValidator :: Stake -> ClosedTerm PValidator
|
stakeValidator :: Stake -> ClosedTerm PValidator
|
||||||
stakeValidator stake =
|
stakeValidator stake =
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ module Agora.Treasury (module Agora.Treasury) where
|
||||||
|
|
||||||
import Agora.AuthorityToken (singleAuthorityTokenBurned)
|
import Agora.AuthorityToken (singleAuthorityTokenBurned)
|
||||||
import GHC.Generics qualified as GHC
|
import GHC.Generics qualified as GHC
|
||||||
import Generics.SOP
|
import Generics.SOP (Generic, I (I))
|
||||||
import Plutarch.Api.V1 (PValidator)
|
import Plutarch.Api.V1 (PValidator)
|
||||||
import Plutarch.Api.V1.Contexts (PScriptPurpose (PMinting))
|
import Plutarch.Api.V1.Contexts (PScriptPurpose (PMinting))
|
||||||
import "plutarch" Plutarch.Api.V1.Value (PValue)
|
import "plutarch" Plutarch.Api.V1.Value (PValue)
|
||||||
|
|
@ -26,14 +26,23 @@ import Plutarch.TryFrom ()
|
||||||
import PlutusLedgerApi.V1.Value (CurrencySymbol)
|
import PlutusLedgerApi.V1.Value (CurrencySymbol)
|
||||||
import PlutusTx qualified
|
import PlutusTx qualified
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
{- | Redeemer for Treasury actions.
|
||||||
|
|
||||||
-- | Redeemer for Treasury actions.
|
@since 0.1.0
|
||||||
|
-}
|
||||||
data TreasuryRedeemer
|
data TreasuryRedeemer
|
||||||
= -- | Allow transaction to pass by delegating to GAT burn.
|
= -- | Allow transaction to pass by delegating to GAT burn.
|
||||||
SpendTreasuryGAT
|
SpendTreasuryGAT
|
||||||
deriving stock (Eq, Show, GHC.Generic)
|
deriving stock
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
Eq
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
Show
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
GHC.Generic
|
||||||
|
)
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
PlutusTx.makeIsDataIndexed
|
PlutusTx.makeIsDataIndexed
|
||||||
''TreasuryRedeemer
|
''TreasuryRedeemer
|
||||||
[ ('SpendTreasuryGAT, 0)
|
[ ('SpendTreasuryGAT, 0)
|
||||||
|
|
@ -43,24 +52,42 @@ PlutusTx.makeIsDataIndexed
|
||||||
|
|
||||||
{- | Plutarch level type representing valid redeemers of the
|
{- | Plutarch level type representing valid redeemers of the
|
||||||
treasury.
|
treasury.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
-}
|
-}
|
||||||
newtype PTreasuryRedeemer (s :: S)
|
newtype PTreasuryRedeemer (s :: S)
|
||||||
= -- | Alters treasury parameters, subject to the burning of a
|
= -- | Alters treasury parameters, subject to the burning of a
|
||||||
-- governance authority token.
|
-- governance authority token.
|
||||||
PSpendTreasuryGAT (Term s (PDataRecord '[]))
|
PSpendTreasuryGAT (Term s (PDataRecord '[]))
|
||||||
deriving stock (GHC.Generic)
|
deriving stock
|
||||||
deriving anyclass (Generic, PIsDataRepr)
|
( -- | @since 0.1.0
|
||||||
|
GHC.Generic
|
||||||
|
)
|
||||||
|
deriving anyclass
|
||||||
|
( -- | @since 0.1.0
|
||||||
|
Generic
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PIsDataRepr
|
||||||
|
)
|
||||||
deriving
|
deriving
|
||||||
(PlutusType, PIsData)
|
( -- | @since 0.1.0
|
||||||
|
PlutusType
|
||||||
|
, -- | @since 0.1.0
|
||||||
|
PIsData
|
||||||
|
)
|
||||||
via PIsDataReprInstances PTreasuryRedeemer
|
via PIsDataReprInstances PTreasuryRedeemer
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
deriving via
|
deriving via
|
||||||
PAsData (PIsDataReprInstances PTreasuryRedeemer)
|
PAsData (PIsDataReprInstances PTreasuryRedeemer)
|
||||||
instance
|
instance
|
||||||
PTryFrom PData (PAsData PTreasuryRedeemer)
|
PTryFrom PData (PAsData PTreasuryRedeemer)
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
instance PUnsafeLiftDecl PTreasuryRedeemer where
|
instance PUnsafeLiftDecl PTreasuryRedeemer where
|
||||||
type PLifted PTreasuryRedeemer = TreasuryRedeemer
|
type PLifted PTreasuryRedeemer = TreasuryRedeemer
|
||||||
|
|
||||||
|
-- | @since 0.1.0
|
||||||
deriving via
|
deriving via
|
||||||
(DerivePConstantViaData TreasuryRedeemer PTreasuryRedeemer)
|
(DerivePConstantViaData TreasuryRedeemer PTreasuryRedeemer)
|
||||||
instance
|
instance
|
||||||
|
|
@ -70,6 +97,8 @@ deriving via
|
||||||
|
|
||||||
{- | 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.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
-}
|
-}
|
||||||
treasuryValidator ::
|
treasuryValidator ::
|
||||||
-- | Governance Authority Token that can unlock this validator.
|
-- | Governance Authority Token that can unlock this validator.
|
||||||
|
|
|
||||||
|
|
@ -21,18 +21,6 @@ module Agora.Utils (
|
||||||
isPubKey,
|
isPubKey,
|
||||||
) where
|
) where
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
import PlutusLedgerApi.V1 (
|
|
||||||
Address (..),
|
|
||||||
Credential (..),
|
|
||||||
CurrencySymbol,
|
|
||||||
TokenName (..),
|
|
||||||
ValidatorHash (..),
|
|
||||||
)
|
|
||||||
|
|
||||||
--------------------------------------------------------------------------------
|
|
||||||
|
|
||||||
import Plutarch.Api.V1 (
|
import Plutarch.Api.V1 (
|
||||||
AmountGuarantees,
|
AmountGuarantees,
|
||||||
KeyGuarantees,
|
KeyGuarantees,
|
||||||
|
|
@ -56,12 +44,22 @@ import "liqwid-plutarch-extra" Plutarch.Api.V1.Value (psymbolValueOf)
|
||||||
import Plutarch.Builtin (pforgetData)
|
import Plutarch.Builtin (pforgetData)
|
||||||
import Plutarch.Extra.List (plookupTuple)
|
import Plutarch.Extra.List (plookupTuple)
|
||||||
import Plutarch.Extra.TermCont (pletC, pmatchC)
|
import Plutarch.Extra.TermCont (pletC, pmatchC)
|
||||||
|
import PlutusLedgerApi.V1 (
|
||||||
|
Address (..),
|
||||||
|
Credential (..),
|
||||||
|
CurrencySymbol,
|
||||||
|
TokenName (..),
|
||||||
|
ValidatorHash (..),
|
||||||
|
)
|
||||||
|
|
||||||
{- Functions which should (probably) not be upstreamed
|
{- Functions which should (probably) not be upstreamed
|
||||||
All of these functions are quite inefficient.
|
All of these functions are quite inefficient.
|
||||||
-}
|
-}
|
||||||
|
|
||||||
-- | Get script hash from an Address.
|
{- | Get script hash from an Address.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
scriptHashFromAddress :: Term s (PAddress :--> PMaybe PValidatorHash)
|
scriptHashFromAddress :: Term s (PAddress :--> PMaybe PValidatorHash)
|
||||||
scriptHashFromAddress = phoistAcyclic $
|
scriptHashFromAddress = phoistAcyclic $
|
||||||
plam $ \addr ->
|
plam $ \addr ->
|
||||||
|
|
@ -69,12 +67,18 @@ scriptHashFromAddress = phoistAcyclic $
|
||||||
PScriptCredential ((pfield @"_0" #) -> h) -> pcon $ PJust h
|
PScriptCredential ((pfield @"_0" #) -> h) -> pcon $ PJust h
|
||||||
_ -> pcon PNothing
|
_ -> pcon PNothing
|
||||||
|
|
||||||
-- | Return true if the given address is a script address.
|
{- | Return true if the given address is a script address.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
isScriptAddress :: Term s (PAddress :--> PBool)
|
isScriptAddress :: Term s (PAddress :--> PBool)
|
||||||
isScriptAddress = phoistAcyclic $
|
isScriptAddress = phoistAcyclic $
|
||||||
plam $ \addr -> pnot #$ isPubKey #$ pfromData $ pfield @"credential" # addr
|
plam $ \addr -> pnot #$ isPubKey #$ pfromData $ pfield @"credential" # addr
|
||||||
|
|
||||||
-- | Return true if the given credential is a pub-key-hash.
|
{- | Return true if the given credential is a pub-key-hash.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
isPubKey :: Term s (PCredential :--> PBool)
|
isPubKey :: Term s (PCredential :--> PBool)
|
||||||
isPubKey = phoistAcyclic $
|
isPubKey = phoistAcyclic $
|
||||||
plam $ \cred ->
|
plam $ \cred ->
|
||||||
|
|
@ -82,7 +86,10 @@ isPubKey = phoistAcyclic $
|
||||||
PScriptCredential _ -> pconstant False
|
PScriptCredential _ -> pconstant False
|
||||||
_ -> pconstant True
|
_ -> pconstant True
|
||||||
|
|
||||||
-- | Find all TxOuts sent to an Address
|
{- | Find all TxOuts sent to an Address
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
findOutputsToAddress :: Term s (PBuiltinList (PAsData PTxOut) :--> PAddress :--> PBuiltinList (PAsData PTxOut))
|
findOutputsToAddress :: Term s (PBuiltinList (PAsData PTxOut) :--> PAddress :--> PBuiltinList (PAsData PTxOut))
|
||||||
findOutputsToAddress = phoistAcyclic $
|
findOutputsToAddress = phoistAcyclic $
|
||||||
plam $ \outputs address' -> unTermCont $ do
|
plam $ \outputs address' -> unTermCont $ do
|
||||||
|
|
@ -91,7 +98,10 @@ findOutputsToAddress = phoistAcyclic $
|
||||||
pfilter # plam (\(pfromData -> txOut) -> pfield @"address" # txOut #== address)
|
pfilter # plam (\(pfromData -> txOut) -> pfield @"address" # txOut #== address)
|
||||||
# outputs
|
# outputs
|
||||||
|
|
||||||
-- | Find the data corresponding to a TxOut, if there is one
|
{- | Find the data corresponding to a TxOut, if there is one
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
findTxOutDatum :: Term s (PBuiltinList (PAsData (PTuple PDatumHash PDatum)) :--> PTxOut :--> PMaybe PDatum)
|
findTxOutDatum :: Term s (PBuiltinList (PAsData (PTuple PDatumHash PDatum)) :--> PTxOut :--> PMaybe PDatum)
|
||||||
findTxOutDatum = phoistAcyclic $
|
findTxOutDatum = phoistAcyclic $
|
||||||
plam $ \datums out -> unTermCont $ do
|
plam $ \datums out -> unTermCont $ do
|
||||||
|
|
@ -102,19 +112,30 @@ findTxOutDatum = phoistAcyclic $
|
||||||
|
|
||||||
{- | Safely convert a 'PValidatorHash' into a 'PTokenName'. This can be useful for tagging
|
{- | Safely convert a 'PValidatorHash' into a 'PTokenName'. This can be useful for tagging
|
||||||
tokens for extra safety.
|
tokens for extra safety.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
-}
|
-}
|
||||||
validatorHashToTokenName :: ValidatorHash -> TokenName
|
validatorHashToTokenName :: ValidatorHash -> TokenName
|
||||||
validatorHashToTokenName (ValidatorHash hash) = TokenName hash
|
validatorHashToTokenName (ValidatorHash hash) = TokenName hash
|
||||||
|
|
||||||
-- | Plutarch level 'validatorHashToTokenName'.
|
{- | Plutarch level 'validatorHashToTokenName'.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
pvalidatorHashToTokenName :: forall (s :: S). Term s PValidatorHash -> Term s PTokenName
|
pvalidatorHashToTokenName :: forall (s :: S). Term s PValidatorHash -> Term s PTokenName
|
||||||
pvalidatorHashToTokenName vh = pcon (PTokenName (pto vh))
|
pvalidatorHashToTokenName vh = pcon (PTokenName (pto vh))
|
||||||
|
|
||||||
-- | Get the CurrencySymbol of a PMintingPolicy.
|
{- | Get the CurrencySymbol of a PMintingPolicy.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
getMintingPolicySymbol :: ClosedTerm PMintingPolicy -> CurrencySymbol
|
getMintingPolicySymbol :: ClosedTerm PMintingPolicy -> CurrencySymbol
|
||||||
getMintingPolicySymbol v = mintingPolicySymbol $ mkMintingPolicy v
|
getMintingPolicySymbol v = mintingPolicySymbol $ mkMintingPolicy v
|
||||||
|
|
||||||
-- | The entire value only contains one token of the given currency symbol.
|
{- | The entire value only contains one token of the given currency symbol.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
hasOnlyOneTokenOfCurrencySymbol ::
|
hasOnlyOneTokenOfCurrencySymbol ::
|
||||||
forall (keys :: KeyGuarantees) (amounts :: AmountGuarantees) (s :: S).
|
forall (keys :: KeyGuarantees) (amounts :: AmountGuarantees) (s :: S).
|
||||||
Term s (PCurrencySymbol :--> PValue keys amounts :--> PBool)
|
Term s (PCurrencySymbol :--> PValue keys amounts :--> PBool)
|
||||||
|
|
@ -123,7 +144,10 @@ hasOnlyOneTokenOfCurrencySymbol = phoistAcyclic $
|
||||||
psymbolValueOf # cs # vs #== 1
|
psymbolValueOf # cs # vs #== 1
|
||||||
#&& (plength #$ pto $ pto $ pto vs) #== 1
|
#&& (plength #$ pto $ pto $ pto vs) #== 1
|
||||||
|
|
||||||
-- | Find datum given a maybe datum hash
|
{- | Find datum given a maybe datum hash
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
mustFindDatum' ::
|
mustFindDatum' ::
|
||||||
forall (datum :: PType).
|
forall (datum :: PType).
|
||||||
(PIsData datum, PTryFrom PData (PAsData datum)) =>
|
(PIsData datum, PTryFrom PData (PAsData datum)) =>
|
||||||
|
|
@ -143,6 +167,8 @@ mustFindDatum' = phoistAcyclic $
|
||||||
|
|
||||||
{- | Extract the value stored in a PMaybe container.
|
{- | Extract the value stored in a PMaybe container.
|
||||||
If there's no value, throw an error with the given message.
|
If there's no value, throw an error with the given message.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
-}
|
-}
|
||||||
mustBePJust :: forall a s. Term s (PString :--> PMaybe a :--> a)
|
mustBePJust :: forall a s. Term s (PString :--> PMaybe a :--> a)
|
||||||
mustBePJust = phoistAcyclic $
|
mustBePJust = phoistAcyclic $
|
||||||
|
|
@ -152,6 +178,8 @@ mustBePJust = phoistAcyclic $
|
||||||
|
|
||||||
{- | Extract the value stored in a PMaybeData container.
|
{- | Extract the value stored in a PMaybeData container.
|
||||||
If there's no value, throw an error with the given message.
|
If there's no value, throw an error with the given message.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
-}
|
-}
|
||||||
mustBePDJust :: forall a s. (PIsData a) => Term s (PString :--> PMaybeData a :--> a)
|
mustBePDJust :: forall a s. (PIsData a) => Term s (PString :--> PMaybeData a :--> a)
|
||||||
mustBePDJust = phoistAcyclic $
|
mustBePDJust = phoistAcyclic $
|
||||||
|
|
@ -159,6 +187,9 @@ mustBePDJust = phoistAcyclic $
|
||||||
PDJust ((pfield @"_0" #) -> v) -> v
|
PDJust ((pfield @"_0" #) -> v) -> v
|
||||||
_ -> ptraceError emsg
|
_ -> ptraceError emsg
|
||||||
|
|
||||||
-- | Create an 'Address' from a given 'ValidatorHash' with no 'PlutusLedgerApi.V1.Credential.StakingCredential'.
|
{- | Create an 'Address' from a given 'ValidatorHash' with no 'PlutusLedgerApi.V1.Credential.StakingCredential'.
|
||||||
|
|
||||||
|
@since 0.1.0
|
||||||
|
-}
|
||||||
validatorHashToAddress :: ValidatorHash -> Address
|
validatorHashToAddress :: ValidatorHash -> Address
|
||||||
validatorHashToAddress vh = Address (ScriptCredential vh) Nothing
|
validatorHashToAddress vh = Address (ScriptCredential vh) Nothing
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue