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

Unchecked uint120 addition in IndexPool.mint lets attacker overflow the balance check with huge amountIn, minting massive LP tokens and draining other LPs' funds.

- Payout: Audit contest
- Severity: high
- Program: Sushi
- Found by: broccoli
- Disclosed: 2021-11-22
- Write-up quality: 7/10
- Original: https://github.com/code-423n4/2021-09-sushitrident-findings/issues/163
- Library page: https://bugbountylibrary.com/r/c4%3A2021-09-sushitrident%3AH-13
- 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:** IndexPool.sol mint function (Solidity smart contract)
**Root cause:** amountIn is a uint120 and the balance check `_balance(tokenIn) >= amountIn + reserve` is performed in an unchecked block, so a large amountIn overflows the addition and passes the check without real liquidity.
**Steps:**
1. Call `mint(tokenIn, amountIn)` on IndexPool with amountIn near uint120 max so `amountIn + reserve` overflows uint120
2. Overflowed sum wraps small, satisfying `_balance(tokenIn) >= amountIn + reserve`
3. Contract mints LP tokens proportional to the huge amountIn despite no real deposit
4. Attacker holds dominant LP share and burns to withdraw proportional pool funds, stealing other LPs' assets
**How found:** Code review of the mint function's unchecked balance check; noticed amountIn is uint120 and the addition could overflow, then built a PoC (mint_overflow.js).
**Exploitation:** Attacker calls mint with a huge uint120 amountIn; the unchecked addition overflows, the balance check passes, and the attacker receives LP tokens far exceeding their actual deposit. Burning those LP tokens redeems a proportional share of the pool, extracting other LPs' funds.
**Insight:** In Solidity, unchecked arithmetic is only safe if operands are widened to uint256 first; when a narrower type like uint120 is added in an unchecked block, overflow is still reachable — check the declared width of user-supplied amounts, not just the presence of `unchecked`.

