# Multi-token stableswap pools allow 0 liquidity for tokens, creating bricked pools

Multi-token stableswap pool creation skips zero-liquidity check, letting a creator omit a token and permanently brick the pool via division-by-zero on later deposits.

- Payout: Audit contest
- Severity: high
- Program: MANTRA
- Found by: carrotsmuggler
- Disclosed: 2025-03-31
- Write-up quality: 7/10
- Original: https://code4rena.com/reports/2024-11-mantra-dex#h-03
- Library page: https://bugbountylibrary.com/r/c4%3A2024-11-mantra-dex%3AH-03
- Tags: area:web3 domain:web3 impact:dos kind:contest platform:code4rena sev:high tech:rust technique:source-review vuln:business-logic vuln:dos

**Target:** CosmWasm pool-manager stableswap provide_liquidity
**Root cause:** Initial provide_liquidity only verifies deposited assets are pool constituents, not that every pool token is funded; a zero balance for one token makes amount_times_coins zero and d_prod division reverts on subsequent deposits.
**Steps:**
1. Create a StableSwap pool with 3 tokens (e.g. uwhale, uluna, uusd).
2. Call provide_liquidity with only 2 of the 3 tokens, e.g. `[coin(1_000_000,"uwhale"), coin(1_000_000,"uluna")]` — succeeds.
3. Call provide_liquidity again on the same pool — reverts with `DivideByZeroError` at helpers.rs d_prod calculation.
4. Pool is permanently bricked; no further liquidity can be added.
**How found:** Code review comparing ConstantProduct vs StableSwap initial liquidity paths: noticed ConstantProduct uses deposits[0]*deposits[1] forcing nonzero, while StableSwap only checks asset membership, then traced amount_times_coins into the d_prod loop to confirm division by zero.
**Exploitation:** Anyone can create a multi-token stableswap pool and seed it while omitting one constituent token; the pool is stored with zero liquidity for that token, and all future provide_liquidity calls revert on division by zero, permanently disabling the pool.
**Insight:** When a protocol supports N-token pools, compare the invariant math against the 2-token path — any term multiplied by a per-token amount becomes zero if that token is unfunded, so check for missing nonzero-deposit validation on every constituent at initialization.

