What is address poisoning, and how do I check a USDC recipient before I send?
Address poisoning is when someone slips a lookalike of an address you already use into your transfer history—often with a zero-value or dust USDC transfer—so you (or your wallet UI) copy the wrong one later. Kertivo Shield checks the recipient against your recent Base USDC history and optional contacts before you send ($0.001 via POST /address/check), and you can see the same answer shape for free at POST https://kertivo.com/demo/address.
Who this is for
- Agents and bots that pay Base USDC and need a pre-send lookalike check, not a post-settlement autopsy.
- Builders wiring an address book or "known_addresses" list into a pay flow.
- Anyone who has seen a 0 USDC "transfer" from or to an address that almost matches a contact.
How address poisoning works (evidence)
Wallets often show only the first and last few characters of an address. Attackers create a different address that shares those characters, then push a zero-value or dust Base USDC transfer so it appears in your history next to a real contact. When you paste from history, you may paste the lookalike.
Kertivo Shield matches lookalikes the same way: same first 4 and last 4 hex characters after 0x, and a different full address (lookalike in src/check.ts). Inbound transfers under $0.01 (including zero) count as dust. On your own side only a zero-value transfer counts, because that is the one an attacker can fake "from" you; any non-zero USDC you really sent, even a $0.001 x402 micropayment, counts as having paid that address before.
On a dated public sample, the address-poisoning benchmark ran POST /address/check on 20 fresh live Base USDC poisoning pairs: all 20 poisoned recipients came back risk: high; none of the 20 genuine counterparts did. The page also documents limits (partial RPC coverage on the cheap tier, small sample size). Poisoning itself is constant on Base: in the benchmark's 600-block sample (about 20 minutes), 3,979 zero-value USDC transfers hit 3,528 different wallets. The 20 genuine addresses all came back medium, because the sender had paid them before but a lookalike was also present.
How Kertivo Shield answers it
Send POST https://kertivo.com/address/check with one of three shapes:
| Shape | Body | What it scans |
|---|---|---|
| History | {from, to, contacts?} | Sender's recent Base USDC transfers for lookalikes and dust/zero-value patterns (honest partial coverage on free RPCs). |
| Contacts-only | {to, contacts} / {recipient, known_addresses} (no from) | Offline lookalike vs your address book only. No RPC. coverage.source is contacts_only. |
| Recipient-only | {address} / {to} alone | That address's own recent USDC history for poisoning fingerprints (coverage.mode recipient_only). |
Aliases such as sender/recipient/known_addresses/known are accepted. Optional chain (base, 8453, or eip155:8453) and token=USDC only. You are only charged when Shield answers with HTTP 200; any other chain or token returns a 400 (unsupported_chain or unsupported_token), which never settles.
The answer includes:
risk:low\|medium\|highseenBefore: whether you have really paidtoin the scanned window (history mode)lookalikes: counterparties that match the first/last-4 rule, with dust counts and a sample tx when foundreasons: plain-language whycontacts: when you sent an address book—inContacts, contact lookalikes with prefix/suffix match lengthscoverage: window,coveragePct,complete,lowCoverage(when almost nothing was scanned, a low risk is not a safety signal)
Rough risk rules:
- History (
from+to):toappears in your history only through dust or zero-value transfers → high; lookalikes present and you have never really paidto→ high; lookalikes present but you have paidto→ medium. - Contacts (with or without
from):tolooks like a contact but is not in your book → high;tois in your book but other contacts look like it → medium. - Recipient-only (
toalone): the address received 0 USDC "transfers" and later got paid real USDC → high (paid_after_zero_value); it only ever received zero-value transfers → high (zero_value_only); zero-value transfers plus real activity → medium; only sub-cent outbound moves → medium; no USDC activity at all in the window → medium (no_activity), since a brand-new address has nothing vouching for it.
Full-history tier: POST /address/check/full ($0.005) uses the same risk logic against the sender's fuller transfer history from one indexer page (up to 500 transfers). It needs from, so there is no contacts-only or recipient-only shape there, and it returns 503 without charging you if the index is down.
Real free demo on 2026-10-15: POST /demo/address returned risk: high, coverage.source: contacts_only, and a reason that the fixture to looks like contact 0x509e…9ede (same first and last characters) but is a different address. Body is ignored; price charged is 0.
Try it
- Free, no wallet:
curl -s -X POST https://kertivo.com/demo/address— fixed contacts-only lookalike fixture, same shape as paid Shield. - Paid, any pair: call
POST /address/checkunpaid for the 402, then retry with the payment header. Copy-paste shapes are at /examples. - Dated evidence: browse /benchmarks/address-poisoning for the 20-pair rerun, tx links, and limitations.
- Every 200 JSON (including
/demo/address) carries a signedattestationyou can verify at /.well-known/attestation.
A wrong chain or a token other than USDC returns a 400 and is not charged.
FAQ
What counts as a lookalike?
Same first 4 and last 4 hex characters after 0x, but a different full address. That mirrors what truncated wallet UIs show.
I only have an address book, not a sender. Can I still check?
Yes. Send {recipient, known_addresses} (or {to, contacts}) with no from. That is contacts-only: no history scan, coverage.source contacts_only.
The demo always says high. Is that a bug?
No. The free demo always uses a fixed fabricated lookalike of our payTo as the recipient, with payTo as the only contact, so the honest answer is high.
Does a low risk mean the address is safe?
No. Low means no lookalike/dust fingerprint in what was scanned. Check coverage.complete and coverage.lowCoverage. If coverage is thin, retry, pass contacts, or use /address/check/full (it needs your from address).
Does Shield check other chains or tokens?
Not today. Base mainnet and native USDC only. A wrong chain or token returns a 400 and is not charged.
Limits
- Base mainnet and native USDC only.
- Does not check sanctions lists, off-chain scams, phishing sites, or "did you mean this other address."
- Cheap
/address/checkuses a recent block window on public RPCs; coverage is often partial. Older poisonings can be missed. - Contacts-only never sees dust in your history unless you also pass
from. - A recipient you already paid real USDC to can come back medium (not high) even if a lookalike is present—pass contacts to catch the lookalike case.
- Kertivo holds no funds and does not stop a send for you. It reports evidence.
