The threat
Suppose an attacker fully compromises our database and rewrites your payout address to theirs. On a conventional processor, that’s the end of the story — the checkout renders whatever the database says, and customers pay the attacker. We designed so that attack fails.The mechanism
You pin your payout address in the embed code on your own site:Read the chain
The browser calls the on-chain registry to resolve the payout address for the anchor from your site. There is no setup step for you here: the registry holds nothing for that address in the normal case today, and it then resolves to the anchor address itself. If a different address is ever recorded, only the anchor wallet’s own signed transaction can record it — the registry gives each address one slot that nobody else can write. Either way, our database has no way to author the answer.
Recompute the address
From that chain-read value, the browser recomputes what your pool address must be — the same deterministic derivation the contracts use.
Compare
If the recomputed address differs from what our API served, something is wrong.
Refuse
The checkout enters a terminal state, hides the payment address, and tells the customer not to pay.
Why the integrity hash matters too
integrity attribute pins its exact hash. If the file we serve differs by a single byte, the browser refuses to execute it at all. Tampered code fails closed rather than running altered.
That is why the URL carries a version. A released file is never edited again, so the hash you pasted stays valid for as long as that version exists; we ship changes as new versions, and you move to one by re-copying the snippet. The unversioned /sdk.js always serves the newest release and changes with it, so never pin an integrity hash to it.
Keep both
integrity and settlementAnchor. Removing either silently removes a protection that exists specifically for you. Neither affects how the checkout looks or behaves normally, which is exactly why they’re easy to drop during a refactor.Honest limits
We won’t overstate this. The conditions under which it holds:It requires you to pin an anchor
It requires you to pin an anchor
Without
settlementAnchor in your embed, the checkout shows an unverified badge and does not block. The protection is opt-in per merchant because it depends on something only you can provide.It defends database compromise, not everything
It defends database compromise, not everything
A total compromise of our served code is mitigated by the integrity pin, not eliminated. Different threat, different (weaker) guarantee.
It covers both ways to pay — on EVM chains only
It covers both ways to pay — on EVM chains only
Whether your customer pays by connecting a wallet or by sending to a pay-to-address we generate for the order, the browser runs the same check before it shows them anywhere to send money. What the check proves is narrow and specific: the destination on screen is the one derived from the address read off the chain. It says nothing about the order amount, the goods, or the safety of the customer’s own wallet. And it runs on EVM chains only — TRON payments are not covered, as the next point explains.
TRON payments don't carry the anchor check
TRON payments don't carry the anchor check
A registry contract is deployed on TRON and listed on the verify page, but nothing in the TRON payment path reads it yet, and the checkout can’t recompute a TRON settlement address in the customer’s browser. TRON payouts go to the address baked into your pool when it was provisioned, which is checked against that committed address before anything is deployed — but without the on-chain recompute-and-compare step described above.
The audit is pending
The audit is pending
A third-party security audit is a mainnet gate and has not completed. Roadmap.
We describe this as a mechanism with conditions, never as “unhackable.” Any vendor who tells you their system cannot be compromised is telling you they haven’t thought about it carefully.
Checking for yourself
Verify page
Every deployed contract, per chain, with explorer links.
Read your own pool
Call
recipient() on your pool address on any block explorer. It should be your payout address, and you should be unable to change it.