-
-
Attacker console — plant a lookalike address into the victim's history (the real poisoning vector)
-
Victim's history after the attack: two payees with identical first/last 4 characters
-
The real sender approves the flagged lookalike send explicitly
-
Pending send shows the full untruncated address — no 0x1234…9c8f truncation
-
After cooldown the lookalike still can't be claimed — sender approval required
-
Sending to the lookalike fires the LOOKALIKE warning before funds lock
-
Recipient claims the approved send — claim doubles as the verify handshake
-
A verified payee settles instantly, like a normal send
The $68M copy-paste mistake
In May 2024 a wallet lost $68 million in WBTC to one of the oldest tricks on-chain: address poisoning. The attacker seeded the victim's transaction history with a zero-value transfer from a lookalike address — same first 4 and last 4 characters as the real payee. The victim copied "their" payee from history, pasted it, hit send. Irreversible by design. (The funds were mostly recovered weeks later — after being stolen in seconds.)
Most wallets render addresses truncated (0x1234…9c8f), and anyone can inject into your history — dust for incoming transfers, zero-value transferFrom for outgoing on USDT-style ERC-20s. The defense has to happen at the same layer the attack exploits: the transaction itself.
How SafeSend works
SafeSend is a poison-aware EVM payment router. Instead of sending ERC-20s straight to an address, you route through the contract, which classifies each destination with a 32-bit fingerprint — (first 4 hex chars << 16) | last 4 hex chars — exactly the parts wallets show you:
- Verified payee → settles instantly, like a normal send.
- Fingerprint collides with a verified payee → flagged
LOOKALIKEand held for 24h. Time alone never unlocks it — the sender must explicitly approve (and can always cancel). This is the poisoning case: the lookalike matches your trusted contact's visible edges. - Unknown recipient → escrowed under a sender-set cooldown (default 1h, 60s–7d). The recipient claims after unlock — which doubles as a claim-to-verify handshake — or the sender reclaims 30 days after the escrow's unlock time.
The sender sees the full untruncated destination before funds lock, not 0x1234…9c8f.
Watch the attack get caught
The repo ships Poisoner.sol, a Foundry reproduction that plants the same lookalike transactions real poisoners use (zero-value transferFrom + dust, Anvil local only). In the demo, the victim's history shows two identical-looking payees — the router quarantines the send to the wrong one, the non-sender "approve" call reverts, and only the real sender can release. Try it: make anvil && make deploy-local && make seed && make web → localhost:5173/?demo=1.
Technical details
- Contract: Solidity 0.8.28, OpenZeppelin
SafeERC20+ReentrancyGuard, checks-effects-interactions. No owner, no admin keys, no fees, not upgradeable. - Toolchain: Foundry (
forge test— 58 tests, 100% line coverage onSafeSend.sol). - Frontend: Vite + React 18 + TypeScript + wagmi v2 + viem + Tailwind. Includes an "Attacker console" so judges can fire the poisoning themselves.
- Networks: local Anvil (chain 31337) for the demo; optional Base Sepolia deploy.
Honest limits
This is a prototype, and we say so: the fingerprint only checks the first/last 4 hex characters (the part users actually compare); routing is detection, not prevention — a poisoned verified payee isn't caught; recipient classification is fixed at escrow creation; addPayee is a trust decision; the contract is unaudited and lives on testnet/local. We also disclose prior art openly: reversible-transaction proposals (REVERSO, ERC-20R/721R), Argent-style trusted contacts, and explorer name-tags — SafeSend's angle is enforcing the edge-fingerprint check inside the transaction path instead of in the UI.
Links
- Live demo (static showcase): https://sharonbasovich.github.io/safesend/
- Demo video (v2, approval flow): https://sharonbasovich.github.io/safesend/media/demo-v2/safesend-demo-v2.mp4
- Pitch deck: https://sharonbasovich.github.io/safesend/media/deck.pdf
- Source: https://github.com/sharonbasovich/safesend
Built With
- base
- ethereum
- evm
- foundry
- openzeppelin
- react
- security
- smart-contracts
- solidity
- tailwindcss
- typescript
- viem
- vite
- wagmi
- web3
Log in or sign up for Devpost to join the conversation.