hacky fix for stake policy using filtered <=

This commit is contained in:
Emily Martins 2022-03-21 18:11:38 +01:00
parent 3f642daaf1
commit d8aa028814
2 changed files with 74 additions and 5 deletions

View file

@ -19,9 +19,12 @@ module Agora.Stake (
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
import Data.Proxy (Proxy (Proxy))
import Data.String (IsString (fromString))
import GHC.Generics qualified as GHC import GHC.Generics qualified as GHC
import GHC.TypeLits ( import GHC.TypeLits (
KnownSymbol, KnownSymbol,
symbolVal,
) )
import Generics.SOP (Generic, I (I)) import Generics.SOP (Generic, I (I))
import Prelude import Prelude
@ -50,6 +53,7 @@ import Plutarch.DataRepr (
) )
import Plutarch.Internal (punsafeCoerce) import Plutarch.Internal (punsafeCoerce)
import Plutarch.Monadic qualified as P import Plutarch.Monadic qualified as P
import Plutus.V1.Ledger.Value (AssetClass (AssetClass))
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
@ -65,6 +69,9 @@ import Agora.Utils (
paddValue, paddValue,
passert, passert,
pfindTxInByTxOutRef, pfindTxInByTxOutRef,
pgeqBy,
pgeqBy',
pgeqBySymbol,
psingletonValue, psingletonValue,
psymbolValueOf, psymbolValueOf,
ptxSignedBy, ptxSignedBy,
@ -200,8 +207,28 @@ stakePolicy _stake =
# ctx.txInfo # ctx.txInfo
# stakeDatum.owner # stakeDatum.owner
-- TODO: Needs to be >=, rather than == -- TODO: This is quite inefficient now, as it does two lookups
let valueCorrect = pdata value #== pdata expectedValue -- instead of a more efficient single pass,
-- but it doesn't really matter for this. At least it's correct.
let valueCorrect =
foldr1
(#&&)
[ pgeqBy' (AssetClass ("", "")) # value # expectedValue
, pgeqBy'
( AssetClass
( fromString . symbolVal $ Proxy @ac
, fromString . symbolVal $ Proxy @n
)
)
# value
# expectedValue
, pgeqBy
# ownSymbol
# tn
# value
# expectedValue
]
ownerSignsTransaction ownerSignsTransaction
#&& valueCorrect #&& valueCorrect
popaque (pconstant ()) popaque (pconstant ())
@ -274,9 +301,27 @@ stakeValidator stake =
#&& (paddDiscrete # stakeDatum.stakedAmount # delta) #== newStakeDatum.stakedAmount #&& (paddDiscrete # stakeDatum.stakedAmount # delta) #== newStakeDatum.stakedAmount
let expectedValue = paddValue # continuingValue # (pdiscreteValue # delta) let expectedValue = paddValue # continuingValue # (pdiscreteValue # delta)
-- TODO: As above, needs to be >=, rather than == -- TODO: Same as above. This is quite inefficient now, as it does two lookups
let correctValue = pdata value #== pdata expectedValue -- instead of a more efficient single pass,
isScriptAddress #&& correctOutputDatum #&& correctValue -- but it doesn't really matter for this. At least it's correct.
let valueCorrect =
foldr1
(#&&)
[ pgeqBy' (AssetClass ("", "")) # value # expectedValue
, pgeqBy'
( AssetClass
( fromString . symbolVal $ Proxy @ac
, fromString . symbolVal $ Proxy @n
)
)
# value
# expectedValue
, pgeqBySymbol
# stCurrencySymbol
# value
# expectedValue
]
isScriptAddress #&& correctOutputDatum #&& valueCorrect
popaque (pconstant ()) popaque (pconstant ())

View file

@ -19,6 +19,9 @@ module Agora.Utils (
psymbolValueOf, psymbolValueOf,
passetClassValueOf, passetClassValueOf,
passetClassValueOf', passetClassValueOf',
pgeqBy,
pgeqBySymbol,
pgeqBy',
pfindTxInByTxOutRef, pfindTxInByTxOutRef,
psingletonValue, psingletonValue,
pfindMap, pfindMap,
@ -180,6 +183,27 @@ passetClassValueOf' :: AssetClass -> Term s (PValue :--> PInteger)
passetClassValueOf' (AssetClass (sym, token)) = passetClassValueOf' (AssetClass (sym, token)) =
passetClassValueOf # pconstant sym # pconstant token passetClassValueOf # pconstant sym # pconstant token
-- | Return '>=' on two values comparing by only a particular AssetClass
pgeqBy :: Term s (PCurrencySymbol :--> PTokenName :--> PValue :--> PValue :--> PBool)
pgeqBy =
phoistAcyclic $
plam $ \cs tn a b ->
passetClassValueOf # cs # tn # b #<= passetClassValueOf # cs # tn # a
-- | Return '>=' on two values comparing by only a particular AssetClass
pgeqBySymbol :: Term s (PCurrencySymbol :--> PValue :--> PValue :--> PBool)
pgeqBySymbol =
phoistAcyclic $
plam $ \cs a b ->
psymbolValueOf # cs # b #<= psymbolValueOf # cs # a
-- | Return '>=' on two values comparing by only a particular Haskell-level AssetClass
pgeqBy' :: AssetClass -> Term s (PValue :--> PValue :--> PBool)
pgeqBy' ac =
phoistAcyclic $
plam $ \a b ->
passetClassValueOf' ac # b #<= passetClassValueOf' ac # a
-- | Union two maps using a merge function on collisions. -- | Union two maps using a merge function on collisions.
pmapUnionWith :: forall k v s. PIsData v => Term s ((v :--> v :--> v) :--> PMap k v :--> PMap k v :--> PMap k v) pmapUnionWith :: forall k v s. PIsData v => Term s ((v :--> v :--> v) :--> PMap k v :--> PMap k v :--> PMap k v)
pmapUnionWith = phoistAcyclic $ pmapUnionWith = phoistAcyclic $