The current implementation of the withdraw function allows users to bypass the intended withdrawal restrictions after loopActivation has been set and before startClaimDate. This could potentially allow users to withdraw their tokens at times when they should instead be using the claim functionality. This breaks an invariant :
* Note Can only be called after the loop address is set and before claiming lpETH, * i.e. for at least TIMELOCK. In emergency mode can be called at any time.
Proof of Concept
The absence of a check for block.timestamp >= startClaimDate for non-ETH token withdrawals in the smart contract code allows users to withdraw tokens at any time, without adhering to the intended time constraints set by loopActivation and startClaimDate.
else {
// @audit no check on (block.timestamp >= startClaimDate) which means can withdraw at any time
IERC20(_token).safeTransfer(msg.sender, lockedAmount);
}
Tools Used
Manual review
Recommended Mitigation Steps
Consider adding the same check for non-ETH tokens :
if (block.timestamp >= startClaimDate) {
revert NoLongerPossible();
}
Lines of code
https://github.com/code-423n4/2024-05-loop/blob/40167e469edde09969643b6808c57e25d1b9c203/src/PrelaunchPoints.sol#L301-L302
Vulnerability details
Impact
The current implementation of the
withdraw
function allows users to bypass the intended withdrawal restrictions afterloopActivation
has been set and beforestartClaimDate
. This could potentially allow users to withdraw their tokens at times when they should instead be using the claim functionality. This breaks an invariant :Proof of Concept
The absence of a check for
block.timestamp >= startClaimDate
for non-ETH token withdrawals in the smart contract code allows users to withdraw tokens at any time, without adhering to the intended time constraints set byloopActivation
andstartClaimDate
.Tools Used
Manual review
Recommended Mitigation Steps
Consider adding the same check for non-ETH tokens :
Assessed type
Other