# isGenesis flag is ineffective to control add liquidity flow in RouterV2.addLiquidity()

RouterV2.addLiquidity's isGenesis guard only blocks when totalSupply==0, and Pair.mint() lacks any genesis check, letting anyone seed liquidity into unlaunched Genesis pools.

- Payout: Contest reward
- Severity: medium
- Program: Blackhole
- Credited: maxzuvex
- Disclosed: 2025-07-03
- Write-up quality: 6/10
- Original: https://code4rena.com/reports/2025-05-blackhole#m-07
- Library page: https://bugbountylibrary.com/r/c4%3A2025-05-blackhole%3AM-07
- Tags: domain:web3 impact:integrity kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:source-review vuln:access-control vuln:business-logic

**Target:** RouterV2.addLiquidity and Pair.mint in Blackhole AMM contracts
**Root cause:** The genesis guard is conditioned on totalSupply()==0, so it stops applying once any LP tokens exist; Pair.mint() has no isGenesis check at all, so a dust mint flips totalSupply and unlocks the router path.
**Steps:**
1. Identify a pair where IBaseV1Factory.isGenesis(pair)==true and totalSupply()==0.
2. Transfer minimal token0 and token1 amounts directly to the pair contract.
3. Call Pair.mint(attacker) directly — no isGenesis check exists, so LP tokens are minted and totalSupply>0.
4. Now call RouterV2.addLiquidity() for the pair: require(!(isGenesis && totalSupply==0)) evaluates to require(true) and passes.
5. Add arbitrary liquidity to the unlaunched Genesis pool.
**How found:** Code reading of the router guard: noticed the require only fails when isGenesis AND totalSupply==0, then checked Pair.mint() and found no genesis restriction, giving a trivial way to make totalSupply nonzero.
**Exploitation:** Attacker sends dust of both tokens to the genesis pair, calls mint() to create LP supply, then uses RouterV2.addLiquidity to inject liquidity before official launch, disrupting the controlled launch and enabling price manipulation.
**Insight:** When a launch gate is expressed as a compound condition on mutable state (totalSupply), look for any other entrypoint that mutates that state without the gate — here the pair's own mint() — since it silently disables the guard.
