Address poisoning: how to spot a lookalike address before you send crypto
Address poisoning plants a lookalike address in your transaction history so you copy it on your next send. Learn the three poisoning patterns, why a test transfer is when the trap gets set, and how to verify the full address. Includes a 2-hour Ethereum mainnet sample and a dependency-free pre-send checker.
Table of Contents
- How do you spot an address-poisoning lookalike before you send?
- The threat model: your history is writable by strangers
- The attack path: three ways the fake gets into your history
- What we observed on mainnet (original sample)
- Why a test transfer is when the trap gets set
- Controls that actually stop it
- Verify before sending: a dependency-free checker
- If you already sent funds to a lookalike
- Sources
- Internal links
- Disclaimer
How do you spot an address-poisoning lookalike before you send?
Never copy a destination address from your transaction history, and never trust an address because its first and last few characters match. Address poisoning works by generating an address that shares the beginning and end of one you recently paid, then making it appear in your history right after your real transfer. Get the destination from a source the attacker cannot write to: a saved address book entry, the recipient's own app or QR code, or a deposit page you open yourself. Then compare the whole address, including the middle.
In a two-hour sample of Ethereum mainnet we took for this article, 2,344 senders of USDT or USDC received a lookalike entry in their history within 100 blocks of a real transfer. The median delay was 22 blocks, about 4.4 minutes.
This guide is for anyone who sends stablecoins or tokens from a self-custody wallet, especially people who send a small "test" amount first and then the rest.
The threat model: your history is writable by strangers
On EVM chains, anyone can create an event that shows up in your wallet's activity list. Your transaction history is not a record of who you chose to deal with. It is a list of every transfer event that mentions your address. Attackers exploit that.
Tsuchiya et al. measured the attack across Ethereum and BNB Smart Chain from July 2022 to June 2024 in Blockchain Address Poisoning (USENIX Security 2025). They found about 270 million poisoning transfers aimed at 17 million victim addresses, and at least 83.8 million USD in losses. The per-attempt success rate on Ethereum was about 0.01%. That rate is low, but the attempts are cheap and automated, so the attack stays profitable.
Attackers generate lookalike addresses by brute-forcing private keys until the address matches the target's first and last hex characters. Each extra matched character multiplies the work by 16. The paper reports most attacker groups matched up to 14 characters in total, with GPU tools making longer matches practical.
The attack path: three ways the fake gets into your history
The paper describes three poisoning methods. All three put a lookalike address next to a real one in your activity list.
| Method | What appears in your history | Why it works |
| ------------------- | ------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| Zero-value transfer | A transfer of 0 tokens from you to the lookalike | On USDT, USDC, and most ERC-20 contracts, transferFrom with amount 0 passes the allowance check, so a stranger can emit a Transfer event naming you as sender. It looks like you paid them before. |
| Tiny transfer | A small real amount from the lookalike to you | The lookalike now appears as a recent counterparty. |
| Counterfeit token | A fake token with a familiar name (for example "USDT") from you or to you | Wallets and explorers may list it next to the real token. The contract is the attacker's, so it can emit any event it likes. |
None of these needs your signature, your approval, or access to your wallet. Revoking approvals and checking signing screens do not stop them. The theft only happens if you later send real funds to the lookalike.
What we observed on mainnet (original sample)
We scanned every Transfer event of the canonical USDT and USDC contracts on Ethereum mainnet for 600 blocks, from block 26,281,983 to 26,282,582 (2026-10-27, 05:35 to 07:35 UTC). We counted a poisoning hit when, within 100 blocks after a real transfer of at least 1 token, one of these appeared:
- a zero-value transfer from the same sender to an address matching the real recipient's first 3+ and last 4+ hex characters, or
- a sub-1-token transfer to the sender from such a lookalike.
The 3-and-4 threshold and the 100-block window follow the detection criteria in the USENIX paper. The scanner uses only eth_blockNumber and eth_getLogs against a public RPC endpoint and has no dependencies.
| Metric | Value |
| ------------------------------------------------- | -------------------------- |
| USDT/USDC Transfer events | 88,512 |
| Transfers of 1 token or more | 61,646 from 21,572 senders |
| Zero-value transfers | 8,910 |
| Poisoning hits | 6,738 |
| Zero-value hits / tiny-transfer hits | 3,320 / 3,418 |
| Senders targeted | 2,344 (10.9% of senders) |
| Share of zero-value transfers that were poisoning | 37.3% |
| Delay after the real transfer (blocks) | min 0, median 22, p90 78 |
| Hits within 5 blocks (about 1 minute) | 551 |
| Matched characters (prefix + suffix) | min 7, median 8, max 13 |
Three pairs from the sample, shortened to 8 characters on each side. The real recipient is first and the lookalike second:
zero-value, 1 block later
real 0x0a2770ff…f4231b77
fake 0x0a272d8f…38f41b77 (prefix 4, suffix 4)
zero-value, 9 blocks later
real 0x28302daa…ccc5b09e
fake 0x2830bf3d…44c5b09e (prefix 4, suffix 6)
zero-value, 7 blocks later
real 0x583e959e…8c907c35
fake 0x583ebf64…5aa97c35 (prefix 4, suffix 4)
How to read this sample:
- It is a two-hour snapshot of two tokens on one chain, not a trend. Counterfeit-token poisoning is not counted, so the real total is higher.
- Hits are a lower bound. Transfers near the start of the range have no preceding real transfer in the data, and poisoning after the last block is not observed.
- A random 7-character match between two specific addresses has a probability of about 1 in 268 million (16⁷), so coincidental matches are negligible at this sample size.
The practical finding is the timing. Poisoning lands minutes after your real transfer, often while you are still about to send the next one.
Why a test transfer is when the trap gets set
Sending a small test amount first is good practice. It confirms the recipient actually receives funds. But the test transfer is also the event that attackers watch for. The usual sequence is:
- You send 10 USDT as a test to the correct address.
- Within minutes, a bot sees the transfer and generates or picks a lookalike of the recipient.
- The bot emits a zero-value transfer from you to the lookalike, or sends you a tiny amount from it.
- The recipient confirms the test arrived. You open your history, copy the "same" address from the top entry, and send the balance.
Step 4 is the mistake. The newest entry with a matching prefix and suffix may be the lookalike. A test transfer protects you only if the main transfer uses the same verified source as the test, not your history.
Controls that actually stop it
Apply these in order. The first two remove most of the risk.
- Use an address book or allowlist for repeat recipients. Save the address once after verifying it through a second channel, then always select it from the address book. Some exchanges and wallets support withdrawal allowlists. Turn them on.
- Take every new address from the recipient's source, not your history. For an exchange deposit, open the deposit page in the exchange app. For a person, ask them to send it again through a different channel and read back characters from the middle.
- Compare the middle, not just the ends. Attackers match the ends. Check a block of characters from the middle of the address, or compare the full string with a tool.
- Hide zero-value and spam transfers in your tools. Etherscan hides zero-value token transfers by default and warns when you copy an address associated with suspicious activity, per its address poisoning guidance. Hiding reduces exposure but does not cover tiny or counterfeit transfers.
- Treat unexpected tiny incoming amounts as a warning sign. A few cents from an unknown address that resembles someone you paid is a poisoning attempt, not a gift. Do not interact with it.
An ENS name helps only if you verify that the name resolves to the expected address. It does not protect you if you later copy the resolved address from history.
Verify before sending: a dependency-free checker
This script compares a destination address against the addresses you trust. It reports an exact match, a lookalike, or an unknown address. Save it as check-address.mjs and run it with Node.js 18 or later.
// Compare a destination address against trusted addresses before sending.
// Usage: node check-address.mjs <destination> <trusted1> [trusted2 ...]
const norm = (a) => {
if (!/^0x[0-9a-fA-F]{40}$/.test(a)) throw new Error(`not an EVM address: ${a}`);
return a.toLowerCase();
};
function edgeMatch(a, b) {
const x = a.slice(2);
const y = b.slice(2);
let prefix = 0;
while (prefix < 40 && x[prefix] === y[prefix]) prefix++;
let suffix = 0;
while (suffix < 40 && x[39 - suffix] === y[39 - suffix]) suffix++;
return { prefix, suffix };
}
const [dest, ...trusted] = process.argv.slice(2).map(norm);
if (!dest || trusted.length === 0) {
console.error('usage: node check-address.mjs <destination> <trusted...>');
process.exit(2);
}
if (trusted.includes(dest)) {
console.log(`OK exact match with a trusted address: ${dest}`);
process.exit(0);
}
let worst = null;
for (const t of trusted) {
const m = edgeMatch(dest, t);
if (m.prefix >= 3 && m.suffix >= 4 && (!worst || m.prefix + m.suffix > worst.score)) {
worst = { t, score: m.prefix + m.suffix, ...m };
}
}
if (worst) {
console.log(`DANGER lookalike of trusted ${worst.t}`);
console.log(
` same first ${worst.prefix} and last ${worst.suffix} hex chars, different middle`
);
process.exit(1);
}
console.log('UNKNOWN not in your trusted list; confirm the full address through a second channel');
process.exit(3);
Output from three runs against one trusted address, 0x1111222233334444555566667777888899990a1b:
$ node check-address.mjs 0x1111222233334444555566667777888899990A1B 0x1111…0a1b
OK exact match with a trusted address: 0x1111222233334444555566667777888899990a1b
(exit 0)
$ node check-address.mjs 0x1111f00dbeefcafe0000123456789abc99990a1b 0x1111…0a1b
DANGER lookalike of trusted 0x1111222233334444555566667777888899990a1b
same first 4 and last 8 hex chars, different middle
(exit 1)
$ node check-address.mjs 0x9999222233334444555566667777888899990000 0x1111…0a1b
UNKNOWN not in your trusted list; confirm the full address through a second channel
(exit 3)
The comparison is case-insensitive on purpose. An EIP-55 checksum confirms that an address was typed correctly, but a lookalike is a valid address with its own valid checksum, so a checksum check does not catch poisoning.
If you already sent funds to a lookalike
On-chain transfers cannot be reversed. Act quickly anyway:
- Record the transaction hash, token, amount, and the lookalike address.
- If the token is a centrally issued stablecoin such as USDT or USDC, contact the issuer and any exchange where the funds may land. The paper documents a case where Tether froze an attacker's address within an hour.
- Report the address to the block explorer so it gets labeled for other users.
- File a report with local law enforcement. Exchanges usually require one before acting.
- Ignore "recovery services" that contact you. Victims of poisoning are frequent targets of a second scam.
Sources
- Blockchain Address Poisoning, Tsuchiya, Dong, Soska, Christin (USENIX Security 2025) and the arXiv version
- Address poisoning attacks are rising on Ethereum (Etherscan Information Center)
- ERC-20 Token Standard (Ethereum Improvement Proposals): "Transfers of 0 values MUST be treated as normal transfers and fire the Transfer event."
- EIP-55: Mixed-case checksum address encoding
Internal links
- Parent hub: Web3 wallet safety: start here
- Related:
Disclaimer
Not financial advice. General security guidance only. The mainnet figures are a short snapshot from one public RPC endpoint and describe observed transfer patterns, not confirmed thefts. Verify wallet and explorer behavior for your own setup before relying on it.
Editor’s picks
- 1Permit2 explained (Web3): why approvals changed and how to use it safely (checklist)
- 2Read wallet signing screens (Web3): a 30-second checklist to avoid permission traps
- 3Spec-to-implementation prompt template (AI development): how to stop the model from guessing
- 4Revoke token approvals on EVM: how to audit allowances safely (checklist)
- 5Clarifying questions checklist (AI development): what to ask before you let an LLM build