tfpdev
3.5Part 3 · Payees

Address Poisoning

The studio pays a freelancer by copying their address from past payments. A scammer slipped in addresses that start and end the same. Try to spot the real one in 30 seconds, then see the safer way.

01Try it

Pay the freelancer again by copying their address from past payments. A scammer slipped three fakes in. You have 30 seconds.

Freelancer · October · 1,200 USDCTheir address starts 0x… and ends …. Find it in past payments and click it.
0:30
Simulator
BreaksCopies from past payments
Finds the newest payment that looks like theirs and copies that address.
The money went to—
HoldsUses the saved contact
Saved the address once, checked it with a second person, never copies it again.
The money went to—

Eight past payments, newest first. A scammer slipped three of them in. You have 30 seconds. Run out, and you copy the top one, like someone in a hurry.

02Step 2

How the trick works

Anyone can add to your list

A scammer can make a fake payment show up in your list without touching your money: one for 0, one in made-up coins, or a tiny gift.

Everyone checks the ends

Apps shorten the address to its start and end, so that's all anyone checks. A computer can make a matching one in a few hours.

There's no taking it back

No bank to call, no refund. Once the money lands on the wrong address, it's gone.

03Step 3

The code

What runs behind the buttons, in one sentence. The code itself is one click away.

The bad version copies the address from past payments. The good version uses an address that was saved once and checked by a second person.

Show the code anyway
BreaksBreaks
The version that loses money. Read the grey notes under it, not the code.
from-history.tsts
const last = history  .filter(tx => tx.to.startsWith("0xBe9d") && tx.to.endsWith("9B2C"))  .at(0);await sendUsdc(last.to, amount);
Anyone can put a row in your history: a zero-value transferFrom, a fake token, a cent of dust. The newest look-alike wins.
HoldsHolds
The version running behind the buttons above.
payee-list.tsts
const payee = await payees.get(freelancerId);if (!payee.confirmedBy || payee.confirmedBy === payee.addedBy) {  throw new Error("payee needs a second person's check");}await sendUsdc(payee.address, amount);
The address is entered once, from the freelancer's own invoice, and a second person confirms it. Payouts read the list, never history.
04Step 4

Still curious?

A few more questions people ask. Open what you need.

Is any of this real?

No. This one is a simulation: nobody is sent fake payments, and the look-alike addresses are just made up to match. The freelancer's address is the same one used in Paid Twice.

Why not just check the whole address?

You should, but people are bad at checking 42 characters, especially when tired. Saving it once and checking it with two people is safer than checking it alone every time.

What about saved contacts in a wallet app?

Same idea, and much better than past payments. What matters is where the address came from when you saved it: from the freelancer directly, not from your history.

Not sure this could happen to you?

That's what the call is for. Tell me how your product works, and I'll tell you what applies to you and what I'd check first.