# First liquidity provider will suffer from revert or fund loss

First LP in Numoen must supply amount0/amount1/liquidity that satisfy the invariant exactly; mismatch causes revert or lets anyone swap out token0 for free.

- Payout: Contest reward
- Severity: medium
- Program: Numoen
- Credited: hansfriese
- Disclosed: 2023-03-03
- Write-up quality: 6/10
- Original: https://github.com/code-423n4/2023-01-numoen-findings/issues/254
- Library page: https://bugbountylibrary.com/r/c4%3A2023-01-numoen%3AM-02
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:source-review vuln:accounting-error vuln:business-logic

**Target:** LiquidityManager.addLiquidity / Pair invariant (Solidity AMM)
**Root cause:** When totalLiquidity==0, addLiquidity takes amount0/amount1 directly from caller-supplied amount0Min/amount1Min while liquidity is a separate input; the three values must satisfy the Pair invariant a+b>=c+d, but no on-chain derivation enforces it.
**Steps:**
1. Call `LiquidityManager.addLiquidity(AddLiquidityParams)` on an empty pool with `liquidity`, `amount0Min`, `amount1Min`.
2. Observe branch `totalLiquidity==0` sets `amount0=params.amount0Min`, `amount1=params.amount1Min` (L148-149).
3. Deposit mints position; `Pair.invariant(amount0,amount1,liquidity)` is checked.
4. If `a+b-c-d > 0` (scale0*1e18 + scale1*upperBound > scale1^2/4 + upperBound^2), anyone calls `swap()` to pull token0 for free.
5. If invariant fails, tx reverts; either way first LP loses or is blocked without off-chain formula L=(PCy+C^2x+sqrt(2PC^3xy+C^4x^2))/(2P^2).
**How found:** Read addLiquidity's empty-pool branch and noticed amount0/amount1 come from caller while liquidity is independent; traced into Pair.invariant and reasoned that strict inequality a+b>c+d lets swap() drain token0, so the three inputs must satisfy an exact relation the contract doesn't compute.
**Exploitation:** After a first LP deposits with amounts exceeding the invariant, an attacker calls swap() to extract the surplus token0 at no cost; otherwise the depositor's tx reverts.
**Insight:** In AMM-style first-deposit paths, check whether initial reserve amounts and share/liquidity units are independent caller inputs; if the pool invariant is an inequality, any surplus above equality is free value extractable via swap.
