When a user locks RAACToken
to get veRAAC
, they can lock tokens again, and the previous data gets overridden. This behavior breaks the system mechanics as described below.
In veRAACToken::lock()
, there is no check to determine if the user has already locked tokens for a given period. This leads to the state of _lockState.locks[msg.sender]
being overwritten with new amounts and lock durations.
A user can call veRAACToken::lock()
multiple times with smaller amounts and shorter durations because there are no checks to prevent it.
Follow along with the comments in the code to understand the flow. You can see the code here:
createLock()
: No check for an existing lock. See here.
_updateBoostState()
: No check for an existing lock. See here.
calculateAndUpdatePower()
: Only validates duration and amount, but not if a lock already exists. See here.
Incorrect Code Logic: Other functions that manipulate locks do check for existing locks and act accordingly. The lock
function is inconsistent in this regard.
Token Loss Risk: If a user calls lock()
multiple times, some tokens can get stuck in the contract because withdrawal functions read the overwritten amount
value to use in the transfer. Neither withdraw()
nor emergencyWithdraw()
can recover these tokens, as the value has been reset. See withdraw here and emergency withdraw here.
Add a check to prevent a user from locking more tokens if they already have an active lock. Users should use the existing incerase()
to do so:
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.