BNB Chain
Reserve manipulation

NEM's $822K Loss and How Olympix Would Have Prevented It

Loss
Loss
Exploit date
October 21, 2026

Date: October 21, 2026, 03:28:50 UTC

Chain: BNB Chain

Loss: 821,920 USDT drained from the USDT/NEM pool on PancakeSwap

Class: a burn-and-sync settlement function fed by sell volume that any transfer into the pool could fake

NEM's token contract carried a deflationary routine meant to reward real selling. Whenever NEM landed in its PancakeSwap pool, the contract logged it as sell volume, and a settlement function later burned a share of that volume straight out of the pool and told the pool to re-read its balances. Each burn made the remaining NEM scarcer against the USDT beside it, which was the whole point.

On October 21, 2026 at 03:28:50 UTC, one transaction turned that routine against the pool's liquidity providers. The attacker fed the pool NEM, took the same NEM straight back, and let the settlement function burn the pool's own tokens on the strength of a sale that never happened. Forty-two rounds later, the pool's NEM reserve had shrunk from about 210,382 tokens to under 30, and a single sale of roughly 75,700 NEM pulled out 821,920 USDT more than the attacker had put in.

Sell Volume That Anyone Could Manufacture

The token, deployed as NemTokenV2 and named Newmont on-chain, traded against USDT in a PancakeSwap V2 pair. Like many BNB Chain tokens, it built its economics into its own transfer logic. A counter called pendingLpSellRecycle grew whenever NEM arrived at the pair, and a function called flushLpSellRecycle() turned that counter into a burn. The on-chain record shows exactly how much: each flush burned 70% of the NEM that had just been counted, taking it directly from the pair's balance, and then called the pair's sync() so the burned tokens disappeared from the pool's recorded reserve too.

The flaw sat in how the counter decided what counted as a sale. According to CertiK, as reported by Crypto Briefing, the contract treated any transfer into the pair as sell volume without checking whether a real swap had taken place. SlowMist, via PANews, describes the same gap as a contract that never verified the result of the swap settlement. A plain transfer to the pair's address looked identical to a sale.

That would have been harmless if the transferred tokens stayed in the pool, because the attacker would have paid for every burn with real NEM. PancakeSwap's skim() removed that cost. A V2 pair tracks two numbers for each token: the balance it actually holds and the reserve it last recorded. Anyone can call skim() and collect the difference. So the attacker could send NEM to the pair, push pendingLpSellRecycle up, and skim the same tokens back out before the flush ran. The counter kept the credit, the attacker kept the tokens, and the burn came out of NEM that belonged to liquidity providers.

Forty-Two Rounds Inside One Transaction

The attack contract started by flash-borrowing roughly 235.8 million USDT from about twenty lenders and pools. It swapped all 235,785,000 USDT into the pair in one buy, which sent 53,007,476.60 NEM to a helper address the attacker controlled. That trade alone moved the pool to about 236.7 million USDT against just 210,382 NEM. The pool was now enormous on one side and thin on the other, which made every NEM removed from it far more valuable.

Then the loop began. In the first round, the attack contract transferred 32,631.98 NEM to the pair, skimmed the same 32,631.98 NEM out to its helper, and the flush burned 22,842.39 NEM from the pair, exactly 70% of the phantom sale. A sync followed, and the pool's recorded NEM reserve dropped to about 187,539 while its USDT side stayed put. The next round did the same thing against the smaller reserve, and so on. Across 42 rounds, the token contract burned 210,352.35 NEM out of the pair, leaving it with less than 30 NEM against roughly 236.7 million USDT.

With the reserve compressed that far, the final step was a single sale. The attack contract sold 75,693.74 NEM into the pair and received 236,606,920.44 USDT. Subtracting the 235,785,000 USDT it had put in, the pool lost 821,920.44 USDT, which is the figure SlowMist reported. The pool's USDT reserve fell from about 933,469 before the attack to about 111,549 after it.

The attacker didn't keep all of it. Repaying about twenty flash loans with their fees cost roughly 95,600 USDT, and the attacker's wallet received 726,307.10 USDT at the end of the transaction. CertiK said the stolen funds were then bridged to Ethereum. As of October 22, 2026, the NEM team hadn't published a post-mortem or a recovery plan.

A Familiar Shape on BNB Chain

Token contracts that reach into their own liquidity pool keep running into the same wall. The pool's reserves are a shared ledger owned by liquidity providers, and every token-level routine that burns from it or forces a sync is a lever on price. Crypto Briefing's report on the CertiK alert links NEM to comparable reserve-manipulation attacks earlier in 2026, including ATM and LULA. NEM's version was unusually clean for an attacker because the settlement function did all the work. The attacker never had to find a way to burn the pool's tokens; the contract volunteered to do it after any transfer.

The lesson for builders is narrow and concrete. When a token infers trading activity from where tokens sit, anyone who can move tokens can fabricate that activity. The recycle counter needed to be driven by a confirmed swap, measured by what the pool actually received and kept, and any routine that burns from a pair and calls sync() needs the same scrutiny as a withdrawal function.

How Olympix Catches a Burn That Answers to Fake Sales

Olympix reads a contract the way an attacker does, as a set of states, transitions and entry points. In NEM's token contract, two pieces of state decide the pool's price: the pair's recorded NEM reserve and the pendingLpSellRecycle counter that drives the burn. The engine maps every entry point that can change either one, then uses signals to narrow from all paths to the feasible ones and from those to the paths that touch an invariant.

Static analysis surfaces the signal right away. A function anyone can trigger burns tokens from the pair's balance and then calls sync(), and the amount it burns comes from a counter that a plain transfer to the pair can raise. Olympix has flagged this class before in other codebases, where settlement or issuance logic priced itself off a spot value the caller could move.

BugPoCer turns that signal into proof of a break. It runs Counterexample-Guided Invariant Refutation from the system outward, starting with the rule the pool depends on: the recorded NEM reserve should only fall when NEM really leaves through a trade, and no caller should be able to shrink it for free. BugPoCer infers that invariant from how the contract and the pair interact, then searches for a sequence that violates it. The one it finds is short. Transfer NEM to the pair, call skim() to take it back, let flushLpSellRecycle() burn 70% of the phantom amount from the pair and sync, and repeat until the reserve is nearly empty.

The output is a counterexample: the sequence of state changes, the minimal conditions that make it work, and a generated Forge test that replays it on a fork. For NEM that test is the October 21 attack in miniature, run at a merge or before release instead of on mainnet with 235.8 million borrowed dollars.

What the Pool Was Owed

Liquidity providers in the USDT/NEM pair trusted that the pool's reserves would move only when someone traded against them. NEM's settlement routine broke that trust with one unchecked inference, and a single transaction turned it into an $822K loss. If your token touches a PancakeSwap or Uniswap pool's reserves in any way, Olympix maps every path that can move them and hands back a runnable counterexample for each one that breaks an invariant. To see it work against your own contracts, book a technical walkthrough.

On-Chain References

Attacker EOA: 0xfd92...e9b6

Attack contract: 0x5e6d...1ca2

Helper address (received bought and skimmed NEM): 0x0003...10de

NEM token (NemTokenV2): 0x9cf0...7777

USDT/NEM PancakeSwap pair (victim pool): 0x840e...12b8

Exploit tx: 0xfb09...3f91

Block: 128866147

Sources

SlowMist: NEM attack alert

Phalcon: NEM price manipulation alert

Crypto Briefing: CertiK flags $820K exploit draining NEM token's PancakeSwap liquidity pool

PANews: SlowMist, NEM attacked with loss of about $821,920

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.