Liquid Staking

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

Unbounded Gas Consumption in `withdraw` Function

Summary

withdraw function in the WithdrawalPool contract is vulnerable to unbounded gas consumption due to the lack of a limit on the number of withdrawals processed in a single transaction. This can lead to failed transactions, increased gas costs, and potential denial-of-service.

Vulnerability Details

The withdraw function allows users to withdraw their queued funds by providing an array of _withdrawalIds and corresponding _batchIds. However, there is no limit on the number of withdrawal IDs that can be passed to the function, which can lead to excessive gas consumption and potential denial-of-service.

In the withdraw function: https://github.com/Cyfrin/2024-09-stakelink/blob/f5824f9ad67058b24a2c08494e51ddd7efdbb90b/contracts/core/priorityPool/WithdrawalPool.sol#L264-L268

// <@audit The loop iterates through all provided withdrawal IDs without any limit
for (uint256 i = 0; i < _withdrawalIds.length; ++i) {
uint256 withdrawalId = _withdrawalIds[i];
Withdrawal memory withdrawal = queuedWithdrawals[_withdrawalIds[i]];
uint256 batchId = _batchIds[i];
WithdrawalBatch memory batch = withdrawalBatches[batchId];
// ...
}

The function iterates through all the provided _withdrawalIds and processes each withdrawal, regardless of the number of IDs passed. This can lead to a scenario where a user provides a large number of withdrawal IDs, causing the function to consume a significant amount of gas and potentially exceeding the block gas limit.

Impact

If a user provides a large number of withdrawal IDs, the transaction may exceed the block gas limit and revert, preventing the user from withdrawing their funds. In extreme cases, this could render the contract unusable for withdrawals.

Tools Used

Manual Review

Recommendations

  1. Adding a limit on the maximum number of withdrawals that can be processed in a single withdraw call.

  2. Splitting the withdraw function into multiple calls if the number of withdrawals exceeds a certain threshold.

  3. Allowing users to withdraw a subset of their queued withdrawals at a time.


    Or:

+ uint256 private constant MAX_WITHDRAWALS_PER_TX = 100;
function withdraw(uint256[] calldata _withdrawalIds, uint256[] calldata _batchIds) external {
+ require(_withdrawalIds.length <= MAX_WITHDRAWALS_PER_TX, "Too many withdrawals");
// ... (rest of the function)
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 8 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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