# Four.meme launchpad: PancakeSwap migration exploits (BSC, Feb & Mar 2025)

## 1. What happened

**Feb 11, 2025, BNB Chain.** Four.meme, a pump.fun-style memecoin launchpad, was drained at its
graduation/migration step. Loss estimates disagree: ~$183,000 per PeckShield [S10], Verichains [S2],
Cointelegraph/Crypto.news [S6][S7], smartcontractshacking [S19]; "more than $180,000 / almost $200K"
per Protos [S8]; "186k (287bnb)" per DeFiHackLabs [S3]; only ~$15,000 for the single demonstrated
`snowboard` token per the Zero Time analysis [S1]. Taken: the BNB migrated into the token's PancakeSwap
V3 pool (~23.5 BNB per graduation); the reproduction drains 23.4259 WBNB from one token [S3][S5]. LP
launches were suspended; internal funds claimed safe [S9][S8].

**Mar 18, 2025, BNB Chain.** Second migration attack. Loss ~$120,000 (ExVul; CertiK "at least 192 BNB",
about $120,000) [S14] versus ~$130,000 (CryptoSlate [S15]; CoinTab ~200 BNB, about $130,000 [S16]).
Decrypt reports ~$174k moved and laundered via PancakeSwap [S18]. Taken: fresh tokens' LP liquidity;
CertiK's example is `SBL`, attacker made 21.1 BNB sandwiching the launch `addLiquidity` [S14]. Launch
function halted, then resumed same day with compensation [S14][S17].

## 2. Root cause

Not a stolen key or tricked signer: both were on-chain logic flaws. At graduation (~24 BNB of curve
reserves) Four.meme calls an owner-only `addLiquidity(token, sqrtPriceX96)` meant to create the meme/WBNB
V3 pool, set its launch price, and mint full-range liquidity (~200,000,000 meme + ~23.5 BNB)
[S1][S4][S5]. It assumed it would own the pool's starting price. In February the PancakeSwap helper
`createAndInitializePoolIfNecessary` no-ops when the pool already exists at a non-zero price
(`initialize` is permissionless, callable once), so pre-initializing the deterministic `(meme, WBNB, 1%)`
pool at `sqrtPriceX96 = 1e40` (~3.68e14x the intended price) made the launch reuse that price; the mint
then deposited 1 wei of meme against the full 23.5 BNB [S4][S5][S2]. In March the attacker used the
platform's own pre-launch buy path (`0x7f79f6df`) to move un-launched, supposedly non-transferable tokens
to the pre-computable, not-yet-created pair address, bypassing `MODE_TRANSFER_RESTRICTED`, created the
pair, and fixed the price; the migration reused it [S12][S13][S11]. Both: the migration trusted
attacker-controllable external pool state. The launchpad was closed-source/unverified on BscScan [S3][S5].

## 3. Pattern

Class: **unvalidated external state - price/oracle manipulation of the launch pool (pool-init
front-run)**, plus **unchecked slippage** on the LP mint:

```
function addLiquidity(token, myPrice) onlyOwner {
  token.setMode(0);              // lifts pre-launch transfer restriction
  pool = createAndInitializePoolIfNecessary(token, WBNB, fee, myPrice);
  // FLAW: pool exists with price != 0 -> myPrice IGNORED (silent no-op)
  mint(token, WBNB, fee, -887200, 887200, 200_000_000e18, 23.5e18,
       amount0Min = 0, amount1Min = 0, // FLAW: no slippage guard
       recipient = this);
}
```

The launchpad never checked the pool's post-state: it treated "create-and-initialize-if-necessary" as a
guarantee its price applied, and minted with zero minimums, so a mismatched price put the full BNB
against ~0 meme without reverting. The transfer restriction also missed the future pair/LP address.

## 4. The check that would have caught it

1. **Post-migration price assertion (unit test).** After `createAndInitializePoolIfNecessary`, read
   `pool.slot0().sqrtPriceX96` and `require` it equals the intended launch price, else revert. Test:
   pre-initialize the `(token, WBNB, fee)` pool at a different price and assert the migration reverts.
   Verichains and Coinspect both call for this check [S2][S4].
2. **Invariant/fuzz test on the mint.** Invariant: every graduation's mint consumes the intended
   liquidity (meme ~200,000,000, WBNB ~23.52, post-migration price within a small band of the final
   bonding-curve price). In February the mint took 1 wei of meme, not 200M [S5], so it fails loudly.
3. **Real slippage guards.** Pass non-zero `amount0Min`/`amount1Min` (Coinspect flags the zero values as
   "the bug") so a price mismatch reverts instead of donating the BNB [S4].
4. **Transfer-restriction review rule.** A restricted-mode token must be untransferable to the future
   pair/LP address; test that a pre-launch transfer to it reverts [S12][S11].

## 5. Sources

- S1 https://www.chaincatcher.com/en/article/2167296
- S2 https://blog.verichains.io/p/fourmeme-hack-analysis
- S3 https://github.com/SunWeb3Sec/DeFiHackLabs/blob/main/src/test/2025-02/FourMeme_exp.sol
- S4 https://www.coinspect.com/learn-evm-attacks/cases/four-meme/
- S5 https://crypto.training/hacks/2025-02-FourMeme/
- S6 https://cointelegraph.com/news/bnb-chain-memecoin-fourmeme-hacked-183k
- S7 https://crypto.news/four-meme-hit-by-malicious-attack-leading-to-183k-loss/
- S8 https://protos.com/binances-memecoin-platform-loses-almost-200k-in-hack/
- S9 https://x.com/four_meme_/status/1889198796695044138
- S10 https://x.com/PeckShieldAlert/status/1889210001220423765
- S11 https://www.quillaudits.com/blog/hack-analysis/four-meme-attack-analysis
- S12 https://www.chaincatcher.com/en/article/2173046
- S13 https://x.com/SlowMist_Team/status/1901845958767657072
- S14 https://cointelegraph.com/news/four-meme-resumes-operation-sandwich-exploit
- S15 https://cryptoslate.com/four-meme-handles-second-exploit-in-months-reinstates-launch-service/
- S16 https://cointab.com/hackers-four-meme-token-steals-130k-in-bnb/
- S17 https://x.com/four_meme_/status/1901857145995587851
- S18 https://decrypt.co/310388/meme-coin-launchpad-four-meme-falls-victim-to-another-exploit
- S19 https://smartcontractshacking.com/hacks/four-meme-hack-2025

Note: rekt.news had no write-up (`/four-meme` returned HTTP 500, sitemap unavailable), and no official
Four.meme post-mortem was reachable; its statements are the X posts above.
