# Unrestricted claiming of fees due to missing balance updates in FeeSplitter

FeeSplitter never updates userFeeOffset on token transfers, so an attacker can cycle tokens through fresh accounts and repeatedly claim accumulated fees.

- Payout: Contest reward
- Severity: high
- Program: Curves Protocol
- Credited: EV\_om
- Disclosed: 2024-07-19
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2024-01-curves-findings/issues/247
- Library page: https://bugbountylibrary.com/r/c4%3A2024-01-curves%3AH-02
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:business-logic vuln:reward-distribution

**Target:** FeeSplitter / Curves ERC20 fee distribution contract
**Root cause:** onBalanceChange()/updateFeeCredit() is only invoked from Curves._transferFees() during buy/sell, not on transferCurvesToken, deposits or withdrawals, so userFeeOffset stays zero for new holders.
**Steps:**
1. Alice buys curve tokens.
2. Alice calls `transferCurvesToken()` to move tokens to fresh Account1; onBalanceChange not triggered, userFeeOffset[Account1]=0.
3. Account1 calls `FeeSplitter.claimFees(token)`; owed = (cumulativeFeePerToken - 0) * balance, paying fees as if held since inception.
4. Transfer tokens from Account1 to new Account2, repeat claim.
5. Loop across new accounts to drain FeeSplitter balance.
**How found:** Code reading of the accumulator pattern: noticed onBalanceChange() is only called from _transferFees() (buy/sell) and not from transferCurvesToken, so userFeeOffset is never synced on transfers.
**Exploitation:** Attacker holds tokens, transfers them to a sequence of fresh addresses (each with userFeeOffset=0), and each address calls claimFees() to collect the full cumulative fee share again, draining the contract's matured yield.
**Insight:** In accumulator/reward-per-token designs, audit every path that changes balance (transfer, deposit, withdraw, mint, burn) and confirm the fee-offset sync hook fires on each; a single un-hooked transfer path lets a zero-offset fresh account re-claim the full cumulative reward.
