# Bypass of recipient check allows pre-seeding the real pair and manipulating initial AMM price

Launchpad.pairFor() omits LP vault and distributor from CREATE2 salt, so the donation guard misses the real pair, letting attackers pre-seed reserves and set the initial AMM price.

- Payout: Contest reward
- Severity: medium
- Program: GTE
- Credited: 0xMilenov
- Disclosed: 2026-02-05
- Write-up quality: 7/10
- Original: https://code4rena.com/reports/2025-08-gte-perps-and-launchpad#m-21
- Library page: https://bugbountylibrary.com/r/c4%3A2025-08-gte-perps-and-launchpad%3AM-21
- Tags: domain:web3 impact:funds-loss kind:contest platform:code4rena sev:medium tech:evm tech:solidity technique:incomplete-fix technique:source-review vuln:business-logic vuln:oracle-manipulation

**Target:** Launchpad.sol bonding curve / GTELaunchpadV2PairFactory CREATE2 pair
**Root cause:** pairFor() computes the pair address with salt keccak256(token0,token1) while the custom factory salts with keccak256(token0,token1,launchpadLp,launchpadFeeDistributor), so the computed address never equals the real pair.
**Steps:**
1. Call buy() on Launchpad with recipient set to the real GTELaunchpadV2Pair address; _assertValidRecipient compares against the miscomputed pairFor address and does not revert.
2. Base tokens are transferred directly into the real AMM pair during bonding, pre-seeding reserves.
3. Add quote tokens and mint LP to fix the reserves ratio, setting the initial AMM price.
4. On graduation, Launchpad.addLiquidity() uses existing reserves via Uniswap _addLiquidity, preserving the attacker's price.
5. Sell launch tokens at the manipulated price to extract excess quote tokens.
**How found:** Code-reading: compared pairFor()'s CREATE2 salt (token0,token1) against the custom factory's salt (token0,token1,launchpadLp,launchpadFeeDistributor) and noticed the addresses diverge, invalidating the donation guard added as a prior fix.
**Exploitation:** Attacker buys base tokens with recipient=real pair during bonding (guard bypassed), then adds quote liquidity and mints LP to lock the manipulated reserve ratio before graduation; Launchpad's addLiquidity preserves the ratio, and attacker sells at favorable prices for profit.
**Escalation:** Same miscomputed address also misdirects endRewards() (silent DoS or wrong pair) and _createPairAndSwapRemaining()'s pair.skim(owner()).
**Insight:** When a factory customizes its CREATE2 salt, any off-chain/on-chain address derivation (pairFor-style) must mirror the exact salt; audit prior-fix guards by verifying the address they compare against actually equals the deployed contract.
