Liquid Staking

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

Erroneous call to `priorityPool::canWithdraw` in `WithdrawalPool::performUpkeep` causes perpetual reversion

Summary

When WithdrawalPool::performUpkeep calls priorityPool::canWithdraw, it mistakenly passes address(WithdrawalPool) as the account to check for queued tokens. Since the WithdrawalPool contract itself is not a depositor and never has queued tokens, this results in the function reading zero queued tokens. Consequently, the condition for withdrawing is never met, causing performUpkeep to revert every time.

Vulnerability Details

In the WithdrawalPool::performUpkeep function, the _account parameter passed to priorityPool::canWithdraw is set to address(this)—the address of the WithdrawalPool contract. This is problematic because WithdrawalPool is not an external user and does not queue deposits, unlike regular depositors. As a result, when getQueuedTokens() is called on the PriorityPool, the accountQueuedTokens mapping is accessed for the WithdrawalPool contract's address, which always returns zero, since the WithdrawalPool contract never interacts with the mapping to queue tokens.

This erroneous interaction occurs in the following code snippet:

function performUpkeep(bytes calldata _performData) external {
uint256 canWithdraw = priorityPool.canWithdraw(address(this), 0);
uint256 totalQueued = _getStakeByShares(totalQueuedShareWithdrawals);
if (
totalQueued == 0 ||
canWithdraw == 0 ||
block.timestamp <= timeOfLastWithdrawal + minTimeBetweenWithdrawals
) revert NoUpkeepNeeded();
// ...
}

Impact

This issue disrupts a core functionality of the protocol. The inability of performUpkeep to proceed due to the perpetual reversion effectively breaks the withdrawal process. Since this function plays a critical role in maintaining the flow of withdrawals, the protocol cannot operate as intended without this bug being fixed.

Tools Used

Manual

Recommendations

Use a correct approach to get the total amount of tokens available in the deposit queue. Consider introducing a dedicated function for that.

Updates

Lead Judging Commences

inallhonesty Lead Judge
11 months ago
inallhonesty Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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