# Second per liquidity inside could overflow uint256 causing the LP position to be locked in UniswapV3Staker

UniswapV3Staker's secondsPerLiquidityInside subtraction underflows uint256 in Solidity 0.8 when a tick was initialized below current tick, reverting unstakeToken and locking LP positions.

- Payout: Contest reward
- Severity: high
- Program: Maia DAO Ecosystem
- Credited: minhquanym
- Disclosed: 2023-09-18
- Write-up quality: 8/10
- Original: https://github.com/code-423n4/2023-05-maia-findings/issues/505
- Library page: https://bugbountylibrary.com/r/c4%3A2023-05-maia%3AH-17
- Tags: domain:web3 impact:dos kind:contest platform:code4rena sev:high tech:evm tech:solidity technique:regression technique:source-review vuln:accounting-error vuln:dos

**Target:** UniswapV3Staker / RewardMath.computeBoostedSecondsInsideX128
**Root cause:** secondsPerLiquidityInsideX128 is computed as cumulative minus tickLower/tickUpper outside values; when a tick is initialized while below current tick, its outside value is set to the cumulative, so the inside value can be a huge uint256 (negative) that later exceeds the staked snapshot, underflowing the subtraction under Solidity 0.8.
**Steps:**
1. Create 1:1 pool, init ticks -180/180 and -60/60, warp.
2. Swap to push currentTick into (60,180) range, then swap back into (-60,60) range, warping between.
3. Create gauge and incentive; warp to startTime+1.
4. Mint position with range [-120,60]; snapshotCumulativesInside returns huge uint256 secondsPerLiquidityInsideX128.
5. safeTransferFrom position to UniswapV3Staker to stake it.
6. Warp 5 weeks so secondsPerLiquidityInside grows past the staked snapshot; call `unstakeToken(tokenId)` — reverts on underflow.
**How found:** Compared Maia's RewardMath to Uniswap's reference implementation and noticed Uniswap used Solidity 0.7 (wrapping) while Maia uses 0.8 (reverting); traced tick initialization in Tick.sol to see secondsPerLiquidityOutsideX128 is set to the cumulative when a tick is initialized below current tick, making the inside value negative.
**Exploitation:** Attacker (or any LP) stakes a position whose tick range includes a tick initialized below current tick; the stored secondsPerLiquidityInsideInitialX128 is a wrapped negative value, so later `secondsPerLiquidityInsideX128 - initial` underflows and reverts, permanently locking the NFT in the staker.
**Insight:** When porting Uniswap v3 math from 0.7 to 0.8, audit every subtraction that relied on wrapping; tick initialization below current tick sets outside values to the cumulative, so 'inside' values can legitimately be negative and must be handled in unchecked blocks.
