# A malicious strategy can permanently DoS all currently pending withdrawals that contain it

A reverting or malicious strategy in a multi-strategy queued withdrawal blocks completeQueuedWithdrawal for all strategies, forcing users to re-queue and wait again.

- Payout: Contest reward
- Severity: medium
- Program: EigenLayer
- Credited: ABA
- Disclosed: 2023-07-06
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2023-04-eigenlayer-findings/issues/132
- Library page: https://bugbountylibrary.com/r/c4%3A2023-04-eigenlayer%3AM-02
- Tags: domain:web3 impact:dos kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:source-review vuln:business-logic vuln:dos

**Target:** StrategyManager.completeQueuedWithdrawal / IStrategy.withdraw
**Root cause:** completeQueuedWithdrawal loops over all strategies and calls strategy.withdraw() when receiveAsTokens is true; a single reverting strategy reverts the whole loop. The receiveAsTokens=false path re-adds shares but still requires a fresh queueWithdrawal and new wait period.
**Steps:**
1. User calls `queueWithdrawal` with strategies array including a malicious/reverting strategy; withdrawalRoot marked pending, shares removed.
2. User waits the withdrawal delay and calls `completeQueuedWithdrawal(withdrawal, tokens, receiveAsTokens=true)`.
3. Loop reaches malicious strategy and calls `strategy.withdraw(msg.sender, tokens[i], shares[i])` which reverts, reverting entire completion.
4. Alternative `receiveAsTokens=false` re-adds shares via `_addShares`/`increaseDelegatedShares`, but user must `queueWithdrawal` again excluding the strategy and wait another delay.
**How found:** Code reading of completeQueuedWithdrawal's loop calling strategy.withdraw() with no skip mechanism, contrasted with slashQueuedWithdrawal which already has an indicesToSkip parameter for exactly this malicious-strategy scenario.
**Exploitation:** Attacker deploys a strategy whose withdraw() always reverts, gets victims to include it in multi-strategy withdrawals (or a legit strategy is paused/broken), denying completion of the whole withdrawal until users re-queue without it and wait out the delay again.
**Insight:** When a batch loop calls into per-item external contracts, compare it against sibling functions that already implement skip/partial-failure handling (here slashQueuedWithdrawal's indicesToSkip) — the asymmetry reveals the missing DoS protection.
