# LPs can split their liquidity withdrawal to get more tokens

TermMax LP reward formula depends on live lpSupply, so splitting one withdrawal into 10 sequential withdrawLiquidity calls yields ~2.5% extra ft/xt tokens.

- Payout: Contest reward
- Severity: high
- Program: TermMax
- Credited: 0x37
- Disclosed: 2025-03-25
- Write-up quality: 6/10
- Original: https://cdn.cantina.xyz/reports/cantina_competition_term_max_december2024.pdf#3.1.4
- Library page: https://bugbountylibrary.com/r/cantina%3Aterm_max_december2024%3A3.1.4
- Tags: domain:web3 impact:funds-loss kind:contest platform:cantina sev:high tech:evm tech:solidity technique:source-review vuln:business-logic vuln:reward-distribution

**Target:** LP liquidity withdrawal / reward accounting in TermMax market router
**Root cause:** LP reward per withdrawal is computed against the current (decreasing) lpSupply within the same block, so each successive withdrawal in a block is priced at a smaller supply and pays out more per LP token.
**Steps:**
1. Provide liquidity as Alice (10000e8) to get lpFt/lpXt.
2. Generate swap fees via 1200 buyFt/buyXt/sellFt/sellXt rounds from deployer.
3. Single withdrawal: withdrawLiquidityToFtXt with full lpFt/lpXt -> ft 2097620090729, xt 2381501084289.
4. Split withdrawal: loop 10x `router.withdrawLiquidityToFtXt(alice, market, lpFtAmt/10, lpXtAmt/10, 0, 0)`.
5. Observe ft 2149293035341, xt 2440368687106 (~2.5% extra).
**How found:** Reading the Eq.F-3 reward formula, noticed reward depends on lpSupply; hypothesized that within a single block (constant timestamp/rewards) a reduced lpSupply after a partial withdrawal raises per-LP payout, then tested split=1 vs split=10 in a Foundry PoC.
**Exploitation:** Any LP calls withdrawLiquidityToFtXt repeatedly in the same block with fractional LP amounts instead of once, capturing the reward delta caused by shrinking lpSupply; profit scales with accumulated swap fees in an active market.
**Insight:** When a payout formula divides by a live pool/supply variable, check whether multiple calls within one block (or one tx) let the denominator shrink between payouts; compare single-call vs split-call outputs in a PoC with fees accrued.
