This PoC is built from the attacker's on-chain call trace, analyzed with Phalcon for a clearer step-by-step view of the transaction. Replaying those steps in a Foundry fork test was used as the method to reproduce the attacker's path and isolate the root cause below.
getEGDPrice() derives the EGD/USDT exchange rate directly from a single PancakeSwap V2 pair's live token balances:
price = USDT.balanceOf(pair) * 1e18 / EGD.balanceOf(pair)
This is an unprotected spot price: there's no TWAP, no minimum-liquidity check, and no defense against being read mid-transaction. PancakeSwap V2's swap() supports flash swaps (withdraw now, repay before the call ends), so any caller can temporarily skew the pair's reserves and have this function report a manipulated price, all within one atomic transaction.
- Flash-borrow ~424,456 USDT from the EGD/USDT pair, draining its USDT side to near-zero while leaving the EGD side untouched. This collapses
getEGDPrice()'s output, so EGD now looks far cheaper in USDT terms than it actually is. - While the price is depressed, trigger EGD Finance's reward-claim logic, which converts the caller's USDT-denominated reward quota into EGD using this manipulated price, minting/transferring a vastly inflated EGD amount (~5.6M EGD) for what should have been a modest reward.
- Repay the flash-borrowed USDT (plus pool fee) before the transaction ends, restoring the pair's reserves and leaving no trace of manipulation post-tx.
- Swap the illegitimately claimed EGD back to USDT through the router and a second pool (USDT/WBNB) to realize the profit before the price can correct.
Any single-block, single-tx price derived purely from balanceOf reads on one AMM pair is only as trustworthy as that pair's instantaneous liquidity, and instantaneous liquidity is exactly what a flash swap lets you rewrite for the duration of your call.