# Overflow in the mint function of ConcentratedLiquidityPool causes LPs' funds to be stolen

Unchecked uint128 addition in ConcentratedLiquidityPool.mint lets an attacker overflow the balance check and mint huge liquidity for almost no tokens, then burn to steal LPs' funds.

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

**Target:** ConcentratedLiquidityPool.mint balance check (Solidity)
**Root cause:** The balance check adds amount1Actual (uint128) to reserve1 (uint128) inside an unchecked block, so the sum wraps to a small value and the require passes even though the pool is underpaid.
**Steps:**
1. Set current price at tick 500000; call `mint` with `lower=100000`, `upper=500000`, `amount1Desired=(1<<128)-47541305835`, `amount0Desired=0`.
2. Contract computes `_liquidity = amount1Desired*(1<<96)//(priceUpper-priceLower)`.
3. `amount1Actual = uint128(getDy(...)) = (1<<128)-47541305834`.
4. If `reserve1 > 47541305834`, `amount1Actual + reserve1` overflows to a small number, passing the balance check.
5. Attacker receives large liquidity for ~0 tokens; burn liquidity to drain other LPs' funds.
**How found:** Noticed the balance check performed uint128 addition inside an unchecked block, mirroring a prior IndexPool overflow finding, and constructed boundary values near 2^128 to force the wrap.
**Exploitation:** Attacker mints near-maximal liquidity with a crafted amount1Desired so the uint128 addition of amount1Actual and reserve1 wraps, paying almost nothing, then burns the position to withdraw a disproportionate share of pool reserves, stealing other LPs' funds.
**Insight:** When a pool's balance check adds a computed amount to a stored reserve in a narrow type (uint128) under unchecked, pick inputs so the sum crosses 2^128 and wraps; the require then passes while actual payment is tiny.

