Use liqwid-script-export
commit ec70bfd539fe2e27fd48f5f76395400287ac72d7
Author: Seungheon Oh <seungheon.ooh@gmail.com>
Date: Tue Oct 18 18:58:59 2022 -0500
use LSE
commit 25fff9b3ad1f2dde4cd7cf36977530b06a87d23c
Merge: 01cd3aa a5567ea
Author: Seungheon Oh <seungheon.ooh@gmail.com>
Date: Tue Oct 18 18:17:45 2022 -0500
Merge branch 'staging' into seungheonoh/ply
commit 01cd3aa7a235e6fe6658246ca1026fa26dc71a83
Author: Hongrui Fang <chfanghr@gmail.com>
Date: Tue Oct 11 12:02:03 2022 +0800
update benchmark
commit a8513244892ce33cfdc9edf8cd501c4985ae8008
Author: Hongrui Fang <chfanghr@gmail.com>
Date: Tue Oct 11 11:59:22 2022 +0800
fix tests
commit 20ca40823485c2e2f78253643cf4453ac7b7ddd5
Author: Hongrui Fang <chfanghr@gmail.com>
Date: Tue Oct 11 11:57:37 2022 +0800
better import
commit a19fe49424210891bd03db71e4083fc1e0edfd98
Author: Hongrui Fang <chfanghr@gmail.com>
Date: Tue Oct 11 11:08:20 2022 +0800
update flake inputs
commit c93b21f1f9441e5c6f54525bf7c6a54757ec36cc
Author: Seungheon Oh <seungheon.ooh@gmail.com>
Date: Mon Oct 10 12:54:12 2022 -0500
tried to make tests pass
commit 1046ae1237299a33c58b48661bdb6d325a22147e
Merge: 2bf4e36 e2bd48b
Author: Seungheon Oh <seungheon.ooh@gmail.com>
Date: Mon Oct 10 12:18:48 2022 -0500
Merge branch 'staging' into seungheonoh/ply
commit 2bf4e3627c1b229f58078695082da85c80efd560
Author: Seungheon Oh <seungheon.ooh@gmail.com>
Date: Mon Oct 10 10:48:36 2022 -0500
remove junkpile
commit a1dbc9ad9e531fe0d0a0480c4aef9cf9ffa90f1d
Author: Seungheon Oh <seungheon.ooh@gmail.com>
Date: Mon Oct 10 10:47:25 2022 -0500
versions
commit 4542a06ac733858297d3a48c53368fad19dedc43
Author: Seungheon Oh <seungheon.ooh@gmail.com>
Date: Thu Oct 6 22:57:48 2022 -0500
script exporting interface
commit 6bd8c1a1d57e4bf9dc25c3068a9c8eae6bf6a19d
Author: Seungheon Oh <seungheon.ooh@gmail.com>
Date: Thu Oct 6 22:58:41 2022 -0500
fixed tests
commit d3ce2cf95633d336f3e621833677bd5bf10ee2c8
Author: Seungheon Oh <seungheon.ooh@gmail.com>
Date: Sun Oct 2 00:55:18 2022 -0500
fixed tests
commit 1ae64c9f692652b77b0506013853b2ba44267c65
Author: Seungheon Oh <seungheon.ooh@gmail.com>
Date: Sat Oct 1 13:28:20 2022 -0500
linker
commit db88cb75c7b74843141ad8ab4e6522b66d0dcfbc
Author: Seungheon Oh <seungheon.ooh@gmail.com>
Date: Sat Oct 1 01:03:50 2022 -0500
exporting scripts
commit 6389fce28e885a8a7f8669629c266f59c0edb51f
Author: Seungheon Oh <seungheon.ooh@gmail.com>
Date: Sat Oct 1 00:51:49 2022 -0500
made scripts parameterized on the script level
commit aea1e518a8890550bdebd0e5251da11d915c53a9
Author: Seungheon Oh <seungheon.ooh@gmail.com>
Date: Wed Sep 28 19:53:29 2022 -0500
Use `TypedScriptEnvelope` for `Agora.Bootstrap`
This commit is contained in:
parent
a5567eaa5e
commit
275d3a5b69
38 changed files with 8614 additions and 2330 deletions
|
|
@ -13,12 +13,6 @@ module Agora.Stake.Scripts (
|
|||
|
||||
import Agora.Credential (authorizationContext, pauthorizedBy)
|
||||
import Agora.Proposal (PProposalDatum, PProposalRedeemer)
|
||||
import Agora.SafeMoney (GTTag)
|
||||
import Agora.Scripts (
|
||||
AgoraScripts,
|
||||
proposalSTAssetClass,
|
||||
stakeSTSymbol,
|
||||
)
|
||||
import Agora.Stake (
|
||||
PProposalContext (
|
||||
PNewProposal,
|
||||
|
|
@ -62,16 +56,13 @@ import Agora.Stake.Redeemers (
|
|||
pretractVote,
|
||||
)
|
||||
import Agora.Utils (passert, pmapMaybe)
|
||||
import Data.Tagged (Tagged (Tagged))
|
||||
import Plutarch.Api.V1 (
|
||||
KeyGuarantees (Sorted),
|
||||
PCredential (PPubKeyCredential, PScriptCredential),
|
||||
PCurrencySymbol,
|
||||
PTokenName,
|
||||
)
|
||||
import Plutarch.Api.V1.AssocMap (plookup)
|
||||
import Plutarch.Api.V1.Value (PValue)
|
||||
import Plutarch.Api.V2 (
|
||||
AmountGuarantees,
|
||||
PMintingPolicy,
|
||||
PScriptPurpose (PMinting, PSpending),
|
||||
PTxInfo,
|
||||
|
|
@ -79,7 +70,7 @@ import Plutarch.Api.V2 (
|
|||
PValidator,
|
||||
)
|
||||
import Plutarch.Extra.AssetClass (
|
||||
passetClass,
|
||||
PAssetClass,
|
||||
passetClassValueOf,
|
||||
pvalueOf,
|
||||
)
|
||||
|
|
@ -114,10 +105,8 @@ import Plutarch.Extra.Value (
|
|||
import Plutarch.Num (PNum (pnegate))
|
||||
import Plutarch.SafeMoney (
|
||||
pvalueDiscrete,
|
||||
pvalueDiscrete',
|
||||
)
|
||||
import Plutarch.Unsafe (punsafeCoerce)
|
||||
import PlutusLedgerApi.V1.Value (AssetClass (AssetClass))
|
||||
import Prelude hiding (Num ((+)))
|
||||
|
||||
{- | Policy for Stake state threads.
|
||||
|
|
@ -137,14 +126,18 @@ import Prelude hiding (Num ((+)))
|
|||
- Check that exactly one state thread is burned.
|
||||
- Check that datum at state thread is valid and not locked.
|
||||
|
||||
@since 0.1.0
|
||||
== Arguments
|
||||
|
||||
Following arguments should be provided(in this order):
|
||||
1. governor ST assetclass
|
||||
|
||||
@since 1.0.0
|
||||
-}
|
||||
stakePolicy ::
|
||||
-- | The (governance) token that a Stake can store.
|
||||
Tagged GTTag AssetClass ->
|
||||
ClosedTerm PMintingPolicy
|
||||
stakePolicy gtClassRef =
|
||||
plam $ \_redeemer ctx' -> unTermCont $ do
|
||||
ClosedTerm (PAssetClass :--> PMintingPolicy)
|
||||
stakePolicy =
|
||||
plam $ \gstClass _redeemer ctx' -> unTermCont $ do
|
||||
ctx <- pletFieldsC @'["txInfo", "purpose"] ctx'
|
||||
txInfo <- pletC $ ctx.txInfo
|
||||
let _a :: Term _ PTxInfo
|
||||
|
|
@ -226,7 +219,7 @@ stakePolicy gtClassRef =
|
|||
|
||||
let hasExpectedStake =
|
||||
ptraceIfFalse "Stake ouput has expected amount of stake token" $
|
||||
pvalueDiscrete' gtClassRef # outputF.value #== datumF.stakedAmount
|
||||
pvalueDiscrete # gstClass # outputF.value #== datumF.stakedAmount
|
||||
let ownerSignsTransaction =
|
||||
ptraceIfFalse "Stake Owner should sign the transaction" $
|
||||
pauthorizedBy
|
||||
|
|
@ -243,338 +236,319 @@ stakePolicy gtClassRef =
|
|||
|
||||
{- | Create a stake validator, given the implementation of stake redeemers.
|
||||
|
||||
== Arguments
|
||||
|
||||
Following arguments should be provided(in this order):
|
||||
1. stake ST symbol
|
||||
2. proposal ST assetclass
|
||||
3. governor ST assetclass
|
||||
|
||||
@since 1.0.0
|
||||
-}
|
||||
mkStakeValidator ::
|
||||
StakeRedeemerImpl ->
|
||||
AgoraScripts ->
|
||||
Tagged GTTag AssetClass ->
|
||||
ClosedTerm PValidator
|
||||
mkStakeValidator
|
||||
impl
|
||||
as
|
||||
(Tagged (AssetClass (gtSym, gtTn))) =
|
||||
plam $ \_datum redeemer ctx -> unTermCont $ do
|
||||
let sstValueOf ::
|
||||
( forall (ag :: AmountGuarantees) (s :: S).
|
||||
Term s (PValue 'Sorted ag :--> PInteger)
|
||||
)
|
||||
sstValueOf =
|
||||
phoistAcyclic $
|
||||
psymbolValueOf # pconstant (stakeSTSymbol as)
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
ctxF <- pletFieldsC @'["txInfo", "purpose"] ctx
|
||||
txInfo <- pletC $ pfromData ctxF.txInfo
|
||||
txInfoF <-
|
||||
pletFieldsC
|
||||
@'[ "inputs"
|
||||
, "referenceInputs"
|
||||
, "outputs"
|
||||
, "mint"
|
||||
, "validRange"
|
||||
, "signatories"
|
||||
, "redeemers"
|
||||
, "datums"
|
||||
]
|
||||
txInfo
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
PSpending stakeInputRef <- pmatchC $ pfromData ctxF.purpose
|
||||
|
||||
let validatedInput =
|
||||
pfield @"resolved"
|
||||
#$ passertPJust
|
||||
# "Malformed script context: validated input not found"
|
||||
#$ pfindTxInByTxOutRef
|
||||
# (pfield @"_0" # stakeInputRef)
|
||||
# txInfoF.inputs
|
||||
|
||||
stakeValidatorCredential =
|
||||
pfield @"credential"
|
||||
#$ pfield @"address" # validatedInput
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
-- Returns stake datum if the given UTxO is a stake UTxO.
|
||||
getStakeDatum :: Term _ (PTxOut :--> PMaybe PStakeDatum) <-
|
||||
pletC $
|
||||
plam $
|
||||
flip (pletFields @'["value", "datum", "address"]) $ \txOutF ->
|
||||
pmatch
|
||||
( pcompareBy # pfromOrd
|
||||
# (sstValueOf # txOutF.value)
|
||||
# 1
|
||||
)
|
||||
$ \case
|
||||
-- > 1
|
||||
PGT -> ptraceError "More than one SST in one UTxO"
|
||||
-- 1
|
||||
PEQ ->
|
||||
let ownerCredential = pfield @"credential" # txOutF.address
|
||||
|
||||
isOwnedByStakeValidator =
|
||||
ownerCredential #== stakeValidatorCredential
|
||||
|
||||
datum =
|
||||
ptrace "Resolve stake datum" $
|
||||
pfromData $
|
||||
pfromOutputDatum @(PAsData PStakeDatum)
|
||||
# txOutF.datum
|
||||
# txInfoF.datums
|
||||
in passert
|
||||
"Should owned by stake validator"
|
||||
isOwnedByStakeValidator
|
||||
(pjust # datum)
|
||||
-- 0
|
||||
PLT -> pnothing
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
-- Find all stake inputs.
|
||||
|
||||
stakeInputDatums <-
|
||||
pletC $
|
||||
pmapMaybe
|
||||
# plam ((getStakeDatum #) . (pfield @"resolved" #))
|
||||
# pfromData txInfoF.inputs
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
-- Assemble the signature context.
|
||||
|
||||
firstStakeInputDatumF <-
|
||||
pletFieldsC @'["owner", "delegatedTo"] $
|
||||
phead # stakeInputDatums
|
||||
|
||||
restOfStakeInputDatums <- pletC $ ptail # stakeInputDatums
|
||||
|
||||
authorizedBy <- pletC $ pauthorizedBy # authorizationContext txInfoF
|
||||
|
||||
PPair allHaveSameOwner allHaveSameDelegatee <-
|
||||
pmatchC $
|
||||
pfoldr
|
||||
# plam
|
||||
( \d p -> unTermCont $ do
|
||||
dF <- pletFieldsC @'["owner", "delegatedTo"] d
|
||||
|
||||
pure $
|
||||
pmatch p $ \(PPair allHaveSameOwner allHaveSameDelegatee) ->
|
||||
let allHaveSameOwner' =
|
||||
allHaveSameOwner
|
||||
#&& dF.owner #== firstStakeInputDatumF.owner
|
||||
allHaveSameDelegatee' =
|
||||
allHaveSameDelegatee
|
||||
#&& dF.delegatedTo #== firstStakeInputDatumF.delegatedTo
|
||||
in pcon $ PPair allHaveSameOwner' allHaveSameDelegatee'
|
||||
)
|
||||
# pcon (PPair (pconstant True) (pconstant True))
|
||||
# restOfStakeInputDatums
|
||||
|
||||
let ownerSignsTransaction =
|
||||
allHaveSameOwner
|
||||
#&& authorizedBy # firstStakeInputDatumF.owner
|
||||
|
||||
delegateSignsTransaction =
|
||||
allHaveSameDelegatee
|
||||
#&& pmaybeData
|
||||
# pconstant False
|
||||
# plam ((authorizedBy #) . pfromData)
|
||||
# pfromData firstStakeInputDatumF.delegatedTo
|
||||
|
||||
signedBy =
|
||||
pif
|
||||
ownerSignsTransaction
|
||||
(pcon PSignedByOwner)
|
||||
$ pif
|
||||
delegateSignsTransaction
|
||||
(pcon PSignedByDelegate)
|
||||
$ pcon PUnknownSig
|
||||
|
||||
sigContext <-
|
||||
pletC $
|
||||
pcon $
|
||||
PSigContext
|
||||
firstStakeInputDatumF.owner
|
||||
firstStakeInputDatumF.delegatedTo
|
||||
signedBy
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
-- Find all stake outputs.
|
||||
|
||||
let gtAssetClass = passetClass # pconstant gtSym # pconstant gtTn
|
||||
|
||||
-- First step of validating stake outputs. We make sure that every stake
|
||||
-- output UTxO carries correct amount of GTs specified by its datum.
|
||||
--
|
||||
-- Note that non-GT assets are treated transparently.
|
||||
stakeOutputDatums <-
|
||||
pletC $
|
||||
pmapMaybe
|
||||
# plam
|
||||
( \output ->
|
||||
let validateGT = plam $ \stakeDatum ->
|
||||
let expected = pfield @"stakedAmount" # stakeDatum
|
||||
|
||||
actual =
|
||||
pvalueDiscrete
|
||||
# gtAssetClass
|
||||
# (pfield @"value" # output)
|
||||
in pif
|
||||
(expected #== actual)
|
||||
stakeDatum
|
||||
(ptraceError "Unmatched GT value")
|
||||
in pfmap
|
||||
# validateGT
|
||||
# (getStakeDatum # output)
|
||||
)
|
||||
# pfromData txInfoF.outputs
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
mintedST <- pletC $ sstValueOf # txInfoF.mint
|
||||
|
||||
pguardC "No new SST minted" $
|
||||
foldl1
|
||||
(#||)
|
||||
[ ptraceIfTrue "All stakes burnt" $
|
||||
mintedST #< 0 #&& pnull # stakeOutputDatums
|
||||
, ptraceIfTrue "Nothing burnt" $
|
||||
mintedST #== 0
|
||||
ClosedTerm (PCurrencySymbol :--> PAssetClass :--> PAssetClass :--> PValidator)
|
||||
mkStakeValidator impl =
|
||||
plam $ \sstSymbol pstClass gstClass _datum redeemer ctx -> unTermCont $ do
|
||||
ctxF <- pletFieldsC @'["txInfo", "purpose"] ctx
|
||||
txInfo <- pletC $ pfromData ctxF.txInfo
|
||||
txInfoF <-
|
||||
pletFieldsC
|
||||
@'[ "inputs"
|
||||
, "referenceInputs"
|
||||
, "outputs"
|
||||
, "mint"
|
||||
, "validRange"
|
||||
, "signatories"
|
||||
, "redeemers"
|
||||
, "datums"
|
||||
]
|
||||
txInfo
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
-- Assemble the proposal context.
|
||||
PSpending stakeInputRef <- pmatchC $ pfromData ctxF.purpose
|
||||
|
||||
let AssetClass (propCs, propTn) = proposalSTAssetClass as
|
||||
let validatedInput =
|
||||
pfield @"resolved"
|
||||
#$ passertPJust
|
||||
# "Malformed script context: validated input not found"
|
||||
#$ pfindTxInByTxOutRef
|
||||
# (pfield @"_0" # stakeInputRef)
|
||||
# txInfoF.inputs
|
||||
|
||||
proposalSTClass <-
|
||||
pletC $
|
||||
passetClass
|
||||
# pconstant propCs
|
||||
# pconstant propTn
|
||||
stakeValidatorCredential =
|
||||
pfield @"credential"
|
||||
#$ pfield @"address" # validatedInput
|
||||
|
||||
getProposalDatum <- pletC $
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
-- Returns stake datum if the given UTxO is a stake UTxO.
|
||||
getStakeDatum :: Term _ (PTxOut :--> PMaybe PStakeDatum) <-
|
||||
pletC $
|
||||
plam $
|
||||
flip pletAll $ \txOutF ->
|
||||
let isProposalUTxO =
|
||||
passetClassValueOf
|
||||
# txOutF.value
|
||||
# proposalSTClass #== 1
|
||||
proposalDatum =
|
||||
pfromData $
|
||||
pfromOutputDatum @(PAsData PProposalDatum)
|
||||
# txOutF.datum
|
||||
# txInfoF.datums
|
||||
in pif isProposalUTxO (pjust # proposalDatum) pnothing
|
||||
flip (pletFields @'["value", "datum", "address"]) $ \txOutF ->
|
||||
pmatch
|
||||
( pcompareBy # pfromOrd
|
||||
# (psymbolValueOf # sstSymbol # txOutF.value)
|
||||
# 1
|
||||
)
|
||||
$ \case
|
||||
-- > 1
|
||||
PGT -> ptraceError "More than one SST in one UTxO"
|
||||
-- 1
|
||||
PEQ ->
|
||||
let ownerCredential = pfield @"credential" # txOutF.address
|
||||
|
||||
let pstMinted =
|
||||
passetClassValueOf # txInfoF.mint # proposalSTClass #== 1
|
||||
isOwnedByStakeValidator =
|
||||
ownerCredential #== stakeValidatorCredential
|
||||
|
||||
newProposalContext =
|
||||
pcon $
|
||||
PNewProposal $
|
||||
pfield @"proposalId"
|
||||
#$ passertPJust # "Proposal output should present"
|
||||
#$ pfindJust # getProposalDatum # pfromData txInfoF.outputs
|
||||
datum =
|
||||
ptrace "Resolve stake datum" $
|
||||
pfromData $
|
||||
pfromOutputDatum @(PAsData PStakeDatum)
|
||||
# txOutF.datum
|
||||
# txInfoF.datums
|
||||
in passert
|
||||
"Should owned by stake validator"
|
||||
isOwnedByStakeValidator
|
||||
(pjust # datum)
|
||||
-- 0
|
||||
PLT -> pnothing
|
||||
|
||||
spendProposalContext =
|
||||
let getProposalRedeemer = plam $ \ref ->
|
||||
flip (ptryFrom @PProposalRedeemer) fst $
|
||||
pto $
|
||||
passertPJust
|
||||
# "Malformed script context: propsoal input not found in redeemer map"
|
||||
#$ plookup
|
||||
# pcon
|
||||
( PSpending $
|
||||
pdcons @_0
|
||||
# pdata ref
|
||||
# pdnil
|
||||
)
|
||||
# txInfoF.redeemers
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
getContext = plam $
|
||||
flip pletAll $ \inInfoF ->
|
||||
pfmap
|
||||
# plam
|
||||
( \proposalDatum ->
|
||||
let id = pfield @"proposalId" # proposalDatum
|
||||
status = pfield @"status" # proposalDatum
|
||||
redeemer = getProposalRedeemer # inInfoF.outRef
|
||||
in pcon $ PSpendProposal id status redeemer
|
||||
)
|
||||
#$ getProposalDatum
|
||||
# pfromData inInfoF.resolved
|
||||
-- Find all stake inputs.
|
||||
|
||||
contexts =
|
||||
pmapMaybe @PList # getContext # pfromData txInfoF.inputs
|
||||
in -- Can only handle one proposal at a time.
|
||||
precList
|
||||
( \_ h t ->
|
||||
pif
|
||||
(pnull # t)
|
||||
(pjust # h)
|
||||
(ptraceError "Ambiguous proposal")
|
||||
)
|
||||
(const pnothing)
|
||||
# contexts
|
||||
stakeInputDatums <-
|
||||
pletC $
|
||||
pmapMaybe
|
||||
# plam ((getStakeDatum #) . (pfield @"resolved" #))
|
||||
# pfromData txInfoF.inputs
|
||||
|
||||
noProposalContext = pcon PNoProposal
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
proposalContext <-
|
||||
pletC $
|
||||
-- Assemble the signature context.
|
||||
|
||||
firstStakeInputDatumF <-
|
||||
pletFieldsC @'["owner", "delegatedTo"] $
|
||||
phead # stakeInputDatums
|
||||
|
||||
restOfStakeInputDatums <- pletC $ ptail # stakeInputDatums
|
||||
|
||||
authorizedBy <- pletC $ pauthorizedBy # authorizationContext txInfoF
|
||||
|
||||
PPair allHaveSameOwner allHaveSameDelegatee <-
|
||||
pmatchC $
|
||||
pfoldr
|
||||
# plam
|
||||
( \d p -> unTermCont $ do
|
||||
dF <- pletFieldsC @'["owner", "delegatedTo"] d
|
||||
|
||||
pure $
|
||||
pmatch p $ \(PPair allHaveSameOwner allHaveSameDelegatee) ->
|
||||
let allHaveSameOwner' =
|
||||
allHaveSameOwner
|
||||
#&& dF.owner #== firstStakeInputDatumF.owner
|
||||
allHaveSameDelegatee' =
|
||||
allHaveSameDelegatee
|
||||
#&& dF.delegatedTo #== firstStakeInputDatumF.delegatedTo
|
||||
in pcon $ PPair allHaveSameOwner' allHaveSameDelegatee'
|
||||
)
|
||||
# pcon (PPair (pconstant True) (pconstant True))
|
||||
# restOfStakeInputDatums
|
||||
|
||||
let ownerSignsTransaction =
|
||||
allHaveSameOwner
|
||||
#&& authorizedBy # firstStakeInputDatumF.owner
|
||||
|
||||
delegateSignsTransaction =
|
||||
allHaveSameDelegatee
|
||||
#&& pmaybeData
|
||||
# pconstant False
|
||||
# plam ((authorizedBy #) . pfromData)
|
||||
# pfromData firstStakeInputDatumF.delegatedTo
|
||||
|
||||
signedBy =
|
||||
pif
|
||||
pstMinted
|
||||
newProposalContext
|
||||
(pfromMaybe # noProposalContext # spendProposalContext)
|
||||
ownerSignsTransaction
|
||||
(pcon PSignedByOwner)
|
||||
$ pif
|
||||
delegateSignsTransaction
|
||||
(pcon PSignedByDelegate)
|
||||
$ pcon PUnknownSig
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
sigContext <-
|
||||
pletC $
|
||||
pcon $
|
||||
PSigContext
|
||||
firstStakeInputDatumF.owner
|
||||
firstStakeInputDatumF.delegatedTo
|
||||
signedBy
|
||||
|
||||
-- Assemeble the redeemer handler context.
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
mkRedeemerhandlerContext <- pletC $
|
||||
plam $ \redeemerContext ->
|
||||
-- Find all stake outputs.
|
||||
-- First step of validating stake outputs. We make sure that every stake
|
||||
-- output UTxO carries correct amount of GTs specified by its datum.
|
||||
--
|
||||
-- Note that non-GT assets are treated transparently.
|
||||
stakeOutputDatums <-
|
||||
pletC $
|
||||
pmapMaybe
|
||||
# plam
|
||||
( \output ->
|
||||
let validateGT = plam $ \stakeDatum ->
|
||||
let expected = pfield @"stakedAmount" # stakeDatum
|
||||
|
||||
actual =
|
||||
pvalueDiscrete
|
||||
# gstClass
|
||||
# (pfield @"value" # output)
|
||||
in pif
|
||||
(expected #== actual)
|
||||
stakeDatum
|
||||
(ptraceError "Unmatched GT value")
|
||||
in pfmap
|
||||
# validateGT
|
||||
# (getStakeDatum # output)
|
||||
)
|
||||
# pfromData txInfoF.outputs
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
mintedST <- pletC $ psymbolValueOf # sstSymbol # txInfoF.mint
|
||||
|
||||
pguardC "No new SST minted" $
|
||||
foldl1
|
||||
(#||)
|
||||
[ ptraceIfTrue "All stakes burnt" $
|
||||
mintedST #< 0 #&& pnull # stakeOutputDatums
|
||||
, ptraceIfTrue "Nothing burnt" $
|
||||
mintedST #== 0
|
||||
]
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
-- Assemble the proposal context.
|
||||
|
||||
getProposalDatum <- pletC $
|
||||
plam $
|
||||
flip pletAll $ \txOutF ->
|
||||
let isProposalUTxO =
|
||||
passetClassValueOf
|
||||
# txOutF.value
|
||||
# pstClass #== 1
|
||||
proposalDatum =
|
||||
pfromData $
|
||||
pfromOutputDatum @(PAsData PProposalDatum)
|
||||
# txOutF.datum
|
||||
# txInfoF.datums
|
||||
in pif isProposalUTxO (pjust # proposalDatum) pnothing
|
||||
|
||||
let pstMinted =
|
||||
passetClassValueOf # txInfoF.mint # pstClass #== 1
|
||||
|
||||
newProposalContext =
|
||||
pcon $
|
||||
PStakeRedeemerHandlerContext
|
||||
stakeInputDatums
|
||||
stakeOutputDatums
|
||||
redeemerContext
|
||||
sigContext
|
||||
proposalContext
|
||||
txInfo
|
||||
PNewProposal $
|
||||
pfield @"proposalId"
|
||||
#$ passertPJust # "Proposal output should present"
|
||||
#$ pfindJust # getProposalDatum # pfromData txInfoF.outputs
|
||||
|
||||
noMetadataContext <-
|
||||
pletC $
|
||||
mkRedeemerhandlerContext
|
||||
#$ pcon
|
||||
$ PNoMetadata
|
||||
spendProposalContext =
|
||||
let getProposalRedeemer = plam $ \ref ->
|
||||
flip (ptryFrom @PProposalRedeemer) fst $
|
||||
pto $
|
||||
passertPJust
|
||||
# "Malformed script context: propsoal input not found in redeemer map"
|
||||
#$ plookup
|
||||
# pcon
|
||||
( PSpending $
|
||||
pdcons @_0
|
||||
# pdata ref
|
||||
# pdnil
|
||||
)
|
||||
# txInfoF.redeemers
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
getContext = plam $
|
||||
flip pletAll $ \inInfoF ->
|
||||
pfmap
|
||||
# plam
|
||||
( \proposalDatum ->
|
||||
let id = pfield @"proposalId" # proposalDatum
|
||||
status = pfield @"status" # proposalDatum
|
||||
redeemer = getProposalRedeemer # inInfoF.outRef
|
||||
in pcon $ PSpendProposal id status redeemer
|
||||
)
|
||||
#$ getProposalDatum
|
||||
# pfromData inInfoF.resolved
|
||||
|
||||
-- Call the redeemer handler.
|
||||
contexts =
|
||||
pmapMaybe @PList # getContext # pfromData txInfoF.inputs
|
||||
in -- Can only handle one proposal at a time.
|
||||
precList
|
||||
( \_ h t ->
|
||||
pif
|
||||
(pnull # t)
|
||||
(pjust # h)
|
||||
(ptraceError "Ambiguous proposal")
|
||||
)
|
||||
(const pnothing)
|
||||
# contexts
|
||||
|
||||
stakeRedeemer <- fst <$> ptryFromC redeemer
|
||||
noProposalContext = pcon PNoProposal
|
||||
|
||||
pure $
|
||||
popaque $
|
||||
pmatch stakeRedeemer $ \case
|
||||
PDestroy _ -> runStakeRedeemerHandler impl.onDestroy # noMetadataContext
|
||||
PPermitVote _ -> runStakeRedeemerHandler impl.onPermitVote # noMetadataContext
|
||||
PRetractVotes _ -> runStakeRedeemerHandler impl.onRetractVote # noMetadataContext
|
||||
PClearDelegate _ -> runStakeRedeemerHandler impl.onClearDelegate # noMetadataContext
|
||||
PDelegateTo ((pfield @"pkh" #) -> pkh) ->
|
||||
runStakeRedeemerHandler impl.onDelegateTo
|
||||
#$ mkRedeemerhandlerContext
|
||||
#$ pcon
|
||||
$ PSetDelegateTo pkh
|
||||
PDepositWithdraw ((pfield @"delta" #) -> delta) ->
|
||||
runStakeRedeemerHandler impl.onDepositWithdraw #$ mkRedeemerhandlerContext
|
||||
#$ pcon
|
||||
$ PDepositWithdrawDelta delta
|
||||
proposalContext <-
|
||||
pletC $
|
||||
pif
|
||||
pstMinted
|
||||
newProposalContext
|
||||
(pfromMaybe # noProposalContext # spendProposalContext)
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
-- Assemeble the redeemer handler context.
|
||||
|
||||
mkRedeemerhandlerContext <- pletC $
|
||||
plam $ \redeemerContext ->
|
||||
pcon $
|
||||
PStakeRedeemerHandlerContext
|
||||
stakeInputDatums
|
||||
stakeOutputDatums
|
||||
redeemerContext
|
||||
sigContext
|
||||
proposalContext
|
||||
txInfo
|
||||
|
||||
noMetadataContext <-
|
||||
pletC $
|
||||
mkRedeemerhandlerContext
|
||||
#$ pcon
|
||||
$ PNoMetadata
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
-- Call the redeemer handler.
|
||||
|
||||
stakeRedeemer <- fst <$> ptryFromC redeemer
|
||||
|
||||
pure $
|
||||
popaque $
|
||||
pmatch stakeRedeemer $ \case
|
||||
PDestroy _ -> runStakeRedeemerHandler impl.onDestroy # noMetadataContext
|
||||
PPermitVote _ -> runStakeRedeemerHandler impl.onPermitVote # noMetadataContext
|
||||
PRetractVotes _ -> runStakeRedeemerHandler impl.onRetractVote # noMetadataContext
|
||||
PClearDelegate _ -> runStakeRedeemerHandler impl.onClearDelegate # noMetadataContext
|
||||
PDelegateTo ((pfield @"pkh" #) -> pkh) ->
|
||||
runStakeRedeemerHandler impl.onDelegateTo
|
||||
#$ mkRedeemerhandlerContext
|
||||
#$ pcon
|
||||
$ PSetDelegateTo pkh
|
||||
PDepositWithdraw ((pfield @"delta" #) -> delta) ->
|
||||
runStakeRedeemerHandler impl.onDepositWithdraw #$ mkRedeemerhandlerContext
|
||||
#$ pcon
|
||||
$ PDepositWithdrawDelta delta
|
||||
|
||||
{- | Validator intended for Stake UTXOs to be locked by.
|
||||
|
||||
|
|
@ -617,14 +591,16 @@ mkStakeValidator
|
|||
- The stakes must not be locked.
|
||||
- Tx must be signed by the owner.
|
||||
|
||||
@since 0.1.0
|
||||
== Arguments
|
||||
|
||||
Following arguments should be provided(in this order):
|
||||
1. stake ST symbol
|
||||
2. proposal ST assetclass
|
||||
3. governor ST assetclass
|
||||
|
||||
@since 1.0.0
|
||||
-}
|
||||
stakeValidator ::
|
||||
-- | Lazy precompiled scripts.
|
||||
AgoraScripts ->
|
||||
-- | See 'Agora.Governor.Governor.gtClassRef'.
|
||||
Tagged GTTag AssetClass ->
|
||||
ClosedTerm PValidator
|
||||
stakeValidator :: ClosedTerm (PCurrencySymbol :--> PAssetClass :--> PAssetClass :--> PValidator)
|
||||
stakeValidator =
|
||||
mkStakeValidator $
|
||||
StakeRedeemerImpl
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue