The $120 million Tectonic hack that shut down Cronos
Cronos froze its own blockchain in the middle of a robbery, then rewound it and struck the theft from the record. We indexed the chain to four seconds before it stopped, added up what the drain took, and followed the part that got away.
On the afternoon of 30 August, the people who run the Cronos blockchain did something networks are not supposed to be able to do. They switched it off.
Cronos is a blockchain backed by Crypto.com, and like most blockchains it is meant to keep producing blocks whether anyone approves of what is in them or not. That afternoon its validators agreed to stop, in the middle of a robbery, because stopping was the only way to keep the money from leaving. It worked, and then they went further than stopping. When the chain came back that evening it had been rewound to the block before the attack, and the theft had been struck from the record.
The target was Tectonic, the biggest lending market on the chain. A lending market is a pool of money other people deposited, which you can borrow from if you leave something valuable behind as security. Tectonic held about $122 million of deposits, by DefiLlama's count, close to half of everything on Cronos. By the time the chain stopped, its lending pools were empty.
Bitquery indexes Cronos, and our index runs to four seconds before the chain stopped. We pulled the transaction that emptied Tectonic and added up what it moved. It drained nine lending markets in 11 transfers, taking everything from dollar stablecoins to bitcoin to XRP, and the total came to $120.4 million.
Then we followed the money, which matters more than usual here. Everything still on Cronos when the chain stopped has since been erased. The only part of this robbery that survives is what had already crossed the bridge to Ethereum in the 103 minutes before the halt, and that is $8.3 million rather than the $6 million in circulation. It sits in four wallets, three of which have not been named anywhere.
01How you rob a lending pool
Borrowing on a platform like Tectonic works the way a pawnshop does. You hand over something valuable, and you get to walk out with a fraction of what it is worth. Leave $100 of one token, borrow $80 of another. If your collateral falls too far in value, the platform sells it and settles up.
The whole thing rests on one point: the platform has to know what your collateral is worth. It learns that from a price feed, a piece of software that watches where the token trades and reports the number back. If you can move the price the feed is watching, you can make the platform believe your collateral is worth far more than it is, and borrow against a number you invented.
That is what happened here, and the token chosen for it was TONIC, Tectonic's own. TONIC is worth about a hundred-millionth of a dollar and barely trades, which is exactly why it was chosen. Moving its price took $1.4 million of borrowed money, and that was enough to move it by a factor of nearly 300.
The attacker deposited $5 million of real dollars, borrowed the entire supply of TONIC that Tectonic had, put it straight back in as collateral, and borrowed again. That loop ran 98 times inside a single transaction. By the end of it the collateral claim on record was about two thirds of every TONIC that exists.
Then they bought TONIC on the open market with money borrowed from Tectonic itself, and waited for the price feed to catch up. Over the next seven minutes the traded price rose to almost 300 times where it started, and the feed followed it up in steps.
02What the drain actually took
At 12:49:39 UTC the attacker made one call to their own contract. It emptied Tectonic's all nine of its lending markets, taking from each one exactly the cash it had available, down to the last unit.
Two of those nine were the dollar stablecoins, and they were the bulk of it. They were split between two destinations, three quarters going to a plain wallet and a quarter to a contract. Between them the two stablecoins came to $100.9 million. The three-quarter share that landed in the wallet, $75.7 million, is the figure most counts stop at.
The other nine legs went to that contract, which the attacker had deployed almost two weeks earlier. Bitcoin, ether, Crypto.com's own wrapped bitcoin and ether, staked CRO, wrapped CRO and XRP, plus the quarter-share of both stablecoins. Together they came to $44.7 million, spread across assets small enough to be easy to miss.
Tectonic's own books show the same thing from the other side. The cash held across its markets fell by about $119 million between the day before the attack and the halt. The biggest market, its USDC pool, was left holding three cents.
Every transfer the drain made, across nine markets. Marked with Tectonic's own price feed from the block before the attack.
| Asset | Amount | Value | Sent to |
|---|---|---|---|
| USDC | 41,429,611.35 | $41,427,963 | A plain wallet |
| USDT | 34,238,092.49 | $34,235,145 | A plain wallet |
| USDC | 13,809,870.45 | $13,809,321 | The contract |
| USDT | 11,412,697.50 | $11,411,715 | The contract |
| WBTC | 98.04 | $7,713,270 | The contract |
| WETH | 1,895.10 | $4,669,805 | The contract |
| CDCBTC | 32.93 | $2,590,723 | The contract |
| LCRO | 26,243,727.70 | $2,104,797 | The contract |
| WCRO | 16,745,476.51 | $1,028,641 | The contract |
| CDCETH | 379.67 | $1,005,170 | The contract |
| XRP | 270,650.42 | $378,736 | The contract |
| Total | $120,375,285 |
03Twelve days of practice
The contract that received those nine assets had been sitting on the chain since 18 August, twelve days before it was used. Creating it was the very first transaction the operator's wallet ever made on Cronos.
What it did over the following hours reads like a dry run. About $1,900 each of USDC, USDT, wrapped bitcoin, wrapped ether and wrapped CRO were walked through it, one asset at a time. That is the same set of assets the drain would later take, at roughly one twenty-thousandth of the scale.
Two days later they tested the way out. The contract sent a small amount of CRO to a second wallet, which pushed it through a cross-chain bridge in four equal batches and kept the change. The change is what funded the attack: on 24 August that wallet sent 12,800 CRO to the operator, and over the next few hours dealt small amounts of gas to every other address that would be used on the day.
None of this was subtle, and none of it was hidden. It was simply done early, on a chain nobody was watching that closely, in amounts too small to trip anything.
0411 minutes
At 12:38:56 UTC on 30 August the operator deployed two more contracts and ran the loop. That single transaction burned 33 million units of gas and emitted 677 events, which is an enormous amount of work to fit into one block.
Three follow-up transactions over the next seven minutes borrowed more money from Tectonic and spent it buying TONIC, feeding the price the feed was reading. The first of the three failed. They adjusted it and sent it again, which is worth noting, because it tells you the operation was being steered by hand and not simply fired off.
At 12:49:39 the drain went through. 11 minutes had passed since the first setup transaction, and Tectonic's lending markets were empty.
05Three ways out, and a deadline nobody announced
Getting money off a blockchain you have just robbed is harder than taking it. The attacker used a bridge, a service that accepts your money on one chain and pays you an equivalent amount on another. Three separate streams went through it.
The one everybody reported is the stablecoins. Around $6.3 million of USDC reached Ethereum between 13:03 and 14:15, and every cent of it was swapped into ether within the hour. That wallet has 2,592 ether in it now and has not touched it since.
The second stream is the one that has gone unreported, and it is the more interesting of the two. The vault contract spent the hour after the drain selling its odds and ends, the staked CRO, the XRP, the ether, the bitcoin, into whatever pools on Cronos would take them. It turned the proceeds into ordinary CRO and pushed it out through the same bridge in 28 batches.
The last batch cleared at 14:31:24. Cronos stopped at 14:32:47. The attacker was still moving money 83 seconds before the network went dark, and that final batch was still paid out on the other side.
A third, smaller stream moved $200,000 of USDT through a wallet that has not been named anywhere either. All three streams paid out to addresses on Ethereum that we can match back to the Cronos side, because the same wallet addresses were used on both chains and each payment landed within twenty seconds of the batch that triggered it.
06What survived
Stopping the chain saved most of the money. Rewinding it saved the rest, apart from what had already gone.
At the moment Cronos stopped, about $111 million of the take was still on it, and the largest single piece of it was not sitting in a wallet at all. Roughly $60 million had been put into a liquidity pool on VVS Finance, a trading venue on the chain, which is why anyone scanning that address for tokens found it empty. It held three quarters of that pool. None of it is there now.
Both columns were read from chain state. The middle column is the halt block; the right column is the same wallet after the restart. Ether is marked at $2,472.66, the Uniswap spot when these balances were read. Wallets tagged new appear in no published account of the hack.
| Wallet | Holding | At the halt | Now |
|---|---|---|---|
| On Cronos | |||
0x7d4e | 75.0079% of the VVS USDT/USDC pool | $60,116,025 | $5,000,950their own capital, returned |
0x085f | Nine assets, from USDC to XRP | $42,200,000 | gone |
0x215a | 7,770,403.28 USDC | $7,771,756 | gone |
0x9ea6 new | 408,092.49 USDT and 372,049.66 USDC | $780,199 | gone |
0x8661 new | 4,226,828.21 CRO | $241,775 | gone |
0xfdb1 new | 1,459,645.89 CRO | $83,492 | gone |
0xc404 | 38,032.90 of a second USDC contract | $38,376 | gone |
| Subtotal | $111,231,623 | $5,001,355 | |
| On Ethereum | |||
0xc404 | 2,592.2152 ETH | $6,409,667 | untouched |
0xfdb1 new | 670.6255 ETH | $1,658,229 | untouched |
0x9ea6 new | 73.7346 ETH | $182,321 | swapped to ether 31 Aug |
0x8661 new | 19.8695 ETH | $49,130 | untouched |
| Subtotal | $8,299,347 | all still held | |
What got out is $8.3 million, spread across four wallets on Ethereum rather than one. Most of the attention has gone to the stablecoin stream; the rest of it is the CRO, which arrived as ether at an address nobody has connected to this. Because it landed on a different chain, no vote on Cronos could reach it.
Three of the four wallets have not been touched since 30 August. The fourth swapped its whole stablecoin balance into ether on 31 August and has held it since. There is still no exchange deposit, no mixer, and nothing at all on the five other major chains we checked.
Three of the wallets on that list appear in no published account of the hack, and they hold $1.89 million of what survived. They are not hard to link to the rest: one of them dealt out the gas that every other wallet in the operation ran on, in the days before the attack.
07The crowd that came for the crumbs
One thing this attack was not is private. Pushing a token up by a factor of nearly 300 in a pool that thin is loud, and the market heard it immediately.
In the 17 minutes around the manipulation, one TONIC trading pool saw 638 trades from 236 different addresses, moving $5.1 million between them. The attacker is three of those trades. Everything else is other people, mostly automated traders with the machine-made wallet addresses that mark them out, piling into a token whose price had come loose from anything real.
That matters for anyone trying to work out what Tectonic can recover. The collateral the attacker left behind is TONIC, and its value depends on those same pools. Those pools were manipulated, and they were also emptied and refilled by hundreds of strangers who had nothing to do with the attack.
08A chain that changed its mind
Cronos started producing blocks again at 23:49 UTC the same evening, a little over nine hours after it stopped. It did not pick up where it left off. The chain had been rewound to block 90,896,189, timestamped 12:38:55 UTC, one block and one second before the attacker's first transaction. Everything after that point, 10,961 blocks of it, was discarded.
The effect is total. The setup transaction and the drain no longer return anything from a Cronos node; as far as the chain is concerned they were never sent. The orchestrator and the borrower have no code at their addresses, because they were created in a transaction that now does not exist. Tectonic's markets are whole: the USDC pool that was left holding three cents is back to $54.2 million, and the fake collateral position has gone with everything else.
The attacker was also handed back the $5 million of real money they had put up, because it arrived on Cronos the day before the fork and was only spent afterwards. Their own capital was restored along with everyone else's.
What could not be reached is the part that had already left. A vote among the people who run one chain does not travel to another, so the ether sitting on Ethereum stayed exactly where it was. That is the whole of what this robbery earned, and it is the reason the 103 minutes between the drain and the halt mattered so much more than they looked at the time.
It is worth being clear about what happened here, because it is unusual. A blockchain is supposed to make history expensive to change. Cronos changed roughly eleven thousand blocks of it by agreement, in under a day, and undid a nine-figure theft in the process. Whether that is a feature or the absence of one is an argument for other people. As a matter of record it worked, and it worked only for the money that had not yet left.
09Read the addresses carefully
Within minutes of the drain, a second and unrelated set of actors turned up: address poisoners. They watch for large transfers and copy them using fake tokens, sending the same amounts from lookalike addresses, hoping somebody later copies the wrong one.
Here they mirrored the real transfers to the digit. A counterfeit contract calling itself USD Coin sent exactly 3,563,579.9794 of itself to an address that begins and ends with the same characters as the real destination. Anyone reading a block explorer sees both.
This is why the abbreviated addresses in the early alerts are a problem. One of them, written as 0xc404…72dd, matches the genuine Ethereum wallet and its counterfeit twin equally well. There is a further trap that has nothing to do with the attacker: Cronos carries two separate, legitimate contracts that both report the symbol USDC, and any tool that adds up balances by symbol rather than by contract will merge them.
There is plenty the chain does not record. We cannot see where the $5 million of starting capital was staged, only that it arrived through a bridge and not from any of the wallets in this cluster. We cannot see who any of these people are. And the Cronos half of the trail no longer exists to be checked, which is why we are publishing the figures we took from it while it did.
The record. Every address and transaction behind the findings above. The two Cronos transactions were discarded in the rewind and no longer resolve on the chain; they are listed as they stood.
| Drain transaction | 0xddc9dc47d330116332ae687ba939f6d6196c4cc5950b2cdb04ae826520eeca20 |
| Setup transaction | 0x0fce5ae8d2eeb82c838e750d0e25af1564a2c7d05bf843dd1cfea102ce587d06 |
| Operator wallet | 0x4266a0e6a0f0ef90abcff3bb089932ca0cce3652 |
| The vault | 0x085f3115ca368aa262246d22f9476e1e2c87e8be |
| Orchestrator | 0xd3aac8a1a9e412e2c590463a8b6f90125e23f1f3 |
| Borrower | 0x2dc6a36f4e5eeefe112c01569de96dea496bb618 |
| Liquidity position | 0x7d4e7e5dcb0ccc66b4f0f8b0f30da5078ad4f2dc |
| Second stablecoin wallet | 0x215adfc84332d8dfdd5afc77af69cceec0bcd3fc |
| Exit hub, both chains | 0xfdb11781ee3818135eebd2acd2247c263e266652 |
| Relay hop, both chains | 0x86616ce5d1829beb030742e65bd3c1fbee8f082e |
| Side pocket, both chains | 0x9ea6b75940de7c57bd1827001536e33ed667b55d |
| Ethereum destination | 0xc404160b79bd8905061a1caecbeca2eeab3f72dd |
Run these queries yourself
Every figure here comes from Bitquery's on-chain index, which you can query directly. The Bitquery MCP server exposes the same data to any AI client, and the transfer and trade docs carry worked examples for the chains used here. Balances in every balance here was cross-checked against Cronos archive state before publication.
More money traced across chains: seven years of Tornado Cash, a $110 million laundering circuit on Tron, and the 1,319 people who lost money to copied addresses.