Liquid Staking

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

Unbounded loop in withdraw() may cause LST tokens to be locked in the contract

Summary

The withdraw() has an unbounded loop with external calls. If the gas costs of functions change between when deposits are made and when rewards are withdrawn, or if the gas cost of the deposit (safetransferFrom()) is less than the gas cost of the withdrawal (safetransfer()), then the withdraw() function may revert due to exceeding the block size gas limit.

https://github.com/Cyfrin/2024-09-stakelink/blob/f5824f9ad67058b24a2c08494e51ddd7efdbb90b/contracts/core/priorityPool/WithdrawalPool.sol#L260

Vulnerability Details

1) The withdraw() function processes a list of withdrawal requests, transferring Liquid Staking Tokens (LSTs) from the contract to the user based on the withdrawal IDs and corresponding batch IDs provided by the caller.

Parameters

_withdrawalIds (uint256[]): List of IDs representing the queued withdrawals that the caller wishes to process.

_batchIds (uint256[]): List of batch IDs corresponding to the withdrawal IDs. Used to verify and compute withdrawal amounts.

External Call

token.safeTransfer(owner, amountToWithdraw): This function transfers the total amount of LSTs calculated from the withdrawal requests to the caller

2) The withdraw function contains a loop that iterates over the entire length of the _withdrawalIds array, making it unbounded. Since there is no limit on the number of withdrawal IDs a user can submit, if the array is too large, the loop may consume too much gas, potentially causing the transaction to revert if it exceeds the block gas limit.

  • The cost of executing the safeTransfer() in the withdrawal process may be higher than the gas cost of deposits (safeTransferFrom()), especially if rewards have accumulated or multiple withdrawals are being processed. If the gas cost increases between the time of deposit and the time of withdrawal (e.g., due to changes in the EVM gas schedule or network congestion), this could cause the withdrawal function to revert.

  • If the transaction reverts due to gas issues, all LST** in the affected withdrawals would remain locked in the contract** until a successful withdrawal can be processed.

Impact

This could create a scenario where users are unable to withdraw their tokens, particularly if they attempt to process large batches of withdrawals in a single transaction.

Tools Used

manual

Recommendations

Allow the specification of an offset and length to the withdraw() function, so that withdrawals can be broken up into smaller batches if required.

Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

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