Multi-Chain Settlement
Cross402 decouples where a payer sends the stablecoin from where the merchant receives it. This page explains that model from the caller's perspective: what the two chain fields mean, how the x402 protocol handles both legs, and what the caller observes as status transitions.
Two chains per intent (and optionally two assets)
Every CreateIntent request carries:
payer_chain— required. The chain on which the payer holds stablecoins and signs an X402 authorization.target_chain— optional, defaults to"base". The chain on which the merchant receives stablecoins.payer_asset— optional, defaults to"usdc". One ofusdc|usdt|usdt0. Selects the stablecoin the payer signs against onpayer_chain.target_asset— optional, defaults to"usdc". Same set aspayer_asset. Selects the stablecoin the merchant receives ontarget_chain.
Asset and chain are independent: a payer can sign in USDT0 on Arbitrum while the merchant still receives USDC on Base. Clients that omit the asset fields keep the historical USDC-everywhere behaviour with no wire-format change. See the Token × Chain matrix for the supported (chain, asset) combinations.
The merchant address is validated against target_chain. If target_chain is an EVM chain, recipient must be a 20-byte hex address; if it is solana, recipient must be a Solana public key. For email recipients, Cross402 resolves the email to a wallet on the target chain via Privy — so the same email returns a Solana address when target_chain is solana, and an EVM address when target_chain is an EVM chain.
Any chain exposed by GET /api/chains may be used as either payer_chain or target_chain, including same-chain combinations (base → base, polygon → polygon, etc.). See Supported Chains for the full set and per-chain caveats.
How settlement works
Both sides of an intent — payer-side collection and target-side merchant payout — run through the x402 protocol. Each side produces a signed x402 payload that Cross402 forwards to the shared x402 facilitator, which executes the payment on-chain.
- Payer side — the payer's client signs an x402 payload authorizing the stablecoin to move from the payer's wallet to Cross402.
- Target side — once the source leg settles, Cross402's proxy wallet signs its own x402 payload authorizing the stablecoin to move from that proxy wallet to the merchant address on
target_chain.
The facilitator is the same component on both sides; the only thing that changes per chain is the signing flavor, which depends on what the chain's USDC contract supports:
Signing flavors
The signing flavor is per-(chain, asset), not per-chain. The same chain can use different flavors for different assets (e.g. on MegaETH, native USDm uses Permit2 while USDT0 uses EIP-3009).
- EIP-3009
TransferWithAuthorization— Circle USDC on Base / Ethereum / Polygon / Arbitrum; USDT0 on Arbitrum / Monad / HyperEVM / MegaETH. A single signed authorization is sufficient; the facilitator relays it on-chain. - Permit2 + EIP-2612 — chains with non-standard USDC (BSC, Monad, MegaETH); and Polygon USDT / USDT0 (same contract
0xc2132D..., implements EIP-2612 on a salted EIP-712 domain — not EIP-3009). The payload combines a Permit2PermitWitnessTransferFromsignature with a gasless EIP-2612Permitthat grants Permit2 the allowance. Cross402 sponsors the on-chain submission. For Polygon USDT/USDT0,payment_requirements.extra.domainType == "salted"signals the non-standard domain layout. - Approval sponsorship — legacy native USDT on Ethereum / BSC / Base (no EIP-3009, no permit). The facilitator pays gas to submit
approve+transferFromon the payer's behalf; first payment from a (chain, wallet) pair carries anapprove(5–60s extra latency), subsequent payments are signature-only. Currently gated behind a deployment flag. - Solana VersionedTransaction (v0) — Solana. The payer or proxy wallet partially signs a VersionedTransaction carrying an SPL
TransferCheckedinstruction; the facilitator co-signs as fee payer before submission.
Callers do not select the flavor. The SDK (or a compliant x402 client) produces the correct payload from the payment_requirements block returned on CreateIntent. From the caller's viewpoint the contract is unchanged: POST createIntent, submit the signed payload, poll status.
What the caller observes
The status progression is the same regardless of which chains are paired:
AWAITING_PAYMENT
│ (payer submits X402 authorization)
▼
PENDING
│ (verification + source-chain settlement)
▼
SOURCE_SETTLED
│ (cross402 dispatches target-chain transfer)
▼
TARGET_SETTLING
│ (target-chain tx confirms)
▼
TARGET_SETTLED ← terminal
On a GetIntent response for TARGET_SETTLED, the target_payment block holds the tx hash and explorer URL for the transfer on target_chain. The source_payment block holds the corresponding source-chain tx.
Rollback
If Cross402 moves the intent to TARGET_SETTLING but the target transfer cannot be dispatched — for example because the agent's target-chain wallet hasn't been provisioned for that chain — the status is rolled back atomically to SOURCE_SETTLED. Callers that poll will see this as a transient dip; the pipeline retries automatically.
Two failures are terminal:
VERIFICATION_FAILED— source-side authorization could not be verified. No funds moved on the payer side.PARTIAL_SETTLEMENT— source settled but target transfer could not be completed at all. Payer funds have moved; contact support for reconciliation.
See Statuses for the full transition table.
Fees
Fees are computed per (payer_chain, target_chain) pair and returned in fee_breakdown on every intent response:
source_chain_fee— gas/network cost on the payer side.target_chain_fee— gas/network cost on the target side (for example Ethereum gas is meaningfully higher than Base or Polygon).platform_feeandplatform_fee_percentage— Cross402's service fee.total_fee— sum.
See Fee Breakdown for the exact shape.
Related
- Supported Chains — payer × target matrix and per-chain caveats.
- Statuses — full state machine.
- Architecture — end-to-end flow.