# range fee growth underflow

RangeFeeGrowth underflows when feeGrowthBelow+feeGrowthAbove exceeds feeGrowthGlobal after tick crossings, reverting mints/burns and locking funds in the pool.

- Payout: Audit contest
- Severity: high
- Program: Sushi
- Found by: broccoli
- Disclosed: 2021-11-30
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2021-09-sushitrident-2-findings/issues/25
- Library page: https://bugbountylibrary.com/r/c4%3A2021-09-sushitrident-2%3AH-09
- Tags: area:web3 domain:web3 impact:dos impact:funds-loss kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:source-review vuln:accounting-error vuln:dos

**Target:** ConcentratedLiquidityPool.sol RangeFeeGrowth / Ticks.sol tick crossing
**Root cause:** On a tick cross only one of feeGrowthOutside0/1 is updated, so feeGrowthBelow+feeGrowthAbove can exceed _feeGrowthGlobal, making the subtraction in RangeFeeGrowth underflow and revert.
**Steps:**
1. `add_liquidity(pool, deposit_amount, -800, 500)`
2. `add_liquidity(pool, deposit_amount, 400, 700)`
3. `swap(pool, False, deposit_amount)` crosses tick 700, updating only feeGrowthOutside1
4. `swap(pool, True, deposit_amount)` crosses tick 500, updating only feeGrowthOutside0; current tick at -800
5. `add_liquidity(pool, deposit_amount, 400, 700)` reverts because feeGrowthBelow1 == feeGrowthGlobal1 and the subtraction underflows
**How found:** Code reading of RangeFeeGrowth's subtraction combined with Ticks.sol updating only one feeGrowthOutside per cross; hypothesized feeGrowthBelow+Above could exceed global and built a Hardhat PoC with two positions and two swaps.
**Exploitation:** No direct theft; the pool's mint/burn/cross-tick paths revert, so liquidity cannot be provided or withdrawn and funds are stuck in the contract.
**Insight:** In Uniswap-V3-style concentrated liquidity, verify that feeGrowthOutside updates on both tokens at every tick cross; asymmetric updates let the inside-fee subtraction underflow and brick tick crossing.

