_finalizeWithdrawals function is called by the deposit function to process queued withdrawals when new tokens are deposited. However, _finalizeWithdrawal has a logic flaw in how it updates the totalQueuedShareWithdrawals variable.
Iit's possible that not all of these shares will actually be used to finalize withdrawals, if the total amount of queued withdrawals is less than sharesToWithdraw. In this case, totalQueuedShareWithdrawals will be decreased by more than the actual amount of shares used, causing it to become out of sync with the real total of queued withdrawals.
The _finalizeWithdrawals function in the WithdrawalPool contract incorrectly updates the totalQueuedShareWithdrawals variable when processing queued withdrawals during a deposit. The function decreases totalQueuedShareWithdrawals by the full amount of shares corresponding to the deposited tokens, even if not all of these shares are actually used to finalize withdrawals.
This can happen when the total amount of queued withdrawals is less than the amount of shares corresponding to the deposited tokens. In such cases, totalQueuedShareWithdrawals will be decreased by more than the actual amount of shares used, causing it to become out of sync with the real total of queued withdrawals.
In WithdrawalPool.sol: https://github.com/Cyfrin/2024-09-stakelink/blob/f5824f9ad67058b24a2c08494e51ddd7efdbb90b/contracts/core/priorityPool/WithdrawalPool.sol#L422-L426
A user queues a withdrawal of 100 shares by calling queueWithdrawal with an amount of LST tokens corresponding to 100 shares.
Another user makes a deposit of tokens corresponding to 500 shares by calling deposit.
The _finalizeWithdrawals function is called with sharesToWithdraw equal to 500. It immediately decreases totalQueuedShareWithdrawals by 500.
However, when processing the queued withdrawals, it only uses 100 of these shares to finalize the one queued withdrawal.
The remaining 400 shares are not used, but totalQueuedShareWithdrawals has already been decreased by the full 500.
As a result, totalQueuedShareWithdrawals is now 400 less than the real total of queued withdrawal shares.
The discrepancy between totalQueuedShareWithdrawals and the real queued amount may grow over time as more deposits and withdrawals happen, exacerbating the impact.
Manual Review
_finalizeWithdrawals() should track the actual number of shares used to finalize withdrawals and only decrease totalQueuedShareWithdrawals by that amount.
We introduces a sharesUsed variable to track the actual number of shares used to finalize withdrawals. It increments sharesUsed as it processes each withdrawal, and then decreases totalQueuedShareWithdrawals by sharesUsed at the end of the function.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.