Spoofed Deposit Addresses: Attacking the Tracing Heuristic Itself

Spoofed deposit addresses: attacking the tracing heuristic itself

This is the write-up promised in our recent note to investigators. While testing our Hydra tracing engine against publicly reported exploits, we observed a laundering behaviour that does not try to outrun tracing software. It targets an assumption inside the software — one that almost every tracing engine, ours included, has relied on.

The short version: attackers are skipping the exchange deposit address and paying a hot wallet directly, because doing so causes tracing engines to label the attacker's own wallet as exchange infrastructure and stop. The trace ends early, and it ends with a false attribution attached to a named exchange.

Before that, the patterns you already know — because the new one is only interesting in contrast to them.

The established playbook

Four of these are well documented. They are worth restating precisely, because each defeats a different part of an investigation.

  • Fragmentation. Funds are split across hundreds to thousands of addresses to inflate the search space. This does not hide anything on its own; it makes exhaustive review expensive enough that an investigator gives up or samples, and sampling is where trails get lost.
  • Token poisoning. Attackers deploy synthetic ERC-20 contracts reusing the name and ticker of a major asset — USDT, USDC, ETH, BNB — and spray worthless transfers through the graph. To an engine that reads token metadata at face value, these read as legitimate flow, and the noise is indistinguishable from signal unless assets are judged by contract address rather than by name.
  • Bridges. Cross-chain hops remain core to the arsenal. They break continuity for any engine that cannot reconcile a departure on one chain with an arrival on another, and an unresolved bridge hop is a trail that simply stops.
  • Mule exchange accounts. A trace terminates at an exchange account registered to a real person who has no idea what it is being used for — they were paid to open it. The trace is technically correct and forensically useless: the identity behind the account is not the one you are looking for.
  • Mixers. Still the hardest break in any trace. We have separate work underway aimed at raising the share of mixer-involved cases that reach a resolution rather than stopping at the deposit.

Every one of those attacks the data. The behaviour below attacks the method.

How a genuine exchange deposit works

When you deposit to an exchange, you are not sending funds to an account you control. The exchange issues you an address it controls, unique to you. You send to it, and the exchange later sweeps the balance into one of its hot wallets and credits your account internally.

That sweep leaves a distinctive fingerprint on chain:

  • The deposit address receives from one party — you — and forwards essentially everything onward.
  • It forwards to an address that is already known to be that exchange's hot wallet.
  • It empties itself. Deposit addresses do not hold balances; they are conduits.
  • The sweep is initiated by the exchange's own infrastructure, on the exchange's schedule, and it is common for the exchange to fund the gas for that sweep rather than the depositor.

Because that pattern is so consistent, tracing engines learned to recognise it, and the recognition became a rule: an address that forwards its funds into a known exchange hot wallet is a deposit address belonging to that exchange.

Why the rule exists, and why stopping there is correct

The rule is not laziness. Once funds reach an exchange deposit address they are in that exchange's custody. What the exchange does with them next — sweeping to a hot wallet, moving between its own wallets, paying out to some unrelated customer — is the exchange's own money moving, not your subject's. A trail drawn onward through custody asserts a movement of the subject's funds that the data does not support.

So a correct engine stops at a deposit address, records it, and reports that the funds entered that exchange. That is the finding, and it is an actionable one: the deposit address is exactly what an exchange's compliance desk needs in order to identify the account holder. Stopping is right. The label is what has to be right.

The spoof

The behaviour we are flagging inverts the rule. After obfuscating across multiple hops, the attacker sends directly from their own wallet into the exchange's hot wallet, skipping the deposit address entirely.

Nothing about that transfer is unusual on chain. Hot wallets receive from all sorts of addresses. But run it through the heuristic and look at what the engine concludes:

attacker wallet --(single transfer)--> known exchange hot wallet

engine reasoning:
  1. this address forwarded into a known hot wallet
  2. therefore it is that exchange's deposit address
  3. deposit addresses are custody boundaries
  4. therefore stop, and report the funds as inside the exchange

Three things are now wrong at once, and they compound:

  • The trace ends early. The attacker's wallet is treated as a terminal node. Anything that wallet did afterwards — other outputs, other chains, the actual cash-out — is never examined.
  • The attribution is false. The engine has recorded an attacker-controlled address as infrastructure belonging to a named exchange. That is not a gap in the evidence; it is an affirmative false statement about a third party, and it is the kind of claim that ends up in a report someone relies on.
  • The failure is invisible. A branch that stops at a deposit address looks exactly like a completed trace. There is no error, no warning, nothing anomalous to notice. The investigation appears to have succeeded.

That last point is what makes this worth writing about. Most tracing failures announce themselves — a bridge that will not resolve, a chain with no data, a hop that goes nowhere. This one produces a clean, confident, wrong answer.

How much evidence does the mislabel actually require?

Less than you would hope, and this is the part worth checking in whatever engine you use.

The single-forward pattern — every outgoing transfer from an address went to one exchange — is the strongest form of the signal, and it is what the heuristic is built to catch. But an address that has made exactly one outgoing transfer, ever, and sent it to a hot wallet, satisfies that condition perfectly. One transfer is enough to look like a textbook deposit address.

An attacker arriving at the end of an obfuscation chain and making a single transfer into an exchange is therefore not an edge case for this heuristic. It is the ideal input.

We found this in our own engine while testing against publicly reported exploits, which is why we are describing the mechanism rather than pointing at anyone else's product. If your tooling implements this heuristic — and if it labels deposit addresses automatically, it almost certainly does — it is worth establishing how many outgoing transfers it requires before it will call an address a deposit address, and what it does when that number is one.

