# Selling will be bricked if all other tokens are withdrawn to ERC20 token

FeeSplitter.addFees reverts with NoTokenHolders when all curve tokens are withdrawn to ERC20, bricking sells for remaining holders.

- Payout: Contest reward
- Severity: medium
- Program: Curves Protocol
- Credited: BowTiedOriole
- Disclosed: 2024-07-19
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2024-01-curves-findings/issues/378
- Library page: https://bugbountylibrary.com/r/c4%3A2024-01-curves%3AM-07
- Tags: domain:web3 impact:dos kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:source-review vuln:business-logic vuln:dos

**Target:** FeeSplitter / Curves ERC20 withdrawal and sell flow
**Root cause:** FeeSplitter.totalSupply() computes (curvesTokenSupply - curvesTokenBalance held by Curves contract) * PRECISION; when every token is withdrawn to ERC20 the difference is zero, so addFees reverts with NoTokenHolders(), blocking sellCurvesToken.
**Steps:**
1. Alice buys 1 curve token and withdraws it to ERC20.
2. Bob buys 1 curve token.
3. Charlie buys 10 curve tokens and withdraws all to ERC20.
4. Bob calls `sellCurvesToken(subject, 1)`; fee distribution calls `FeeSplitter.addFees` which reverts `NoTokenHolders()` because totalSupply()==0.
**How found:** Code reading of FeeSplitter.totalSupply() formula and noticing the subtraction of the Curves contract's own balance can reach zero, then testing the withdraw-all scenario.
**Exploitation:** Any holder can withdraw all their tokens to ERC20; once no tokens remain held by the Curves contract, totalSupply() returns 0 and every subsequent sell reverts, locking remaining holders' funds until someone buys again.
**Insight:** When a supply metric subtracts a contract-held balance, check the boundary where that balance equals total supply; ERC20 withdrawal paths can drive derived supply to zero and revert dependent fee logic.
