# ConcentratedLiquidityPool: secondsPerLiquidity should be modified whenever pool liquidity changes

Sushi ConcentratedLiquidityPool fails to update secondsPerLiquidity before mint/burn liquidity changes, corrupting tick accounting and fee/position math.

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

**Target:** ConcentratedLiquidityPool mint()/burn() and Ticks.insert()
**Root cause:** secondsPerLiquidity is only incremented from lastObservation diff, but mint()/burn() change liquidity without first accruing secondsPerLiquidity, so the value used in Ticks.insert() is stale relative to the liquidity change.
**Steps:**
1. Observe secondsPerLiquidity += uint160((diff << 128) / liquidity) with diff = timestamp - lastObservation.
2. Call mint() or burn() while lowerTick <= currentTick < upperTick so pool liquidity changes.
3. Note liquidity is added/removed before Ticks.insert() without recomputing secondsPerLiquidity.
4. Compare to UniswapV3 _updatePosition() which calls observations.observeSingle() to fetch latest value before updating.
**How found:** Code-reading of the secondsPerLiquidity accrual formula and comparison against UniswapV3's _updatePosition() which fetches the latest observation before modifying liquidity.
**Insight:** When porting UniswapV3-style concentrated liquidity, check that every liquidity mutation first accrues time-weighted accumulators (secondsPerLiquidity, feeGrowth) using the latest observation; ordering bugs here silently corrupt tick accounting.

