
Date: July 12, 2026
Chain: BNB Chain
Loss: 156.21 WBNB, about $89.6K, the pool's entire WBNB side
Class: token fee logic that burns from the pair and syncs before the sale settles
The PHX-WBNB pool on PancakeSwap V2 held about 156 WBNB on the morning of July 12, 2026. It was young, created roughly nine days earlier according to Crypto Times, and its PHX token charged a fee on every sale. At 02:05:29 UTC, a single transaction emptied the WBNB side of the pool down to 0.0001 WBNB.
The attacker's sale of 593.5 PHX should have bought a few WBNB at most. It bought 467,711.69, enough to return a borrowed 467,555.49 and keep 156.21 WBNB, about $89,600, because PHX's own transfer code had just burned nearly every PHX token the pool held and told the pool to update its books, before the sale's tokens arrived. For one swap, the pool believed it held almost no PHX at all.
PHX is a fee-on-transfer token: when someone sells it into the pair, the token contract takes a cut before the rest reaches the pool. The exploit transaction shows exactly what that cut looked like on a 593.5 PHX sale. Three other addresses received 53.41, 17.80 and 17.80 PHX, 15% of the sale in total, and the remaining 504.47 PHX went to the pool.
PHX also did something less common. During the same sale, it burned PHX directly out of the pair's balance, an amount equal to half of the sale, and then called the pair's sync() function. Sync tells a Uniswap V2 style pair to throw away its recorded reserves and replace them with whatever its token balances are right now. Everything about the pair's pricing runs off those two reserve numbers, so whatever they say at the moment of the next swap is the price.
The order of those steps was the flaw. PHX burned from the pair and called sync() while the seller's tokens were still in flight, so the pair recorded a PHX reserve that didn't yet include the sale. If the pair's PHX balance was small to begin with, the burn could take it close to zero, and sync would write that near-zero number into the reserves with the WBNB side left untouched. The next swap would then price PHX against a pool that seemed to hold almost none of it.
The teaching moment is that a token's transfer function can change the state of a market it doesn't own. Whenever token code touches a pair's balances or calls sync(), it's setting the pair's price, and it has to leave the reserves in a state that matches the trade actually happening. Think of a shopkeeper who counts the till halfway through a customer's payment and posts the new prices off that count.
The exploit transaction deployed a contract from 0xF61Ff6cd361561aC0274a7d3d197C79310bDeE61 and ran the attack from an executor at 0x8d161cb068a576b53f5be6f9f024b9c489e005f8. The executor borrowed 408,028.38 WBNB, 2,614.32 BTCB and 4,336,488.36 USDT from Lista DAO's Moolah, the flash-loan source Crypto Times identifies, and pulled more WBNB from other lending markets.
It then swapped 467,555.49 WBNB into the pair through the PancakeSwap router and directed the 886,011.37 PHX that came out to 0x1e176e5277c22d839be9f962143ce81fd7987166, the address PHX's contract reports as its owner, which Crypto Times describes as fee-exempt. After that trade, the pair held 296.75 PHX against 467,711.69 WBNB, so before the attack it had held about 156.21 WBNB.
Next came a sale of exactly 593.4995 PHX from the attacker's wallet. Half of that is 296.7497 PHX, and the pair's PHX reserve was 296.7497 PHX plus 1,000,000 wei, the token's smallest unit. PHX burned the half-sale amount from the pair and called sync(), and the pair's own Sync event records the result: a PHX reserve of 1,000,000 wei, or 0.000000000001 PHX, against an unchanged 467,711.69 WBNB.
Only then did the 504.47 PHX left after fees land in the pair. The executor called swap() and asked for 467,711.6937 WBNB. The pair checks that its balances after a trade still satisfy its pricing rule measured against the stored reserves, and with the PHX reserve at a millionth of a millionth of a token, 504 PHX more than satisfied it. The pool paid out all but 0.0001 WBNB.
The executor repaid every loan and sent the difference, 156.2057 WBNB, to the attacker's wallet. TenArmor's alert valued the loss at about $89.6K. Crypto Times places the fault in PHX's token contract and reports no compromise of PancakeSwap's contracts. As of October 20, 2026, we hadn't found a public statement from a PHX team about the incident.
Olympix reads PHX the way an attacker would, as states, transitions and entry points, and it takes in the context the token lives in, a Uniswap V2 style pair whose price is its two stored reserves, to infer the invariants the code depends on but never writes down. The states that matter are the pair's balances and reserves, and the transfer path is the entry point that can change them. The engine flags the signal in that path: a token transfer that burns from the pair's balance and calls sync() on the pair before the transfer it's processing has been credited.
The invariant is simple to state: after any transfer into the pair, its stored reserves should match its real balances in a way that reflects the trade that's happening, and no single sale should be able to pull out more of the other token than the pool's pricing allows. BugPoCer works outward from that rule. It runs Counterexample-Guided Invariant Refutation, inferring the invariant from how the fee logic interacts with the pair, then executing paths until one breaks it. Paths that never trigger the burn fall away, and the remaining ones narrow to a sale large enough that half of it matches the pair's whole PHX balance.
The counterexample it returns is the July 12 transaction in development. Buy PHX out of the pair until its PHX reserve is small, sell exactly twice that reserve so the burn empties it and sync records almost nothing, then swap the post-fee PHX in for the WBNB side. BugPoCer reports that sequence with its minimal conditions, a pair holding little PHX and a sale sized against it, plus a generated Forge test that replays it and shows the pool losing its WBNB. It runs automatically as code is written, at every merge and before release, so a fee routine that calls sync() at the wrong moment shows up before a pool ever trades against it.
A token contract that reaches into its own liquidity pool takes on the pool's job of keeping reserves honest, and PHX did it at the one moment when the pool's books couldn't reflect the trade. Builders shipping fee-on-transfer or burn-on-sell tokens can close this class by settling the transfer first and syncing after, or by never burning from the pair at all. To see how Olympix tests the way your token logic interacts with the pools that price it, and returns a runnable counterexample when it breaks, book a technical walkthrough.
Protocol: PHX token and its PHX-WBNB PancakeSwap V2 pool
Chain: BNB Chain
Date: July 12, 2026, 02:05:29 UTC
Loss: 156.2057 WBNB (about $89.6K per TenArmor)
Attacker EOA: 0xf61f...ee61
Contract deployed by the exploit tx: 0x843d...8d6d
Attack executor: 0x8d16...05f8
PHX token: 0x2540...a481
PHX-WBNB pair (victim): 0x09db...b6cf
PHX owner address: 0x1e17...7166
Moolah (flash-loan source): 0x8f73...5d8c
Exploit tx: 0xb5a6...1ebe
Block: 109472554
TenArmor: Security Alert on PHX (BSC)
Crypto Times: PHX-WBNB Liquidity Pool Drained of Nearly $90K in BNB Chain Exploit