What separates a genuine sweep from a spoof

The two look identical if you only consider the single edge into the hot wallet. They stop looking identical as soon as you consider the address's history and the economics of the transfer. Signals we consider useful, in rough order of strength:

  • Who paid for the transfer. A genuine sweep is executed by the exchange, and on many designs the exchange funds the gas for it. An attacker sending their own funds pays their own gas. Gas provenance is a question about who controls the address, and it is answerable from chain data.
  • What the address did before. A real deposit address is typically fresh and narrow: created for one customer, receiving from one counterparty, then emptied. An attacker's wallet arrives carrying history — multiple inbound hops, often a bridge crossing or a swap immediately prior. A deposit address with a laundering chain behind it is a contradiction in terms.
  • Inbound diversity. Deposit addresses generally receive from the one customer they were issued to. An address funded by many unrelated counterparties and then forwarding to an exchange is not behaving like an exchange-issued address.
  • Whether the address empties and stays empty. Conduits sweep to zero and are reused or abandoned. Retained balances, or later activity unrelated to the exchange, are inconsistent with an address the exchange controls.
  • Whether the brands agree. An address inferred to be one exchange's deposit address that pays a different exchange's hot wallet is either mislabelled or multi-use. Either way it should not be treated as settled custody.

None of these is individually conclusive, and we would be sceptical of anyone claiming a single clean test. Taken together they separate the cases well, and — this matters more than the individual signals — they let an engine express uncertainty instead of silently choosing one of two opposite conclusions.

The underlying discipline: an inference is not a fact

Step back from the specific attack and the general lesson is about provenance.

"This address is Binance's deposit address" can be two very different statements. It can be a curated fact from an authoritative source. Or it can be something the tracing engine worked out for itself from a forwarding pattern, which is a guess — often a good one, and still a guess.

An engine that stores both in the same field, with no record of which is which, will eventually present its own inference back to itself as evidence. That is exactly the surface this attack exploits: it does not need to defeat a database of known exchange addresses, it only needs to trigger an inference and let the engine trust itself.

Our position is that a label's source is part of the label, that an inference must never be presented as an authoritative statement of what an address is, and that a heuristic conclusion strong enough to end a trace must be strong enough to survive being asked how it was reached. This is a design principle we apply across the platform's address labelling, not something specific to deposit detection.

What this means for your casework

If you are working exploit proceeds, three practical implications:

  • Treat a trace that terminates at a deposit address as a claim to verify, not a conclusion. Ask what evidence produced the deposit label. If the answer is "it sent funds to a hot wallet once", you have not necessarily found an exchange deposit — you may have found the subject's own wallet.
  • A terminal exchange finding is exactly where a subpoena or compliance request goes. Sending one naming an attacker-controlled address as an exchange's deposit address wastes the request and the relationship, and the exchange will tell you the address is not theirs.
  • Check the hop before the boundary. If the address immediately preceding the exchange arrived via a bridge, a swap, or a long chain of hops, that is not the shape of a customer making a deposit.

Where we are

We are tuning Hydra to separate genuine sweeps from spoofed deposits, working from the signals above rather than from the single forwarding edge. We would rather an engine say "this looks like a deposit address but the evidence is one transfer and the address has laundering history behind it" than quietly close the branch. A tracing engine that cannot express uncertainty will express false confidence instead, and in this line of work false confidence is the more expensive failure.

We are publishing the mechanism rather than sitting on it because the heuristic is close to universal, the attack requires no sophistication, and an investigator who knows to check the deposit label can catch it manually today.

FAQ: spoofed deposit addresses

How do I tell a genuine exchange deposit address from a spoofed one?

Look past the single edge into the hot wallet and examine the address's history. A genuine deposit address is typically fresh, receives from one counterparty, empties itself, and is swept on the exchange's schedule — often with the exchange funding the gas. An attacker's wallet arrives carrying history: multiple inbound hops, frequently a bridge crossing or swap immediately before, and it pays its own gas. No single test is conclusive, but a deposit address with a laundering chain behind it is a contradiction in terms.

Why do tracing engines stop at deposit addresses at all?

Because funds that reach one are in that exchange's custody. What the exchange does next — sweeping to a hot wallet, moving between its own wallets, paying an unrelated customer — is the exchange's money moving, not your subject's. Drawing the trail onward would assert a movement of the subject's funds that the data does not support. Stopping is correct; the label is what has to be right.

Does this mean past traces that ended at an exchange are wrong?

Not necessarily, and most are not. The question to ask of any trace terminating at a deposit address is what evidence produced that label. If the address was identified as a deposit address on the strength of a single outgoing transfer to a hot wallet, and it has a multi-hop history behind it, the finding is worth re-examining. A deposit address that has swept repeatedly over time and receives from one party is behaving exactly as it should.

What should I do if a trace ends at a deposit address?

Treat it as a claim to verify rather than a conclusion. Check the hop immediately before the boundary — if the funds arrived there via a bridge, a swap, or a long chain of hops, that is not the shape of a customer making a deposit. This matters before sending a subpoena or compliance request: naming an attacker-controlled address as an exchange's deposit address wastes the request, and the exchange will tell you the address is not theirs.

Can an exchange confirm whether an address is really theirs?

Yes, and it is the definitive check. An exchange's compliance desk can say whether an address is one of its deposit addresses. If you have cases where an exchange confirmed an address attributed to them was not theirs, those are precisely the examples we would like to compare notes on.

If you have seen the same behaviour in your own casework — particularly if you have examples where an exchange confirmed an address was not theirs — we would like to compare notes.