Pancake V3 Launch Drain
Exploit Transactions
0xdb5d43317ab8e5d67cdd5006b30a6f2ced513237ac189eb1e57f0f06f630d5820x4235b006b94a79219181623a173a8a6aadacabd01d6619146ffd6fbcbb206dff0xe0daa3bf68c1a714f255294bd829ae800a381624417ed4b474b415b9d2efeeb50x2902f93a0e0e32893b6d5c907ee7bb5dabc459093efa6dbc6e6ba49f85c27f61Victim Addresses
0x5c952063c7fc8610ffdb798152d69f0b9550762bBSC0x4abfd9a204344bd81a276c075ef89412c9fd2f64BSCLoss Breakdown
Similar Incidents
Unauthenticated Pancake Callback Drain
40%PHIL Public Mint Drain
34%Annex Liquidator WBNB Drain
34%ZS Pair Burn Drain
33%FiberRouter Allowance Reuse Drain
33%TipTag Pump Pair Pre-Seeding
33%Root Cause Analysis
Pancake V3 Launch Drain
1. Incident Overview TL;DR
On BSC, an attacker exploited the launch flow behind proxy 0x5c952063c7fc8610ffdb798152d69f0b9550762b by buying launch tokens early, permissionlessly creating the token/WBNB Pancake V3 pool, and initializing that pool at an extreme attacker-chosen price before the victim seeded liquidity. When transaction 0xe0daa3bf68c1a714f255294bd829ae800a381624417ed4b474b415b9d2efeeb5 later triggered the launch contract’s liquidity-add path, the victim delegated into helper logic that accepted the pre-existing pool state, minted with zero slippage bounds, and never validated the returned amount0/amount1. As a result, the Pancake V3 mint consumed only 1 launch-token unit but spent 23519999970521880780 wei of WBNB-equivalent value.
The root cause is a concrete victim-side logic flaw, not merely bad market conditions. The launch proxy delegated selector 0x55110640 into helper 0xbd17a5d1f802edf1bfc80d84ad66d3039b28ce75, where createAndInitializePoolIfNecessary was followed by mint with amount0Min = 0 and amount1Min = 0, and no post-mint validation of consumed amounts. That let an unprivileged adversary pre-prime pool price state and convert protocol-owned WBNB seed liquidity into an attacker-extractable position. The final dump transaction 0x2902f93a0e0e32893b6d5c907ee7bb5dabc459093efa6dbc6e6ba49f85c27f61 paid 21083328036280789564 wei to the main profit recipient.
2. Key Background
The victim contract at 0x5c952063c7fc8610ffdb798152d69f0b9550762b is not standalone application logic. The reconstructed runtime is a minimal EIP-1967 proxy that loads implementation slot 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc and forwards calldata with DELEGATECALL. In the exploit traces, the proxy routes into module 0xb28723a16d3347cdc0ce035eb1c1eb0b7406682f, which in turn delegates the core liquidity-add operation to helper 0xbd17a5d1f802edf1bfc80d84ad66d3039b28ce75.
Pancake V3 pool creation and initialization are permissionless. The collected NonfungiblePositionManager source shows that createAndInitializePoolIfNecessary creates a pool only if none exists; otherwise it returns the existing pool and only initializes it if slot0().sqrtPriceX96 == 0. That behavior matters here because the attacker’s tx 0x4235b006b94a79219181623a173a8a6aadacabd01d6619146ffd6fbcbb206dff created the token/WBNB pool first and fixed its price at sqrtPriceX96 = 10000000000000000000000000000000000000000.
The launch token 0x4abfd9a204344bd81a276c075ef89412c9fd2f64 is a verified ownable ERC-20 with transfer restriction modes. Its source shows an owner-controlled setMode(uint) and renounceOwnership(). The victim add-liquidity flow uses those owner powers during launch setup, which is consistent with the trace showing Token::setMode(0) before the mint and Token::renounceOwnership() immediately after.
3. Vulnerability Analysis & Root Cause Summary
This was an ATTACK-class ACT incident caused by unsafe launch-liquidity logic. The victim’s add-liquidity path assumed that a Pancake V3 pool returned by createAndInitializePoolIfNecessary was safe to mint against, even though that function explicitly tolerates a previously created pool. The helper then constructed a mint call with amount0Desired equal to the launch-token inventory, amount1Desired equal to the WBNB budget, but amount0Min = 0 and amount1Min = 0. That choice disabled any slippage-style protection against a hostile pool price.
The code-level breakpoint is the helper call path reached from selector 0x55110640. Module 0xb287... delegatecalls helper 0xbd17... selector 0x6ff18326, which approves the token to Pancake’s NonfungiblePositionManager, calls createAndInitializePoolIfNecessary, and then calls mint without checking whether the returned amount0 and amount1 match the intended launch inventory. Because the attacker had already primed the pool price, the mint legally settled at a near-one-sided outcome.
The safety invariant is straightforward: if the launch intends to seed 200000000000000000000000000 token units and roughly 23.52 WBNB, the minted position must actually consume those intended assets at the intended launch price. The traces and balance diffs show that this invariant failed. The victim emitted LiquidityAdded for the full launch inventory, but the actual Pancake IncreaseLiquidity event consumed only 1 token unit and 23519999970521880780 wei of WBNB. That mismatch is the exploit-enabling bug.
4. Detailed Root Cause Analysis
The exploit begins with tx 0xdb5d43317ab8e5d67cdd5006b30a6f2ced513237ac189eb1e57f0f06f630d582, where the attacker uses helper 0x4fdebca823b7886c3a69fa5fc014104f646d9591 to invoke the launch contract’s public buy path. The helper’s reconstructed selectors show it wraps repeated launch buys, and the balance diff confirms that helper 0x4fdeb... receives 1603243002223000000000 units of token 0x4abfd9... while the attacker spends only 100000000000000 wei plus gas.
The attacker then primes the AMM state in tx 0x4235b006b94a79219181623a173a8a6aadacabd01d6619146ffd6fbcbb206dff. The trace shows helper 0xbf26e147918a07cb8d8cf38d260edf346977686c calling Pancake’s createAndInitializePoolIfNecessary, which emits PoolCreated for pool 0xa610cc0d657bbfe78c9d1ea638147984b2f3c05c and then Initialize with the extreme sqrtPriceX96.
PoolCreated(token0=0x4abfd9..., token1=WBNB, fee=10000, pool=0xa610cc0d657bbfe78c9d1ea638147984b2f3c05c)
Initialize(sqrtPriceX96=10000000000000000000000000000000000000000, tick=511251)
The critical victim transaction is 0xe0daa3bf68c1a714f255294bd829ae800a381624417ed4b474b415b9d2efeeb5. The trace shows proxy 0x5c95... delegating into 0xb287..., then into 0xbd17..., which calls createAndInitializePoolIfNecessary and mint. Because the attacker-created pool already exists and has a nonzero slot0, Pancake does not overwrite the manipulated price. The same trace shows the exact broken consequence:
Token::transferFrom(launch, PancakeV3Pool, 1)
WBNB::transfer(PancakeV3Pool, 23519999970521880780)
emit IncreaseLiquidity(tokenId=1552051, liquidity=186344638, amount0=1, amount1=23519999970521880780)
emit LiquidityAdded(token=0x4abfd9..., tokenAmount=200000000000000000000000000, ..., wbnbAmount=23519999999451199994)
The balance diff for the same transaction independently confirms the state change: the launch proxy’s token balance falls by exactly 1, the pool’s launch-token balance becomes 1, and WBNB increases by 23519999970521880780. This is the direct evidence that the helper trusted the manipulated pool price and never checked post-mint consumption.
Pancake’s collected source explains why this works. PoolInitializer::createAndInitializePoolIfNecessary returns an existing pool unchanged once it already exists and has a nonzero sqrtPriceX96. NonfungiblePositionManager::mint then emits IncreaseLiquidity using the actual amount0 and amount1 returned from the pool math. The victim helper accepted those returns without validation, so the attacker-controlled price fully determined how much of each asset the victim actually supplied.
5. Adversary Flow Analysis
The attack sequence is deterministic and permissionless:
- In tx
0xdb5d..., EOA0xf91848a076efaa6b8ecc9d378ab6d32bd506dc79funds helper0x4fdeb..., which invokes the public launch buy path and accumulates1603243002223000000000launch-token units. - In tx
0x4235..., EOA0x010fc97cb0a4d101dce20dab37361514bd59a53adrives helper0xbf26...to create and initialize the Pancake V3 token/WBNB pool at an extreme price. - In tx
0xe0daa..., third party0x74d86638f359bdff6ec55d78a97f294747f8f5b3triggers the victim’s launch-liquidity path. The victim proxy delegates into helper logic that reuses the already-primed pool and mints one-sidedly. - In tx
0x2902..., EOA0x935d6cf073eab37ca2b5878af21329d5dbf4f4a5uses dump helper0x06799f7b09a455c1cf6a8e7615ece04b31a9d051to sell the accumulated launch tokens into the mispriced pool, unwrap WBNB, and distribute native BNB proceeds.
The extraction transaction’s balance diff shows the main payout clearly:
{
"address": "0x8a4ae92228283a213a05b96d16df1f4d6657ac33",
"delta_wei": "21083328036280789564"
}
The same artifact shows WBNB at 0xbb4c... dropping by 23425920040311988396 wei, which matches the drained seed-liquidity outcome. The helper reconstruction also matches the behavioral roles seen on-chain: 0x4fdeb... is a buy wrapper, 0xbf26... is a pool-priming wrapper, and 0x06799... performs the final swap and native BNB fan-out.
6. Impact & Losses
The victim launch contract lost essentially all seeded WBNB liquidity intended for the token launch. The concrete loss evidenced in the extraction balance diff is 23425920040311988396 wei of WBNB, leaving only a small residual amount in the pool after the attacker dump. The launch token side of the pool is also distorted: instead of a balanced initial market, the pool is left holding attacker-sold launch tokens while the WBNB side has been drained.
The principal affected victim is the launch system behind proxy 0x5c952063c7fc8610ffdb798152d69f0b9550762b. The practical consequence is that launch-owned liquidity capital was transferred to an unprivileged adversary cluster immediately after seeding, defeating the intended launch pricing and inventory distribution.
7. References
- Victim proxy:
0x5c952063c7fc8610ffdb798152d69f0b9550762b - Victim module:
0xb28723a16d3347cdc0ce035eb1c1eb0b7406682f - Victim helper:
0xbd17a5d1f802edf1bfc80d84ad66d3039b28ce75 - Launch token source:
0x4abfd9a204344bd81a276c075ef89412c9fd2f64 - Pancake NonfungiblePositionManager source:
0x46a15b0b27311cedf172ab29e4f4766fbe7f4364 - Buy transaction:
0xdb5d43317ab8e5d67cdd5006b30a6f2ced513237ac189eb1e57f0f06f630d582 - Pool-create transaction:
0x4235b006b94a79219181623a173a8a6aadacabd01d6619146ffd6fbcbb206dff - Victim liquidity transaction:
0xe0daa3bf68c1a714f255294bd829ae800a381624417ed4b474b415b9d2efeeb5 - Extraction transaction:
0x2902f93a0e0e32893b6d5c907ee7bb5dabc459093efa6dbc6e6ba49f85c27f61 - Auditor reconstruction artifact:
/workspace/session/artifacts/auditor/iter_1/victim_code_analysis.json