The WithdrawalPool::updateWithdrawalBatchIdCutoff
function is designed to update the withdrawalBatchIdCutoff
, which helps efficiently return data in getBatchIds
by skipping old withdrawal batches. However, a malicious user can exploit this function by delaying their token withdrawal indefinitely, preventing the cutoff from advancing. This manipulation can lead to a DoS situation when the function tries to iterate over a large number of withdrawals, risking an out-of-gas error.
The updateWithdrawalBatchIdCutoff
function iterates over the queuedWithdrawals
array to find the first unprocessed or partially filled withdrawal and updates the withdrawalIdCutoff
accordingly. Since numWithdrawals
is an ever-growing array, the function stores newWithdrawalIdCutoff
to avoid recalculating from the beginning each time.
Here's the relevant code section:
A malicious user whose withdrawal request is at the withdrawalIdCutoff
can intentionally delay withdrawing their tokens. This causes the list of queued withdrawals to grow without updating the cutoff. Eventually, the loop will iterate over too many unprocessed withdrawals, risking an out-of-gas DoS. The attack is low-cost, as the attacker can simply withdraw their tokens whenever they choose.
Illustration explaining withdrawalIdCutoff
:
[0, 0, 0, 1, 0, 0, 0, 1, 1] : withdrawalIdCutoff
= 2
[0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 1] : withdrawalIdCutoff
= 6
[0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1] : withdrawalIdCutoff
= 9
If the user at the cutoff delays their withdrawal indefinitely, the difference between the current withdrawalIdCutoff
and the next valid cutoff grows, making future updates to the cutoff computationally expensive.
If getBatchIds
becomes unusable, users will struggle to retrieve accurate parameters for withdrawing their tokens. This makes the withdrawal process inefficient and can disrupt normal protocol operations, causing financial loss and frustration for users.
Manual
Implement a timeout or penalty system for users who do not withdraw their tokens within a reasonable timeframe. Alternatively, limit the number of iterations per transaction to prevent an out-of-gas DoS when the queue grows too large.
Let me know if you'd like any further changes!
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.