TMX Tribe's $893K Loss and How Olympix Would Have Prevented It
Date: January 5, 2026
Chain: Arbitrum
Loss: 846,008.85 USDT0, 828.81 USDC and 340.79 WSOL, about $893K
Class: pool value accounting that let a mint, swap and redeem loop pay out more than it took in
At 01:00:12 UTC on January 5, 2026, a wallet on Arbitrum deposited 55,109.95 USDT0 into TMX Tribe's liquidity pool and received 54,286.12 staked TLP, the pool's liquidity token. Seventeen seconds later it bought USDG, the protocol's internal stablecoin, straight from the vault. Sixteen seconds after that it redeemed the same 54,286.12 TLP and got back 57,323.68 USDT0. Then it sold its USDG back to the vault and started again.
TMX Tribe was a GMX fork offering perpetual futures on Arbitrum, and its liquidity pool paid out more than it took in every time that loop ran. Over the next two hours and nineteen minutes or so, the wallet repeated it dozens of times and left with about $893K of the pool's assets. The pool priced its liquidity token from accounting that the attacker could inflate with a swap, and the redemption that followed paid out at the inflated price.
A GMX Fork With Its Own Accounting
GMX's design, which TMX copied, pools every asset traders trade against into one vault. Liquidity providers deposit stablecoins or other assets and receive the pool's liquidity token (GLP in GMX, TLP in TMX), and they earn the fees traders pay. The liquidity token's price comes from the pool's assets under management, or AUM, divided by the token's supply. Every mint and redemption is priced off that number, so if AUM is wrong, every mint and redemption is wrong in the same direction.
USDG sits underneath that machinery. In GMX-style vaults it's an accounting stablecoin: the vault mints USDG when assets come in and burns it when they go out, and the liquidity token's minting and redemption run through it. TMX's vault, at 0x67AF...1Cb4, did the same. On-chain, TMX's reward router and swap router are TransparentUpgradeableProxy contracts deployed by the address 0x3339...9543, and the implementations behind both were never verified on Arbiscan, so their source code isn't public.
Four Transactions That Paid 1,500 USDT0
The first cycle of the main run shows the whole mechanism in four transactions, all readable on Arbitrum's explorer.
At 01:00:12 UTC the wallet called TMX's reward router, which took 55,109.95 USDT0 into the vault, minted 54,641.52 USDG to another TMX contract, and gave the wallet 54,286.12 TLP, which was immediately staked. At 01:00:29 it sent 82,664.93 USDT0 to the vault through the swap router and received 81,962.28 USDG minted directly to its own address. At 01:00:45 it unstaked and redeemed its 54,286.12 TLP, and the vault burned 57,323.68 USDG and paid out 57,323.68 USDT0. At 01:00:59 it sold the 81,962.28 USDG back and received 81,962.28 USDT0.
Adding up the four transactions, the wallet put in 137,774.88 USDT0 and took out 139,285.96 USDT0, a gain of 1,511.07 USDT0 in 47 seconds. The swap leg lost a little to fees. The liquidity leg gained 2,213.72 USDT0, because the same TLP redeemed for about 4% more than it cost to mint.
The only thing that happened between the mint and the redemption was the USDG purchase. That purchase moved 82,664.93 USDT0 into the vault without creating any TLP. Under the GMX pricing model, that's exactly the kind of deposit that raises the pool's measured value per TLP, and the redemption then paid the attacker as if the pool had grown. The USDG the attacker held was still a claim on the same USDT0, which it collected a few seconds later. Rekt's analysis describes the exploit as flawed logic in TMX's minting, staking and swapping, with no flash loans, oracle manipulation or reentrancy involved.
The Teaching Moment: Count Every Claim Once
A liquidity pool's value has to account for every claim on its assets, including claims held by people who aren't liquidity providers. When a deposit enters the vault and the depositor walks away holding a token that can be redeemed for that deposit, the pool hasn't gotten richer. If the LP token's price counts that deposit as pool value anyway, anyone who can make the deposit, mint and redeem around it can collect the difference, and the pool's real liquidity providers pay for it.
An everyday version would be a shared fund that counts a member's short-term loan to the fund as fund profit. Everyone's share looks more valuable for the length of the loan, and the member who made the loan can cash out at that price and then ask for the loan back.
Two Hours on Arbitrum, Two Days of Preparation
The main exploiter wallet, 0x763a...2661, received its first funds through a cross-chain bridge relay at 11:02:53 UTC on January 3. A second wallet it funded, 0x16Ed...288d, ran the same mint, swap and redeem cycle from 16:59 UTC on January 3 until 20:18 UTC on January 4, but its net flows with the vault came to almost nothing. At 00:51 UTC on January 5, the main wallet bridged in another 137,774.89 USDT0 through Across and started the run that worked.
From 01:00:12 to 03:19:06 UTC, the main wallet sent 393 transactions to TMX's reward router and swap router, 371 of which succeeded. Summing every token transfer between the wallet and the vault across the whole run, the vault paid it a net 846,008.85 USDT0, 828.81 USDC and 340.79 WSOL. The USDG side netted to zero, with 11,558,609.75 USDG minted to the wallet and the same amount returned. Valuing the WSOL at CoinGecko's $134.43 for January 5, the take comes to about $893K.
Rekt's headline figure is about $1.4M, and Rekt traces just under $1.2M bridged to Ethereum as 260 WETH, 3.42 WBTC and 15.94 WETH, but it doesn't give a method for the total. The bridged amounts would include the capital the attacker brought in as well as the profit, so this post uses the on-chain net from the vault.
A Bounty Offer and Upgrades Mid-Drain
According to Rekt, the stolen assets were swapped to ETH, bridged from Arbitrum to Ethereum through Across, and deposited into Tornado Cash, leaving the exploiter address with about $21. At 13:46:57 UTC on January 5, the same address that deployed TMX's proxy contracts, 0x3339...9543, sent the exploiter an on-chain message, which Rekt reports offered a bounty of 20% for returning 80%. Rekt reported no response.
Rekt also notes that no pause or circuit breaker was triggered during the drain, that the team's wallet deployed and upgraded contracts repeatedly during and after the attack, and that TMX's X account was deleted and then reappeared with a single post. As of Rekt's January 8 report, TMX hadn't published a statement or a compensation plan, and Rekt found no security audit for the protocol.
How Olympix Finds the Deposit That Inflates the Pool
Olympix reads a protocol the way an attacker does, as states, transitions and entry points, and it works on the source code a team actually ships, so verified source on a block explorer isn't a prerequisite. In a GMX-style vault, the states that matter are the pool's asset balances, the AUM computed from them, the USDG and TLP supplies, and the price every mint and redemption uses. The entry points that move them are few: mint and stake, unstake and redeem, swap into USDG, swap out of USDG.
The engine narrows from every path to the feasible ones that can change TLP's price, and then to sequences that touch the invariant. The signal here is a path that adds assets to the vault and changes AUM without minting or burning TLP, sitting next to a redemption path that prices TLP off that same AUM. That combination is what makes a mint, swap and redeem sequence worth attacking.
The invariant fits in one sentence: a round trip through the pool's public entry points must never return more than it put in, apart from fees. BugPoCer runs Counterexample-Guided Invariant Refutation, inferring that rule from the vault, the LP manager and the router as one system and executing sequences of calls until one breaks it. Given TMX's source, the counterexample is the four-transaction cycle above: mint TLP, buy USDG from the vault, redeem the TLP at the higher price, sell the USDG back. BugPoCer returns it with the minimal conditions that trigger it and a generated Forge test that replays it, which turns the January 5 drain into a failing test in development.
Olympix has flagged this class before in other codebases, where share accounting let a deposit and withdrawal cycle redeem more than it put in. Running at every merge and before release, the engine would have surfaced the loop before the vault held any liquidity provider's money.
Forks Inherit the Invariants Too
Forking a battle-tested protocol copies its code, and it also copies the assumptions that code depends on, including which paths are allowed to move the numbers that price everyone's share. Any change to how a forked pool mints, swaps or values its assets needs the round-trip rule checked again from scratch. If you're running a pool built on someone else's design, see how Olympix tests every sequence through your vault against the rules it depends on and hands back a runnable counterexample for any that pays out too much, and book a technical walkthrough.
On-Chain References
Protocol: TMX Tribe (GMX fork)
Chain: Arbitrum
Date: January 5, 2026, 01:00:12 to 03:19:06 UTC (main run)
Loss: 846,008.85 USDT0, 828.81 USDC and 340.79 WSOL net to the main exploiter (on-chain), about $893K
Main exploiter: 0x763a...2661
Second exploiter wallet: 0x16Ed...288d
TMX vault: 0x67AF...1Cb4
Reward router proxy: 0x6E78...Ba46
Swap router proxy: 0x18f3...E425
Deployer and bounty sender: 0x3339...9543
First mint in main run: 0xc1d8...dbab
USDG purchase: 0x5467...e4d5
Redemption: 0x24cf...de62
USDG sale: 0x3d35...6277
Block (first mint): 417991135
Funding tx (January 3): 0xaa78...95d8
Bounty message tx: 0xb31a...ccf4
Sources
More post-mortems
See every post-mortem →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.




