Liquid Staking

Stakelink
DeFiHardhatOracle
50,000 USDC
View results
Submission Details
Severity: low
Invalid

Incorrect Time Comparison in `WithdrawalPool::checkUpKeep` May Cause Delayed Execution

Summary

The checkUpKeep function is responsible for determining whether withdrawals should be executed by checking two conditions: the availability of withdrawal space and whether enough time has passed since the last withdrawal. However, the current time check logic is flawed, which could lead to unnecessary delays in executing withdrawals.

/**
* @notice Returns whether withdrawals should be executed based on available withdrawal space
* @return true if withdrawal should be executed, false otherwise
*/
function checkUpkeep(bytes calldata) external view returns (bool, bytes memory) {
if (
_getStakeByShares(totalQueuedShareWithdrawals) != 0 && priorityPool.canWithdraw(address(this), 0) != 0
@> && block.timestamp > timeOfLastWithdrawal + minTimeBetweenWithdrawals <@
) {
return (true, "");
}
return (false, "");
}

Vulnerability Details

The issue lies in how the function checks if the required time interval between withdrawals has passed. The condition uses block.timestamp > timeOfLastWithdrawal + minTimeBetweenWithdrawals, which only allows the upkeep to trigger if the timestamp is strictly greater than the sum of the last withdrawal time and the minimum interval. This means that if the current block.timestamp equals the calculated threshold (i.e., exactly when the interval elapses), the condition will incorrectly return false, delaying the upkeep until a future block.

Impact

This faulty comparison can result in a delayed execution of withdrawals, as the upkeep will not be triggered precisely when the minimum time requirement is met. While the function will eventually allow execution in subsequent blocks, this delay could affect user experience or system efficiency, particularly in time-sensitive scenarios.

Tools Used

Manual Review, Solodit Checklist

Recommendations

Update the comparison to use a >= check, ensuring that withdrawals are triggered as soon as the minimum time interval has elapsed:

/**
* @notice Returns whether withdrawals should be executed based on available withdrawal space
* @return true if withdrawal should be executed, false otherwise
*/
function checkUpkeep(bytes calldata) external view returns (bool, bytes memory) {
if (
_getStakeByShares(totalQueuedShareWithdrawals) != 0 && priorityPool.canWithdraw(address(this), 0) != 0
- && block.timestamp > timeOfLastWithdrawal + minTimeBetweenWithdrawals
+ && block.timestamp >= timeOfLastWithdrawal + minTimeBetweenWithdrawals
) {
return (true, "");
}
return (false, "");
}
Updates

Lead Judging Commences

inallhonesty Lead Judge
11 months ago
inallhonesty Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Known issue

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.