# DoS: Blacklisted user may prevent withdrawExcessRewards()

A blacklisted or paused-token user cannot withdraw, leaving totalDepositsWei nonzero and permanently blocking the owner's withdrawExcessRewards() call.

- Payout: Contest reward
- Severity: high
- Program: FactoryDAO
- Credited: AuditsAreUS
- Disclosed: 2022-08-02
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2022-05-factorydao-findings/issues/57
- Library page: https://bugbountylibrary.com/r/c4%3A2022-05-factorydao%3AH-02
- Tags: domain:web3 impact:dos impact:funds-loss kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:business-logic vuln:dos

**Target:** PermissionlessBasicPoolFactory withdraw/withdrawExcessRewards
**Root cause:** withdraw() requires all ERC20 transfers to succeed via `require(success)`, so a reverting/blacklisted transfer reverts the whole withdrawal; withdrawExcessRewards() requires totalDepositsWei==0, which never becomes true.
**Steps:**
1. Deploy pool with a reward/deposit token that can blacklist (e.g. USDC).
2. Attacker deposits negligible amount and gets blacklisted (or token paused).
3. Attacker calls `withdraw()`; `IERC20(token).transfer(receipt.owner, amount)` fails, `success=false`, `require(success,'Token transfer failed')` reverts.
4. totalDepositsWei stays >0; owner's `withdrawExcessRewards()` reverts on `require(pool.totalDepositsWei == 0)`.
**How found:** Code reading of withdraw()'s transfer loop and the totalDepositsWei==0 guard in withdrawExcessRewards(); noted ERC20 transfers can fail (blacklist, pause) and that a single stuck user blocks the owner path.
**Exploitation:** Attacker deliberately gets blacklisted with a tiny deposit, cheaply locking all users' rewards/deposits and the owner's excess rewards in the contract indefinitely.
**Insight:** When a privileged sweep/withdraw is gated on an aggregate counter reaching zero, check whether any single user action (or token-level failure like blacklist/pause) can keep that counter nonzero forever; per-user try/catch or time-based fallback avoids the lock.
