fix bugs and vulnerabilities in premoveLocks

This commit is contained in:
Hongrui Fang 2022-11-24 21:06:59 +08:00
parent 02164c13b2
commit edb982abaa

View file

@ -50,7 +50,6 @@ import Agora.Stake (
), ),
pstakeLocked, pstakeLocked,
) )
import Data.Functor ((<&>))
import Plutarch.Api.V1.Address (PCredential) import Plutarch.Api.V1.Address (PCredential)
import Plutarch.Api.V2 (PMaybeData, PPOSIXTime) import Plutarch.Api.V2 (PMaybeData, PPOSIXTime)
import Plutarch.Extra.Bool (passert) import Plutarch.Extra.Bool (passert)
@ -60,7 +59,7 @@ import "liqwid-plutarch-extra" Plutarch.Extra.List (
ptryDeleteFirstBy, ptryDeleteFirstBy,
ptryFromSingleton, ptryFromSingleton,
) )
import Plutarch.Extra.Maybe (pdjust, pdnothing, pjust, pmaybe, pmaybeData, pnothing) import Plutarch.Extra.Maybe (pdjust, pdnothing, pmaybeData)
import Plutarch.Extra.Record (mkRecordConstr, (.&), (.=)) import Plutarch.Extra.Record (mkRecordConstr, (.&), (.=))
import "liqwid-plutarch-extra" Plutarch.Extra.TermCont (pguardC, pletC, pletFieldsC, pmatchC) import "liqwid-plutarch-extra" Plutarch.Extra.TermCont (pguardC, pletC, pletFieldsC, pmatchC)
import Plutarch.Extra.Time (PCurrentTime (PCurrentTime)) import Plutarch.Extra.Time (PCurrentTime (PCurrentTime))
@ -269,14 +268,14 @@ instance DerivePlutusType PRemoveLocksMode where
{- | Remove stake locks with the proposal id given the list of existing locks. {- | Remove stake locks with the proposal id given the list of existing locks.
The first parameter controls whether to remove creator locks or not. If The first parameter controls whether to remove creator locks or not. If
one of the locks performed voting action, the unlock cooldown will be one of the locks performed voting action, the unlock cooldown will be
checked if it's given. checked.
-} -}
premoveLocks :: premoveLocks ::
forall (s :: S). forall (s :: S).
Term Term
s s
( PProposalId ( PProposalId
:--> PMaybe PPOSIXTime :--> PPOSIXTime
:--> PProposalTime :--> PProposalTime
:--> PRemoveLocksMode :--> PRemoveLocksMode
:--> PBuiltinList (PAsData PProposalLock) :--> PBuiltinList (PAsData PProposalLock)
@ -293,19 +292,18 @@ premoveLocks =
( (pfield @"createdAt" #) -> ( (pfield @"createdAt" #) ->
createdAt createdAt
) = ) =
let notInCooldown = let notInCooldown = createdAt + unlockCooldown #<= lowerBound
pmaybe
# pconstant True
# plam (\c -> createdAt + c #<= lowerBound)
# unlockCooldown
in foldl1 in foldl1
(#||) (#||)
[ shouldRemoveAllLocks [ shouldRemoveAllLocks
, ptraceIfFalse "Stake lock in cooldown" notInCooldown , -- Fail the transaction if a voter lock is in cooldown.∏
passert
"Voter lock shouldn't be in cooldown"
notInCooldown
(pconstant True)
] ]
handleLock = shouldRemoveLock =
plam $
flip flip
pletAll pletAll
( \lockF -> ( \lockF ->
@ -319,6 +317,9 @@ premoveLocks =
) )
. pfromData . pfromData
-- Return true, given a lock that should be kept.
handleLock = plam $ (pnot #) . shouldRemoveLock
pure $ pfilter # handleLock pure $ pfilter # handleLock
{- | Default implementation of 'Agora.Stake.RetractVotes'. {- | Default implementation of 'Agora.Stake.RetractVotes'.
@ -340,18 +341,13 @@ pretractVote = pvoteHelper #$ phoistAcyclic $
] ]
proposal proposal
(mode, unlockCooldown) <- let unlockCooldown =
pmatchC (proposalF.status #== pconstant Finished) <&> \case pfield @"minStakeVotingTime"
PTrue ->
( pcon PRemoveAllLocks
, pnothing
)
_ ->
( pcon PRemoveVoterLockOnly
, pjust
#$ pfield @"minStakeVotingTime"
# proposalF.timingConfig # proposalF.timingConfig
)
mode = pmatch (proposalF.status #== pconstant Finished) $ \case
PTrue -> pcon PRemoveAllLocks
_ -> pcon PRemoveVoterLockOnly
pguardC "Authorized by either opwner or delegatee" $ pguardC "Authorized by either opwner or delegatee" $
pisSignedBy # pconstant True # ctx pisSignedBy # pconstant True # ctx