A malicious RESDL token holder can queue a withrawal request, then queue any subsequent number of extended lock durations in order to effectively earn receive more withdrawal tokens.
A malicious user of the protocol on the secondary pool can essentially request a withdrawal by call the withdraw() function, which will in turn queue a new lock update.
Then the user proceeds to call the extendLockDuration() function with incremental duration times not exceeding the maximum lock duration, this can be done any number of times before an update.
In turn after the current update batch has been updated then the user proceeds to execute their updates.
The execution of such a call chain will end up in the function _executeQueuedLockUpdates() in which the exploit emanates from the line
int256 baseAmountDiff = int256(updateLockState.amount) - int256(curLockState.amount);
the error in this statement comes from the subtraction of current update state which will be zero and the current lock state which is not updated for the current lockID.
Although this is one exploit the root cause lies in putting the line
Lock memory curLockState = locks[lockId];
outside the loop
while (j < numUpdates) {...}
This in turn will allow a user to re-enter the withdrawal block of the if statement in the while loop, since baseAmountDiff is less than zero.
Loss of funds.
Manual Review
I would recommend putting the line
Lock memory curLockState = locks[lockId];
inside the while loop to get the updated lock for each lockId subsequent update
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.