October 20, 2026
|
Exploit Postmortem
Cover image for "MCN Labs' $93K Loss and How Olympix Would Have Prevented It"

MCN Labs' $93K Loss and How Olympix Would Have Prevented It

Date: September 29, 2026

Chain: BNB Chain

Loss: 92,607 USDT, about $92.6K

Class: reward accounting that read a manipulable pool reserve at accrual and again at claim

LPBonus had been paying liquidity providers on MCN Labs' FIST/MSN pool for about a year. Every MSN transfer skimmed a 2% fee, the fee was swapped into FIST, and LPBonus shared that FIST out to the people supplying liquidity on PancakeSwap. In total, about 940,041 FIST had been funded into it.

In one BNB Chain transaction, someone borrowed 13.48 million FIST, ran a short sequence of swaps and liquidity moves, and claimed 1,442,165 FIST from LPBonus, roughly 53% more than the pool had ever received. They ended the transaction holding 92,607 USDT. It worked because LPBonus measured the pool's MSN reserve once when it counted rewards and again when it paid them, and anyone with a flash loan could make those two readings disagree.

A Reward Pool Driven by Trades

MCN Labs is the incubator arm of MCN GLOBAL, which also runs the MCNEX exchange and MCN Chain. Its MSN token launched on BNB Chain in September 2025 with a 2% fee on every transfer, and LPBonus turned those fees into rewards for liquidity providers.

The design ran itself. According to the DeFiHackLabs reproduction, LPBonus's reward callbacks could only be called by MSN, and MSN fired them from inside its own transfer logic, so every swap and liquidity change topped up rewards and updated each provider's share automatically. That also meant the reward logic could be driven entirely by trades, with no keys, admin rights or governance needed.

Two Readings of the Same Number

LPBonus used one figure to decide who earned what: the amount of MSN in the FIST/MSN pool at that instant. SlowMist's analysis shows the contract read it in two places, once in AddFistFee when new rewards came in, and again in CalcPendingUser when a provider withdrew. Both readings were the live reserve, and the live reserve is whatever the last trade left it at.

A reward pool has one rule it can't break: it can't pay out more than it took in. LPBonus kept that rule only as long as the reserve looked the same at accrual and at claim, which in ordinary trading it roughly did. A flash loan, a loan borrowed and repaid inside one transaction, removes that assumption, because for the length of one transaction anyone with enough borrowed capital can put a pool's reserve wherever they want. Reading it at two different moments lets the attacker choose both numbers. It's like a payroll clerk who calculates each worker's share using the headcount on Monday and pays it out using the headcount on Friday, with the attacker deciding who's in the building on both days.

Squeeze, Accrue, Restore, Claim

The DeFiHackLabs reproduction and SlowMist's alert lay out the sequence. The attacker flash-borrowed 13,481,395 FIST from the FstSwap USDT/FIST pair, spent part of it buying MSN, and added 140 MSN with FIST as liquidity, which registered them as a provider while the pool held roughly 501 MSN.

Next they dumped 12.2 million FIST into the pool, squeezing its MSN reserve down to about 89. Selling MSN back in triggered the reward accrual at that low point, so incoming FIST was credited as though it were being split across a pool less than a fifth of its real size. The same sale pushed the reserve back up to about 491 MSN.

With the reward index inflated and the reserve restored, the attacker burned a dust-sized slice of their liquidity, 40,372 units of LP, and LPBonus calculated their payout against the restored reserve: 1,442,165 FIST. They removed the rest of the position, sold the leftover MSN, repaid the flash loan plus its 0.3% fee, and swapped the profit into 92,607 USDT, all inside block 124759921.

No public response from MCN Labs turned up in reporting on the incident.

How Olympix Catches a Reserve Read Twice

Olympix reads a contract the way an attacker does, as states, transitions and entry points, and it uses the context around the code, here the fact that MSN's own transfers drive LPBonus, to infer the rules the system relies on. The state that matters is the reward index and each provider's pending FIST, and every swap or liquidity change in the FIST/MSN pool is a transition that can move them. The signal Olympix's static analysis surfaces is reward math that divides and multiplies by a live pool reserve any swap can move, read in one function at accrual and in another at claim. Olympix has flagged this class before in other codebases.

BugPoCer picks up that signal and widens the view to the whole fee loop, since LPBonus only makes sense together with MSN's transfer hooks and the pool they read. Its Counterexample-Guided Invariant Refutation starts from the one promise any reward pool makes, which here reads: total FIST paid to providers can never exceed total FIST funded into LPBonus. BugPoCer infers that promise and keeps reordering swaps, liquidity adds and removals between an accrual and a claim until the payout side of the books runs past the funding side.

The counterexample is this attack's shape: become a provider, crush the MSN reserve, trigger accrual at the low point, restore the reserve, and claim against the high one, ending with more FIST paid than funded. BugPoCer returns it with the minimal conditions that trigger it and a generated Forge test that replays it. Because Olympix runs at every merge and before release, that test would have existed before LPBonus held a single fee.

Count Rewards on Ground That Doesn't Move

LPBonus ran for about a year before anyone moved the pool between its two readings. Reward contracts should count against values the caller can't push around inside a transaction, such as internal deposit accounting, and should be tested directly against the rule that paid can never exceed funded. If your reward or fee logic reads live pool state, book a technical walkthrough.

On-Chain References

Protocol: MCN Labs LPBonus (MSN LP reward pool)

Chain: BNB Chain

Date: September 29, 2026, 17:53:01 UTC

Block: 124759921

Loss: 92,607.317234 USDT

Attacker EOA: 0xb6ff...6f7A

Attack contract: 0xa860...43c7

LPBonus (drained, unverified): 0x5227...054b

MSN token: 0xd8b3...97c1

FIST token: 0xC988...Bc6A

FIST/MSN pool (PancakeSwap V2): 0xdD95...e6e5

Flash-loan source (FstSwap USDT/FIST): 0xB4Ec...D8C9

Attack tx: 0xecac...8e6b

Sources

SlowMist: MCN Labs LPBonus exploit alert

DeFiHackLabs: LPBonus exploit reproduction

SlowMist Hacked: BSC incident database (MCN Labs, 2026-09-30)

MCN GLOBAL: MCN GLOBAL and MSN Ignite DeFi, September 2025

More from Olympix:

No items found.

Ready to Shift Security Assurance In-House? Talk to Our Security Experts Today.