fix bugs and vulnerabilities in premoveLocks

This commit is contained in:
Hongrui Fang 2022-11-24 21:06:59 +08:00
parent 1fe39ae5a7
commit cefc6740f0
No known key found for this signature in database
GPG key ID: F2D0D08AF77AC599

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,31 +292,33 @@ 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 -> foldl1
foldl1 (#&&)
(#&&) [ proposalId #== lockF.proposalId
[ proposalId #== lockF.proposalId , pmatch lockF.action $ \case
, pmatch lockF.action $ \case PVoted r -> handleVoter r
PVoted r -> handleVoter r _ -> shouldRemoveAllLocks
_ -> shouldRemoveAllLocks ]
] )
) . pfromData
. pfromData
-- Return true, given a lock that should be kept.
handleLock = plam $ (pnot #) . shouldRemoveLock
pure $ pfilter # handleLock pure $ pfilter # handleLock
@ -340,18 +341,13 @@ pretractVote = pvoteHelper #$ phoistAcyclic $
] ]
proposal proposal
(mode, unlockCooldown) <- let unlockCooldown =
pmatchC (proposalF.status #== pconstant Finished) <&> \case pfield @"minStakeVotingTime"
PTrue -> # proposalF.timingConfig
( pcon PRemoveAllLocks
, pnothing mode = pmatch (proposalF.status #== pconstant Finished) $ \case
) PTrue -> pcon PRemoveAllLocks
_ -> _ -> pcon PRemoveVoterLockOnly
( pcon PRemoveVoterLockOnly
, pjust
#$ pfield @"minStakeVotingTime"
# proposalF.timingConfig
)
pguardC "Authorized by either opwner or delegatee" $ pguardC "Authorized by either opwner or delegatee" $
pisSignedBy # pconstant True # ctx pisSignedBy # pconstant True # ctx