What we saw

Across a rolling window of finalized blocks, a single deployer (0x…redacted) produced dozens of small contracts in tight bursts — more than fifty in a two-hour span. Individually they look unremarkable. In aggregate, the deployment cadence, funding path and bytecode shape line up into a recognisable drainer family: contracts built to convert a victim approval into a transfer the moment it lands.

The dataset alone doesn't sell. The signal is: “this pattern is approaching your users” — early, with evidence, before funds move.

How we cluster them

We don't rely on a single fingerprint. Each newly deployed contract is reduced to a set of features and compared against what we already track:

When a fresh contract is 90%+ similar to a known family and shares a funder with prior members, it inherits the family label with a confidence score and a short reason string.

family:      approval-pull / "burst minter"
members:     53 (last 2h)
deployer:    0x…redacted
funder:      0x…redacted (also funded 3 prior families)
selectors:   approve, permit, transferFrom, multicall
similarity:  0.94 vs family centroid
first calls: victims approve ERC-20 spend within <10 blocks

Why it matters to a client

You don't need every drainer on every chain. You need the ones aiming at your token, users and brand. The same clustering runs against a customer profile: if a family starts requesting approvals for your token, or a fake contract uses your name and symbol, that's a targeted alert — not a global firehose.

What a team should do

  1. Watch approvals to spenders that aren't on your known-good list.
  2. Warn users off any “claim / migration” flow you didn't publish.
  3. Keep a revoke path handy; treat unbounded approvals as the default risk.
  4. Track the deployer and funder — families reappear under fresh addresses.

A note on language

Everything here is scored, not asserted. We say “similar to a known drainer family” and “high-risk approval pattern,” and we show the evidence. Attribution from timing and shape alone is probabilistic — we flag it that way.