The TradeWiz attacker was a customer first
A copy-trading bot lost control of thousands of its users' wallets in one afternoon. The trail on the chain runs back a month before the theft, and it ends at two exchanges that keep records on their customers.
- 27
- $459K
- 73%
- 63¢
- 94%
- 39 sec
01 · AugustA quarter of a SOL from MEXC
On the morning of August 28, a new Solana wallet got its first money: a quarter of a SOL, about $31, withdrawn from MEXC, a crypto exchange. It passed the money to a second wallet 16 minutes later.
Within 6 hours the second wallet was buying memecoins through TradeWiz, a copy-trading bot, and paying TradeWiz a fee on every trade. Over the next week the pair did it three more times. About 1 SOL went in. 27 trades came out.
Then both wallets went quiet for more than three weeks.
On September 30 the first wallet came back. This time money poured into it from more than 20,000 drained TradeWiz wallets. TradeWiz is a trading bot that holds its users' private keys, and it says some of those keys leaked. Bitquery indexes every transfer on Solana, so we took the wallet that collected the money and read its whole history, from that first withdrawal to the cash-outs after the theft. We counted what was taken, timed the drain against TradeWiz's response, and followed the money to where it sits today. We do not know who the attacker is or how the keys got out. Two exchanges are in a position to answer the first question. Only TradeWiz can answer the second.
02 · The botA wallet you don't hold the key to
TradeWiz is a trading bot for Solana memecoins. You pick wallets to copy, and when they buy, the bot buys for you seconds later. It runs on Telegram and as an app, and it sells several products. One is called SOL PVP.
Speed is the product, and it has a cost. To trade without asking you each time, the bot has to hold the wallet's private key. Users can ask for a copy through a feature called key export. TradeWiz's own FAQ tells them not to: "By not exporting your private keys, we can ensure 100% security of your assets."
On Solana the private key is the wallet. There is no password reset and no fraud desk. Whoever holds the key can move everything in it, and the chain cannot tell one signer from another. It has happened to a bot before. On September 7, one address emptied 2,442 dormant Ethereum wallets, half of them customers of LootBot, a Telegram bot that kept its users' keys.
On September 30, TradeWiz posted that "a limited private key exposure occurred in the SOL PVP private key export feature." It promised to compensate users in full and told them to stop using their SOL PVP wallets. It has not said how many keys got out, or how.
| Posted | What TradeWiz said |
|---|---|
| Sept. 30, 14:41 | Security notice: a "limited private key exposure" in the "SOL PVP private key export feature". Full compensation promised. |
| Sept. 30, 18:08 | Refunds: "First Wave of Refunds Has Been Sent." |
| Oct. 1, 07:34 | Police: reported to the police, who have "contacted the relevant exchanges that received the stolen funds". |
03 · The customerThe attacker's own bot wallet
Start with the wallet where the stolen money landed. We call it the collector. Before the theft it had received money only four times, each time from a MEXC hot wallet, the address an exchange pays withdrawals from. That wallet is in our address labels and in MEXC's proof of reserves, the list of wallets the exchange publishes as its own.
| Withdrawn from MEXC | SOL | Passed to the trading wallet after |
|---|---|---|
| Aug. 28, 07:26 | 0.2624 | 16 minutes |
| Aug. 28, 13:44 | 0.2012 | 17 hours |
| Aug. 29, 07:28 | 0.2685 | 8 seconds |
| Sept. 3, 13:10 | 0.2735 | 50 seconds |
| Total | 1.0056 |
Every withdrawal went on to one address, which we call the trading wallet. Three moved within 16 minutes. One sat overnight.
The trading wallet then did what TradeWiz customers do. It made 27 trades in memecoins. Each of those trades carries two signatures, the wallet's own and a second one, as other TradeWiz trades do. Each one also pays a small fee to the same wallet, the one TradeWiz trades pay their fee to.
How do we know that fee wallet is TradeWiz's? It carries no public label, so we tested it. Since August last year, more than 35,000 wallets have paid it or the fee wallet it replaced. About one in six of them was drained. Among wallets that paid another busy trading address, about one in 400 was. And on the day of the drain the payments to the fee wallet stopped. None has arrived since that evening.
The trading wallet was small, with about 1 SOL going through it in all. It also signed 16 transactions with no bot signature, which suggests its owner also used the key outside TradeWiz. TradeWiz lets users import a wallet or export its key, and we can't tell which happened here.
What the chain does show is the order. A month before it collected from the drained wallets, the collector paid for a TradeWiz wallet of its own.
04 · The testEighteen wallets in five minutes
The trading stopped on September 4. Nothing happened for 24 days.
On the evening of September 28, money began to arrive in the collector from addresses it had never dealt with. A wallet was emptied every 2 or 3 seconds, and after a short pause a few more followed. Nobody signs that fast by hand. A script was doing it. Each transfer was signed by the wallet being emptied and by nobody else. That is what a stolen key looks like on-chain. There is no exploit and no token approval to find, only a normal transfer that the owner did not make.
The haul was 34 SOL, about $4,100. By the next morning all of it had gone out by four routes into the hub wallet of a service we could not identify, one that gave each of these payments its own deposit address.
Then the attacker stopped again. For almost two days TradeWiz ran as normal, and its fee wallet took about 20,000 payments per day.
05 · The drainTwo and a half hours
The main sweep started early in the afternoon of September 30 and ran for two and a half hours. At its peak the script emptied 307 wallets in a minute.
The wallets were not taken at random. The sweep came in four runs, and each run opened on the richest wallets it had. The first took its four richest in the opening second. The biggest of all, with 232 SOL, was not touched until the fourth run opened, 95 minutes in.
| Run | Wallets | SOL | Biggest |
|---|---|---|---|
| 13:25-13:59 | 3,866 | 867.3 | 55.8 |
| 13:59-14:08 | 1,088 | 75.1 | 20.0 |
| 14:09-14:59 | 3,901 | 629.7 | 45.4 |
| 15:00-15:52 | 11,921 | 1,916.5 | 231.7 |
| All four | 20,776 | 3,488.6 |
We can't say why it came in runs. The keys may have reached the attacker in batches, or the attacker may have worked through one list in pieces. Either way, by the time it stopped the script had been through more than 20,000 of them.
06 · The responseThe bot went quiet. The drain kept going.
Trades stopped paying TradeWiz's fee wallet 41 minutes into the sweep. Until then it had been taking dozens of payments every 5 minutes. After that, apart from a brief burst that evening, it took none. Users who kept trading moved to other tools.
TradeWiz posted its security notice 35 minutes after that. The sweep had more than an hour left to run.
Neither step could slow it down. Whether TradeWiz switched the product off or its users simply stopped, the trades ended and the sweep carried on. Switching a bot off stops the bot from signing. It does nothing about a copy of the key in someone else's hands. When the fee payments stopped, about a quarter of the money was gone. When TradeWiz posted, a little under half. The rest was still sitting where the script had not reached yet. The way to save it was to move it to a wallet with a new key before the script arrived.
07 · The losses63 cents, and 232 SOL
Most of the drained wallets were leftovers. The median one lost 63 cents. Two thirds held less than 0.01 SOL, the dust left behind after a trader has moved on.
The money was in a small group. 69 wallets lost 10 SOL or more, and between them they account for nearly half of everything swept.
The SOL was only the first pass. About an hour later the attacker started a second one, with a fresh gas wallet paying the transaction fees so that addresses already emptied could still sign. It went back through nearly 3,000 wallets and moved out the USDC, the USDT and a few hundred memecoins it found. Then it closed their empty token accounts. A Solana wallet keeps each token in an account of its own, and the chain holds a small deposit, called rent, against every one. Close the account and the rent comes back. The attacker closed nearly 93,000 of them and kept the rent, 189 SOL.
The count that was widely shared that evening was taken while the token accounts were still being closed, so it misses most of the rent. It also includes four senders that were never victims. They were address-poisoning bots, which send dust from look-alike addresses and hope someone copies the wrong one.
| Shared count | Our count | |
|---|---|---|
| Swept wallets | 20,798 | 20,794 |
| SOL swept | 3,523.04 | 3,523.04 |
| Rent, SOL | 24.21 | 189.31 |
| All wallets | 20,838 | 20,933 |
| Total | $438.9K | $459.5K |
Our total, with the whole second pass in, is about $459,000.
| Taken | Amount | USD |
|---|---|---|
| SOL swept | 3,523.29 SOL | $422,795 |
| Rent | 189.31 SOL | $22,718 |
| USDC | 7,373.40 USDC | $7,373 |
| USDT | 1,534.16 USDT | $1,534 |
| Wrapped SOL | 15.59 SOL | $1,871 |
| Other tokens | 3,176.54 CASH | $3,177 |
| Total | $459,468 |
The keys stayed in use. Two drained addresses received new deposits after the sweep. Both were emptied again within 4 seconds. A drained TradeWiz wallet should be treated as burned. Anything sent to it can be taken.
08 · The moneyWhere it is now
Very little of it has gone anywhere. About 94% of the SOL sits in two wallets: the collector, and a second one that was filled while the sweep was still running and has never sent a transaction.
The first real cash-out came on October 1. The collector sent 100 SOL to a wallet we call the forwarder. It stayed there 39 seconds. Then the forwarder passed it to a deposit address at KuCoin, the address an exchange gives one customer to pay into. About a minute later KuCoin swept it into its hot wallet. Another 91 SOL took the same road 3 hours later, and that time the forwarder waited 51 minutes.
The forwarder is not new either. Its money trail starts in June. Since then it has taken stablecoin payments from 26 senders, about $36,000 in all, and passed them to deposit addresses at KuCoin, MEXC and Bitget. It is in no hurry with those. Its usual wait is about 6 hours.
We don't know who owns it. It could be the attacker's own wallet, or a dealer who buys crypto for cash. But whoever it was had it open when the first of the stolen money arrived.
09 · The trailTwo exchanges hold the records
Stolen crypto usually scatters. When $387 million left Bitget on September 24, it went out across nine blockchains. This trail runs the other way, into exchanges that keep records on their customers.
MEXC knows which account withdrew a quarter of a SOL to the collector in August, and three more times after that. KuCoin knows which account owns the deposit address that took 191 SOL, an address the forwarder has paid into since July.
On October 1 TradeWiz said it had reported the theft to the police, and that they had "contacted the relevant exchanges that received the stolen funds." It also made the attacker an offer: return the assets, and it would consider dropping legal action.
Almost everything in this theft was done with other people's keys. The first step was not. The quarter of a SOL that opened the collector came out of an exchange account, and exchange accounts have owners.
| Wallet | Address | What it did |
|---|---|---|
| Collector | 6mmi…88Hj | Took the MEXC withdrawals in August and the stolen funds in September |
| Trading | 5e92…jfaC | Funded by the collector; 27 trades through TradeWiz |
| Bot fee | Aes3…wJST | Takes the fee on TradeWiz trades; silent since Sept. 30 |
| Gas | 8Fae…HzcY | Paid the fees for the token and rent pass |
| Holding | 7iFX…MHsc | Holds 1,599 SOL, never moved |
| Forwarder | 9Jx1…eKCj | Passed 191 SOL to a KuCoin deposit address |
| KuCoin deposit | Cmjw…oxXs | Sweeps into the KuCoin hot wallet |
| MEXC hot | ASTy…iaJZ | Source of the August withdrawals |
10 · MethodHow we counted
We read every transfer into and out of the collector, then did the same for each address it paid. A wallet counts as drained if it signed its balance away to the collector, or signed off on the later sweep of its tokens and rent. That gives 20,794 wallets that lost SOL, 18 of them in the test run, and 139 more that lost only tokens or rent.
Exchange wallets are named from our own labels and checked against each exchange's published proof of reserves. Dollar figures use $120 per SOL, close to where it traded during the drain. Balances are as of October 1 at 09:54. All times are UTC.
There are limits. TradeWiz has not published a list of affected wallets, so the link between its incident and the ones we counted rests on its own statement, the timing, and the fee-wallet test in section 03. We did not price the 252 token types the attacker has not sold. And we have not identified the service that took the first 34 SOL.
The wallets are public
Every wallet named here is on Solana for anyone to read. You can pull its transfers, follow the SOL that is still parked, and see whether anything has moved since we published.
This article is provided for informational and educational purposes only and reflects analysis of publicly available on-chain data and TradeWiz's public statements as of the times stated. It does not constitute legal, financial, compliance, or investment advice.
Wallets are identified by address only. Nothing here states who controls them. 'The attacker' means whoever signed the transfers that emptied the wallets described, and 'the collector', 'the trading wallet' and 'the forwarder' are our names for addresses, not findings about a person. We do not find that the forwarder belongs to the attacker.
References to TradeWiz, MEXC, KuCoin, Bitget, LootBot and any other party describe on-chain activity or public statements. This article does not find that any of them took part in the theft. An exchange deposit or withdrawal shows that an account exists. It does not show who holds it.
Nothing herein should be relied upon as a definitive determination of fact. Readers should conduct their own independent verification before taking any action. The authors and publisher accept no liability for any loss or damage arising from the use of this article.
Reported by Gaurav Agarwal for Bitquery Research, with AI tools; every figure was checked against the raw data.
Read any Solana address yourself
Bitquery serves every transfer on Solana, for any address or token, with exchange and service labels attached.