The one-sentence version
Ethereum addresses consist of 40 hexadecimal characters, and the human eye typically only notices the first and last few digits. Attackers mass-generate fake addresses that have the same prefix and suffix as your frequently used addresses, then send you a "transaction" with a zero or negligible amount to make it appear in your transaction history. The next time you copy an address from your history, you will end up copying the attacker's address. This attack does not need to steal anything; it simply exploits human habits. Defense relies on: not copying addresses from history, using an address book, comparing more characters, and wallets proactively flagging similar addresses.
This article has three layers:
- Layer 1: The Intuition: How the attack is performed
- Layer 2: Real-World Use: Real loss cases and responses from wallets and exchanges
- Layer 3: Principles and engineering key points: The cost of generating similar addresses, what EIP-55 checksums can and cannot do, and detection rules
Layer 1: The Intuition
1.1 Attack Steps
To make wallet interfaces look better, addresses are often abbreviated to 0x7a3f...91c2. The real address and the fake address look exactly the same once abbreviated.
1.2 Why it works
- Human memory for a long string of random characters is generally limited to just the first and last few digits;
- "Copying from history" is a very natural operation that everyone does;
- The cost of the attack is extremely low: generating an address and sending a 0-amount transfer are very cheap, allowing attackers to cast a wide net across tens of thousands of people.
Layer 2: Real-World Use
- Scale: Statistics from on-chain security firms show that address poisoning attempts number in the hundreds of millions annually, with cumulative victim losses exceeding tens of millions of dollars.
- Notable Case (May 2024): A user lost 1,155 WBTC (approximately $68 million at the time) in a single transfer because they copied a poisoned address. This incident later took a dramatic turn: following on-chain messages and tracking, the attacker returned most of the funds. However, the vast majority of victims are not so lucky.
- Industry Response:
- Wallets and block explorers now default to hiding zero-amount transfers and unknown tokens;
- Warning prompts such as "This address is similar to one from your history" during transfers;
- Whitelisting withdrawal addresses on exchanges to prevent errors from copying from history at the source.
Caloogy Wallet also employs address poisoning detection.
Layer 3: Principles and Engineering
3.1 How difficult is it to generate a similar address?
An Ethereum address is derived from the hash of a public key and can be viewed as 40 random hexadecimal characters. To make a fake address and a real address match in both the first digits and the last digits, on average, one would need to try
private keys.
| Matching digits (Prefix + Suffix) | Average attempts | Difficulty |
|---|---|---|
| 4 + 4 | A single GPU in seconds to minutes | |
| 6 + 6 | GPU clusters, feasible | |
| 10 + 10 | Practically infeasible |
Note that this is a second preimage style search (finding a similar address given a specific target address), not a birthday attack, so you cannot take the square root (see "The Birthday Paradox and Hash Collisions"). The conclusion is: Checking only 4 digits at the start and end is far from enough; the more digits you verify, the safer it is.
3.2 EIP-55 Checksum: Prevents typos, but not poisoning
The casing of Ethereum addresses is not arbitrary. EIP-55 stipulates: Take the Keccak-256 hash of the lowercase address; if the th hexadecimal digit of the hash is , then the th letter of the address is written in uppercase.
Test address in EIP-55 standard
Correct format: 0x5aAeb6053F3E94C9b9A09f33669435E7Ef1BeAed
If the last digit is miscopied, ...BeAed becomes ...beaee, then the correct casing for the corresponding address becomes
0x5Aaeb6053f3e94c9B9a09F33669435e7EF1BeAee, where almost every letter's case changes.
If the wallet detects that the casing pattern you entered does not match the correct one, it will throw an error. (Verified with Python.)
Similar to the "casting out nines" method or checksums used in ID cards and bank cards, EIP-55 can catch random transcription errors. However, a poisoning address is itself a legitimate address with its own correct checksum, so EIP-55 cannot prevent poisoning at all.
3.3 Detection Rules
| Rule | Description |
|---|---|
| Compare prefix/suffix similarity with historical transaction recipients | If the first and last several digits match but the overall address is different, mark it as suspicious |
| Whether the counterparty has sent you 0-amount or fake token transfers | A typical prelude to poisoning |
| Whether this is the first time transferring to this address | The first transfer itself should require an extra layer of confirmation |
| Whether the token is on a whitelist | Poisoning is often accompanied by fake tokens (e.g., named "USDT" but with a different contract address) |
3.4 Interface Design
- Do not provide a "Select recipient from history" entry point; instead, use an address book that requires active addition;
- The confirmation page should display the full address rather than an abbreviation, and highlight more digits;
- In high-risk scenarios, require the user to manually input several digits of the address (to break the "glance and confirm" habit, see "Risk Control Scoring and Friction Design");
- Before a first-time or large-value transfer, suggest sending a small test amount first, or verifying the address with the counterparty through another channel (see "Out-of-band Verification").
Summary
| Layer | Key points |
|---|---|
| Attack | Generate addresses with matching prefixes and suffixes to blend 0-amount transfers into your history |
| Cost | Matching 8 digits at the start and end requires only a few billion attempts, which is very cheap |
| Checksum | EIP-55 prevents typos but does not prevent poisoning (the poisoned address itself is valid) |
| Defense | Do not copy from history; use address books; full display; similarity detection; out-of-band verification |