# DOS of completeQueuedWithdrawal when ERC20 buffer is filled

OperatorDelegator.completeQueuedWithdrawal calls DepositQueue.fillERC20withdrawBuffer, which is gated by onlyRestakeManager, so the call always reverts and blocks EigenLayer withdrawals.

- Payout: Contest reward
- Severity: high
- Program: Renzo
- Credited: Aymen0909
- Disclosed: 2024-06-07
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2024-04-renzo-findings/issues/87
- Library page: https://bugbountylibrary.com/r/c4%3A2024-04-renzo%3AH-07
- Tags: domain:web3 impact:dos impact:funds-loss kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:access-control vuln:dos

**Target:** OperatorDelegator / DepositQueue Solidity contracts
**Root cause:** OperatorDelegator calls DepositQueue.fillERC20withdrawBuffer directly, but that function enforces onlyRestakeManager, so msg.sender (OperatorDelegator) is rejected and the whole withdrawal completion reverts.
**Steps:**
1. Admin calls `OperatorDelegator.completeQueuedWithdrawal(withdrawal, tokens, middlewareTimesIndex)` for an ERC20 token.
2. Function completes EL withdrawal, then computes `bufferToFill = withdrawQueue.getBufferDeficit(token)`.
3. If `bufferToFill > 0`, it calls `restakeManager.depositQueue().fillERC20withdrawBuffer(token, bufferToFill)`.
4. fillERC20withdrawBuffer's `onlyRestakeManager` modifier checks `msg.sender == restakeManager`; sender is OperatorDelegator, so it reverts `NotRestakeManager`.
5. Entire completeQueuedWithdrawal reverts; funds stay stuck in EigenLayer.
**How found:** Code reading of completeQueuedWithdrawal's buffer-fill path and cross-checking the access modifier on the DepositQueue function it calls.
**Exploitation:** Not attacker-driven; the flaw triggers whenever the ERC20 withdrawal buffer is below target, causing the admin's withdrawal completion to revert and locking protocol/user funds in EigenLayer.
**Insight:** When a contract calls another protocol contract to move funds, verify the callee's access modifiers against the actual msg.sender (the intermediate contract), not the intended admin; a mismatched onlyX guard turns a routine path into a permanent revert.
