A Special Demixing Case

A note before we start: the case as a whole was handled by the entire Token Recovery team, and this demixing work in particular was done together with Benjamin Brooks. That’s why I say “we” throughout, the credit is shared.
Thousands of bitcoins walked out of a virtual asset service provider years ago. The wallets went quiet for a long time. When they woke up, the money didn’t go to another exchange. It went into a mixer.
A mixer is the one tool built specifically to beat people like us. Here is how we beat it back, in plain terms.
A mixer is a black box for coins. You put Bitcoin in. Later, someone takes Bitcoin out. But what goes in and what comes out are deliberately disconnected: equal-sized chunks, shuffled together, no on-chain line you can draw from “money in” to “money out.” Everyone’s coins sit in one shared pool, and when a withdrawal happens the blockchain will not tell you whose deposit paid for it.
So the obvious approach fails. We could see the stolen coins enter the mixer. Then the thread was cut. Thousands of withdrawals left the pool over the same period, and every one of them looked exactly like the next. No labels. No origin. Nothing that said “this one is the thief’s.”
This is the wall. The point where most reports write “funds entered a mixer, trail lost” and close the file.
But the attacker had one weakness they could not hide: the sheer scale of their deposits. They had pushed so much money through such a small mixer that, as we will see, that volume is the only reason any of this worked.
We did not have a single withdrawal we could prove belonged to the attacker. So we stopped trying to follow the coins, and we asked a different question.
Not “which coins are theirs?” but “how much of the pool has to be theirs?”
Here is the key. A mixer can hide which coins belong to whom. It cannot break arithmetic. At any moment, the total sitting inside the mixer is just two things added together: our Threat Actor money, and everybody else’s money. There is no third pile.
Threat Actor balance + everyone else’s balance = total balance. Always.
And neither of those two balances can ever fall below zero. You cannot withdraw money that is not there.
That last sentence is the crack in the wall.
So we reconstructed the mixer’s total balance and sorted all of its activity into three buckets: deposits we could tie to the Threat Actor, deposits we could tie to everyone else, and withdrawals, which the mixer had scrambled on purpose so that no withdrawal could be traced back to whose deposit it came from.
With everything broken down this way, we pushed the numbers to their two extremes.
Extreme one: assume every unattributed withdrawal was the Threat Actor. This drives their balance as low as it can possibly go. Sometimes it gets driven all the way to zero, and the instant it does, the next withdrawal cannot be theirs, there is nothing left in their pile to take. That extra withdrawal has to belong to someone else.
Extreme two: assume the opposite, that every unattributed withdrawal was everyone else’s. This drains the other pile to its minimum instead. When that one hits zero, the leftover withdrawals can’t belong to anyone else. They must be the Threat Actor.
That forced leftover is the overflow: the amount the mixer was mathematically compelled to allocate to one side or the other within the now identified narrow time window. Not a guess, not a probability, a certainty squeezed out of the simple fact that a balance can’t go negative.
The mixer’s whole promise was you can’t separate your coins from the crowd’s. True. We didn’t separate the coins. We separated the math.
Now the part that actually matters: how do we know it’s right?
The overflow told us that the attacker withdrew inside a specific window. It did not tell us which withdrawals were theirs. So we settled it by elimination.
Working from the blockchain data itself, and using Caudena’s aggregation of clusters, we took a sample of the withdrawals from that window and followed each one to the wallet cluster it ended up in.
Caudena let us easily see the deposit clusters ranked by volume and group the withdrawals into their own clusters. Then we listed the biggest players sending money into the mixer and pulling money out of it. For each one, we simply counted how much they were moving. That told us who the heavy hitters were.
One withdrawals cluster towered over everyone else. The rest were all much smaller.
Our Threat Actor was, by a wide margin, the one moving the most.
And that is the whole reason this worked. The attacker was the mixer’s biggest depositor by far, pushing through more money than such a small service could ever hide. We checked every other player, right down to the second-biggest, and none of them came anywhere close to that volume found in the withdrawal cluster. Once they were all ruled out, only one wallet cluster was left that could explain the money: our Threat Actor.
From that anchor, everything downstream came loose.
The mixer was built so that no single withdrawal could ever be pinned to the thief.
It never had to be. The balance sheet pinned them for us.
Next: Inside Inferno Drainer
Also published on LinkedIn.