# PositionManager.moveLiquidity could revert due to underflow

PositionManager.moveLiquidity underflows when accrued interest makes lpbAmountFrom exceed tracked fromPosition.lps, reverting the liquidity move.

- Payout: Contest reward
- Severity: medium
- Program: Ajna Protocol
- Credited: 0xnev
- Disclosed: 2023-06-29
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2023-05-ajna-findings/issues/99
- Library page: https://bugbountylibrary.com/r/c4%3A2023-05-ajna%3AM-14
- Tags: domain:web3 impact:dos kind:contest platform:code4rena sev:medium tech:solidity technique:source-review vuln:accounting-error

**Target:** PositionManager.moveLiquidity in ajna-core
**Root cause:** fromPosition.lps is decremented by vars.lpbAmountFrom returned from pool.moveQuoteToken, but interest accrued since deposit can make the moved LP amount exceed the stored position LP, causing underflow.
**Steps:**
1. Deposit liquidity into a bucket via PositionManager, recording fromPosition.lps and depositTime.
2. Let interest accrue so bucket LP-to-quote rate increases.
3. Call `moveLiquidity(params_)` moving liquidity from that bucket to another index.
4. pool.moveQuoteToken returns lpbAmountFrom > fromPosition.lps, so `fromPosition.lps -= vars.lpbAmountFrom` underflows and reverts.
**How found:** Code reading of moveLiquidity: noticed fromPosition.lps is reduced by the pool-returned lpbAmountFrom rather than deleted, and reasoned accrued interest could push the returned amount above the tracked LP.
**Insight:** When a contract decrements a stored share balance by an amount recomputed from a live pool exchange rate, check whether interest accrual between deposit and withdrawal can make the recomputed amount exceed the stored value; deleting the position (as redeemPositions does) avoids the mismatch.
