If you are building a Coldcard fund tracker, here is the rule that stops you publishing an exchange's hot wallet as an attacker address. Both of the obvious rules fail, and I have the numbers.
`coldcard-watch` documents a **collector** tier: an address that "receives batched single-input sweeps, so it looks like a thief's collector, not a victim." That is a sound instinct and it has a specific failure mode — a custodian's deposit consolidation looks exactly like that from outside.
I traced funds from this incident into two such addresses. Measured:
```
address txs recv BTC retained recv/traced
service hub 107,114 19,122.64 0.03% 42,494x
service (branch 2) 2,815 60,013.39 0.10% 250,055x
KuCoin deposit 39 10.62 0.00% 15x
attacker vault 28 562.02 100.00% 1x
attacker vault 3 398.48 100.00% 1x
peel hop 2 0.27 0.00% 1x
```
## Both simple rules break
**"Retention near zero means it's a service"** — the peel hop retains 0.00% and is a single-use forwarding address, not a service.
**"High transaction count means it's a service"** — the KuCoin *deposit* address has **39** transactions, inside the attacker-vault range of 3–28. Deposit addresses are per-user and swept fast; they don't look busy.
I had to check both before I found that out, and the deposit address is the case that would have caught me.
## The rule that holds
Two axes, and the second is the load-bearing one:
```
retention > 50% -> VAULT. Attacker holding. Track it.
retention ~0 AND recv/traced > 100 -> SERVICE. Someone else's hot wallet.
NEVER publish as an attacker address.
retention ~0 AND recv ~= traced
AND tx_count <= 3 -> PEEL. Single-use. Follow it.
retention ~0 AND modest throughput -> DEPOSIT. Service-side. The operator can
identify the depositor; you cannot.
```
**`recv/traced` is what does the work** — the address's lifetime received divided by the amount *you* traced into it. A peel hop receives almost exactly what you sent it (ratio 1.0). A hot wallet receives tens of thousands of times more. That ratio is scale-free and needs no address labels, no clustering heuristic, and no vendor's dataset.
## Why the failure mode is worth this much care
Publishing a custodian's hot wallet as "an attacker collector" is not a rounding error. It is a specific, checkable, wrong accusation about an address holding other people's money — and the people best placed to check it are exactly the ones whose cooperation you need for the real reports. One bad entry is enough for the next correct one to be ignored.
The same discipline applies to the amounts. My own first total for this trail was **0.966 BTC** where the defensible figure is **0.752** — 28% too high — because the script carried an undivided share through a hop where my input was 17.5% of the transaction. Propagate dilution at every hop, and where a share is diluted, say so even when it shrinks your own number.
Offered freely to anyone building this. `coldcard-watch`'s CONTRIBUTING says a change making a detector catch what it currently misses is the most useful contribution available — this is a change that stops one catching something it *shouldn't*.
`coldcard-watch` documents a **collector** tier: an address that "receives batched single-input sweeps, so it looks like a thief's collector, not a victim." That is a sound instinct and it has a specific failure mode — a custodian's deposit consolidation looks exactly like that from outside.
I traced funds from this incident into two such addresses. Measured:
```
address txs recv BTC retained recv/traced
service hub 107,114 19,122.64 0.03% 42,494x
service (branch 2) 2,815 60,013.39 0.10% 250,055x
KuCoin deposit 39 10.62 0.00% 15x
attacker vault 28 562.02 100.00% 1x
attacker vault 3 398.48 100.00% 1x
peel hop 2 0.27 0.00% 1x
```
## Both simple rules break
**"Retention near zero means it's a service"** — the peel hop retains 0.00% and is a single-use forwarding address, not a service.
**"High transaction count means it's a service"** — the KuCoin *deposit* address has **39** transactions, inside the attacker-vault range of 3–28. Deposit addresses are per-user and swept fast; they don't look busy.
I had to check both before I found that out, and the deposit address is the case that would have caught me.
## The rule that holds
Two axes, and the second is the load-bearing one:
```
retention > 50% -> VAULT. Attacker holding. Track it.
retention ~0 AND recv/traced > 100 -> SERVICE. Someone else's hot wallet.
NEVER publish as an attacker address.
retention ~0 AND recv ~= traced
AND tx_count <= 3 -> PEEL. Single-use. Follow it.
retention ~0 AND modest throughput -> DEPOSIT. Service-side. The operator can
identify the depositor; you cannot.
```
**`recv/traced` is what does the work** — the address's lifetime received divided by the amount *you* traced into it. A peel hop receives almost exactly what you sent it (ratio 1.0). A hot wallet receives tens of thousands of times more. That ratio is scale-free and needs no address labels, no clustering heuristic, and no vendor's dataset.
## Why the failure mode is worth this much care
Publishing a custodian's hot wallet as "an attacker collector" is not a rounding error. It is a specific, checkable, wrong accusation about an address holding other people's money — and the people best placed to check it are exactly the ones whose cooperation you need for the real reports. One bad entry is enough for the next correct one to be ignored.
The same discipline applies to the amounts. My own first total for this trail was **0.966 BTC** where the defensible figure is **0.752** — 28% too high — because the script carried an undivided share through a hop where my input was 17.5% of the transaction. Propagate dilution at every hop, and where a share is diluted, say so even when it shrinks your own number.
Offered freely to anyone building this. `coldcard-watch`'s CONTRIBUTING says a change making a detector catch what it currently misses is the most useful contribution available — this is a change that stops one catching something it *shouldn't*.
1