A wrong field in a CCTP burn or an OFT send loses funds permanently. So the client never trusts the server on those fields. Each verifier decodes what the user is about to sign and compares it with the chain registry and with what the user picked or typed. It throws on any mismatch.
Pass the values from your own UI and the SDK’s registry, never from the server’s response. A verifier that compares the server with itself proves nothing.
verifyCctpCalls
Checks a CCTP deposit’s evm_calls:
- exactly
approve then depositForBurnWithHook, with no native value;
- the approve is on the chain’s USDC, for TokenMessengerV2, for the amount;
- the burn targets TokenMessengerV2 with destination domain 27;
mintRecipient and destinationCaller are both Circle’s Stellar forwarder;
- the hook data decodes to
recipient, the user’s own Stellar address;
- the burn token is USDC, the amount is
amount6, maxFee is 0 and minFinality is 2000.
verifySendToAddress
Checks that a send_to_address action is on the picked chain, is the user’s own smart wallet, and asks for the quoted amount. It does not check the asset, so build the token transfer from your own USDC constant.
verifyStellarPayment
Checks a Stellar send: a plain transaction (not a fee-bump) from the owner, with one USDC payment to the destination for the amount. Returns the Transaction to sign. Sign that object, not the raw XDR.
Verifiers for the other routes
Envelope rules for Stellar transactions
Every Stellar verifier also checks the envelope:
- no memo;
- an expiry no more than 30 minutes away, and not valid more than 60 seconds in the future;
- a fee of at most 10,000 stroops for a payment, or 1 XLM for a contract call (its resource fee is included);
- no extra signers, ledger bounds or sequence preconditions;
- for contract calls, one call with only source-account authorization rooted at it.