BNB Chain
Price manipulation

WHALE Token's $3.5K Loss and How Olympix Would Have Prevented It

Loss
Loss
Exploit date
June 17, 2026

Date: June 17, 2026

Chain: BNB Chain

Loss: 3,460.41 USDT

Class: mining hashrate credited from a flash-inflated AMM reserve

WHALE's PancakeSwap pool held about 3,496 USDT and 958.5 WHALE when the attack began, according to crypto.training's reproduction. Against that small pool, in a single transaction mined at 10:43 UTC on June 17, 2026, the attacker borrowed more than 41 million USDT, pushed it through the pool, and gave every borrowed dollar back before the transaction ended. What stayed behind was a hashrate balance WHALE's contracts had credited at a reserve roughly 16,000 times larger than the honest one, and the WHALE tokens that balance paid out.

The exploit transaction itself shows 3,460.41 USDT landing in the attacker's wallet, the same figure the DeFiHackLabs proof of concept records, and the flaw that produced it sat in the arithmetic WHALE used to decide how much every liquidity provider earned.

Mining Rewards Measured in LP

WHALE tied its token emissions to liquidity. Providers who added liquidity to the WHALE/USDT pair earned hashrate, recorded in a companion contract called WHALEHashrate as hWHALE, and hashrate in turn entitled them to newly minted WHALE through the token's mining emission. The more value a provider added to the pool, the more hashrate they were supposed to get.

Measuring that value is the delicate part. A liquidity position's worth depends on the pool's reserves, and the reserves of an automated market maker move every time someone trades. According to crypto.training, WHALEHashrate computed the hashrate for new liquidity at settlement time as twice the new LP amount, multiplied by the pair's current USDT reserve and divided by the pair's current total LP supply. The reserve in that formula was the one the pair reported at that moment, after the new liquidity had been minted.

A Comment That Named the Risk

crypto.training quotes a comment in the WHALE source explaining that an earlier stage-time reserve snapshot had been deleted and that settlement now used the current getReserves() value, a change that opened what the comment itself calls a self-inflation surface. The reproduction describes that trade-off as accepted for code simplicity. Two other pieces made it reachable. The mining emission function only enforced a global cap, with no limit per user or per block, and a PolVault function called flushPol() could be called by anyone, which let the attacker reset the baseline WHALE used to measure new liquidity partway through the transaction.

Together, those pieces meant that anyone who added liquidity while the pool's USDT reserve was enormous would be credited as if their position were worth an enormous amount, and nothing checked whether that reserve was real.

Forty-One Million Borrowed Dollars

crypto.training's walkthrough lays out the transaction. The attack contract borrowed 7,772,960 USDT from Moolah and 34,075,340 USDT from the PancakeSwap Infinity Vault. It made a 1,000 USDT priming buy, added a first round of liquidity, and called flushPol() to re-baseline WHALE's staging.

Then it bought WHALE with 15,000,000 USDT. That single swap lifted the pair's USDT reserve to about 15,005,778, roughly 16,000 times its honest level. The contract added a second round of liquidity, including a large USDT donation, which pushed the USDT reserve to about 20,632,945. A zero-value WHALE transfer then triggered settlement, and WHALEHashrate credited the attacker's 771.98 new LP at that inflated reserve. The result was 10,434,499 hWHALE. At the honest reserve, crypto.training calculates, the same LP would have earned about 479.

The harvest came next. A zero-value transferFrom from the pair minted 293,639 WHALE into the pool as a mining reward, and the contract sold about 294,529 WHALE for 20,632,911 USDT. It repaid both lenders in full and forwarded 3,460.41 USDT to the attacker's wallet, a transfer visible in the transaction's logs. crypto.training's reproduction lands one cent higher, at 3,460.42 USDT.

Reserves Are a Snapshot of the Last Trade

An AMM's reserves are an honest description of the pool right now, and that's exactly why they make a poor measure of value for anything that pays out. Whoever controls the trades in a transaction controls the reserves for its duration, and a flash loan gives anyone that control for the price of a fee. WHALE's own source acknowledged the exposure when the snapshot was removed. Elsewhere this year, a flash-loaned price spike let a 214K LPD deposit at LpdFi record $140M of principal and drain $694K, a much larger version of the same mistake of valuing a deposit at a number the depositor can move.

The defenses are well understood. Value reward rights from a snapshot taken before the depositor can trade, or from a time-weighted average, reject or discount additions made while reserves sit far from that reference, cap emissions per account and per block, and keep functions that reset accounting baselines away from arbitrary callers.

How Olympix Would Have Caught the Inflated Credit

Olympix reads a system like WHALE as states, transitions and entry points spread across several contracts. The states that matter are each provider's LP, their hashrate in WHALEHashrate, the WHALE minted through mining emission, and the pair's reserves. The transitions are swaps, liquidity additions, settlement on transfer, flushPol() and harvest. Olympix's static analysis would have surfaced the signal here: a reward credit computed from the pair's live getReserves() value inside a path any caller can reach in the same transaction as a swap, with no snapshot, no TWAP and no deviation check between the reserve read and the hashrate it produces.

That signal narrows the search to the paths that feed the invariant WHALE's mining depends on. Hashrate should track the real value a provider adds, so no one should be able to earn more WHALE than their contribution justifies by trading against the pool first, and no sequence of actions inside one transaction should let a caller leave with more USDT than they brought. BugPoCer would have run Counterexample-Guided Invariant Refutation from the token, the hashrate contract, the vault and the pair outward, inferred that invariant, and searched for a sequence that breaks it with the pool's reserves free to move.

The counterexample it would have returned follows the shape of the real attack. Borrow, add a small position, reset the staging baseline, inflate the USDT reserve with a large swap and donation, add liquidity and settle at the inflated reserve, harvest the over-credited emission, dump it into the pool and repay. BugPoCer would have returned that sequence with the minimal conditions that trigger it and a generated Forge test that replays it, which would have been the June 17 drain produced in development, on the change that deleted the reserve snapshot.

A Reward Is Only as Honest as Its Inputs

WHALE wrote a mining system around a measurement anyone could distort for the length of one transaction, and the code said so in a comment. Any protocol that turns liquidity into rewards needs that measurement tested against a caller who moves the pool first. To see how Olympix traces every reserve and price read in your reward logic and returns a runnable counterexample when one can be inflated, book a technical walkthrough.

On-Chain References

Protocol: WHALE token, WHALEHashrate and the WHALE/USDT PancakeSwap pair

Chain: BNB Chain

Date: June 17, 2026, 10:43:36 UTC (block 104,744,231)

Loss: 3,460.41 USDT

Attacker EOA: 0xa27e...9bfa

Attack contract: 0x4ce3...1386

WHALE token: 0xABC7...0123

WHALEHashrate (hWHALE): 0x436C...3691

WHALE/USDT pair: 0xdD31...4D59

Exploit tx: 0xf8f4...6d86

See what Olympix finds on your own code

Send us a repo that's already been audited, and we'll run Olympix at the same commit and show you what comes back.