Accept payments from any USDC chain
CCTP V2 routing. Customer pays from Ethereum, Base, Arbitrum, Polygon, Solana, etc., you get USDC on Arc.
Roadmap, not shipped
Cross-chain via CCTP V2 is on the roadmap. The database schema and
scheduler wiring are in place, and the design below is how it will
work when shipped. The checkout <StrimzPayButton sourceChain=...> prop
is not live yet. Merchants who need cross-chain today should keep the
customer on Arc.
Strimz settles on Arc, where USDC is the native gas token. But your customer might hold their USDC on a different chain (Ethereum, Base, Arbitrum, Polygon, Solana, Avalanche, Optimism). Instead of forcing them to bridge first, Strimz uses Circle's CCTP V2 to bridge and settle in one flow.
How it works
- Customer chooses their source chain in your hosted checkout. (The picker is a
<StrimzPayButton sourceChain="base" />prop.) - Customer signs a
depositForBurnon their source chain. This burns USDC and emits a CCTPMessageSentevent. - Apps/web detects the burn, enqueues a
strimz.routing.cctp.bridgejob onto the agent's queue with(sourceDomainId, sourceTxHash, merchantId). - Agent's bridge worker polls Circle's IRIS API for the attestation. That's the cryptographic signature that says "the burn happened, here's the message you can replay on the destination". CCTP V2 fast-transfers attest in ~13 seconds.
- Agent enqueues a settle action onto the scheduler's queue. Scheduler signs
MessageTransmitter.receiveMessage(message, attestation)on Arc. - You get USDC on Arc. A standard
Transactionrow is written; you receivepayment.completed.
From your perspective, the customer pays, and a payment lands. From the customer's perspective, they connect their wallet on the chain they actually use, sign once, and they're done.
Supported source chains
Strimz supports every chain Circle's CCTP V2 supports:
| Chain | CCTP domain |
|---|---|
| Ethereum | 0 |
| Avalanche | 1 |
| Optimism | 2 |
| Arbitrum | 3 |
| Solana | 5 |
| Base | 6 |
| Polygon | 7 |
| Arc (destination) | 26 |
When Circle adds a new chain, Strimz picks it up automatically. There's no integration work on your end.
What you'll see in the dashboard
Cross-chain payments show up in your Transactions list with a small flag indicating the source chain. The activity timeline includes:
routing_bridge_initiated. Agent received the source-chain hash.routing_payment_completed. Circle attested, scheduler enqueued.payment.completed(after the indexer projects the on-chain receipt).
If a bridge gets stuck (Circle attestation never lands, network outage on the destination chain), it sits in routing_bridge_initiated and the activity log shows the latest poll attempt. You can manually replay from the dashboard.
Failure modes
- Source-chain tx reverts. It never reaches Strimz. The customer sees the error in their wallet.
- Circle attestation never lands. Extremely rare. After 100 polling attempts (about 50 minutes), the bridge is marked
failedand the customer is automatically refunded by re-burning on the source chain. - Destination-chain settle fails. The scheduler retries with exponential backoff. Transient errors (gas spike, RPC blip) self-resolve. A permanent error (destination contract paused) triggers an email and pauses routing for that merchant until you resume it manually.
Why CCTP V2 specifically
V1 attests in around 13 minutes instead of 13 seconds, supports fewer chains, and has worse failure semantics. V2's fast-transfer mode is what makes the cross-chain experience feel like one payment to the customer rather than a bridging step plus a payment.
The full Circle docs are at
developers.circle.com/stablecoins/cctp-getting-started.
Strimz's source-side burn is implemented client-side in apps/web.
The destination-side settle is server-side in apps/agent and
apps/scheduler.
