# Removing more gauge weight than it should be while transferring ERC20Gauges token

ERC20Gauges._decrementWeightUntilFree used totalFreed instead of userFreed in loop condition, so transferring tokens removed weight from deprecated gauges and over-freed live gauge weight.

- Payout: Contest reward
- Severity: medium
- Program: Maia DAO Ecosystem
- Credited: KingNFT
- Disclosed: 2023-09-18
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2023-05-maia-findings/issues/477
- Library page: https://bugbountylibrary.com/r/c4%3A2023-05-maia%3AM-21
- Tags: domain:web3 impact:integrity kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:source-review vuln:accounting-error

**Target:** ERC20Gauges.sol _decrementWeightUntilFree
**Root cause:** Loop condition checks (userFreeWeight + totalFreed) < weight, but totalFreed excludes deprecated gauges while userFreed includes them, so the loop keeps iterating and decrements more user gauge weight than needed.
**Steps:**
1. Deploy MockERC20Gauges with 1h cycles, setMaxGauges(2), add gauge1 and gauge2.
2. Mint 200 to alice, alice delegates to self, increments gauge1 and gauge2 with 100 each.
3. Alice calls removeGauge(gauge1) making it deprecated.
4. Alice transfers 100 tokens to bob.
5. Observe getUserGaugeWeight(alice, gauge2) becomes 0 and getUserWeight(alice) becomes 0, though only 100 weight should have been freed.
**How found:** Code review of _decrementWeightUntilFree loop condition, noticing totalFreed excludes deprecated gauges while userFreed includes them, causing the loop to over-iterate.
**Insight:** When a loop tracks two counters (one filtered, one unfiltered), verify the loop bound uses the counter matching the actual freed amount; deprecated/excluded items silently break the termination condition.
