# Selling partial base tokens are more profitable then selling in one go

WooFi SPMM pricing makes splitting a base-token sell into many small swaps yield more quote tokens than one swap, bypassing maxGamma/maxNotionalSwap limits.

- Payout: Contest reward
- Severity: medium
- Program: Woofi Swap
- Credited: Bandit
- Disclosed: 2024-03-06
- Write-up quality: 7/10
- Original: https://github.com/sherlock-audit/2024-03-woofi-swap-judging/issues/20
- Library page: https://bugbountylibrary.com/r/sherlock%3A2024-03-woofi-swap%3AM-2
- Tags: domain:web3 impact:funds-loss kind:contest platform:sherlock sev:medium tech:evm tech:solidity technique:chained technique:source-review vuln:business-logic vuln:fee-bypass

**Target:** WooPPV2 AMM swap pricing (sellBase/sellQuote)
**Root cause:** The SPMM price-impact formula applies gamma and spread such that marginal output per unit decreases non-linearly, so multiple sequential partial swaps in one tx each start from a less-degraded price, netting more quote tokens than a single large swap.
**Steps:**
1. Model sellBase: `g = deltaBase*p*c`, `deltaQuote = deltaBase*p*(1-(g+s))`, `np = p*(1-g)`
2. Single sell 20 base (p=1,c=0.01,s=0.1): g=0.2, deltaQuote=14
3. Two sells of 10: first g=0.1, deltaQuote=8, np=0.9; second g=0.09, deltaQuote=7.29; total 15.29
4. Loop `router.swap(WETH,USDC,sellWethAmount/N,...)` N times in one tx to accumulate extra USDC
5. Observe 500-500 split yields +3395.8 USDC and 1000x1 split yields +6776.5 USDC vs single 1000 WETH sell
**How found:** Reading the sellBase/sellQuote math in WooPPV2.sol, graphing the formulas on Desmos, and noticing output decreases after a mid-point for price>1, prompting a textual and Foundry comparison of single vs split swaps.
**Exploitation:** A swapper splits a large sell into N partial swaps within a single transaction, each priced off the slightly-degraded pool price, capturing more quote tokens than a single swap and bypassing maxNotionalSwap/maxGamma caps; no external capital or flash loan needed.
**Escalation:** Splitting also circumvents maxNotionalSwap and maxGamma limits, allowing arbitrarily large effective swap sizes that the protocol intended to block.
**Insight:** When an AMM's price-impact formula is not path-independent (unlike Uniswap/Curve where N small swaps in one tx equal one big swap), test splitting a swap into N sequential calls in a single transaction and compare cumulative output; also check whether per-swap caps like maxNotionalSwap can be evaded by chunking.
