x402 Progressive Demo · Chapter 4 of 7

Multi-Chain

What if the buyer holds crypto on a different network?
Published 2026-04-16 · Northwoods Software · x402 Payment Protocol

The Real-World Problem

Chapters 1 through 3 were all Solana. The buyer connected a Solana wallet, signed a Solana transaction, and the server verified on the Solana blockchain. That was the right place to start — Solana has sub-second finality and transaction fees under a penny, which makes it ideal for micropayments.

But here is the reality of the crypto market in 2026: USDC lives on many chains. A buyer might hold their stablecoins on Base (Coinbase's L2), Polygon, Arbitrum, or Ethereum itself (its base chain, L1). Telling those buyers "sorry, bridge to Solana first" is the crypto equivalent of telling someone "we only accept Visa, not Mastercard." It's a conversion killer.

Chapter 4 answers the question: can one payment framework accept USDC from any chain — without duplicating code for each network?

The Framework: x402-client.js

The answer required extracting the payment logic from the demo pages into a standalone, reusable framework. This framework — x402-client.js — uses a registry pattern for chain adapters. Each blockchain gets an adapter that implements the same interface. The framework doesn't know or care how each chain works internally; it just calls the adapter's methods.

// Register chain adapters — one per network
client.registerChain('solana',   solanaAdapter)
client.registerChain('base',     evmAdapter({ chainId: 8453 }))
client.registerChain('polygon',  evmAdapter({ chainId: 137 }))
client.registerChain('arbitrum', evmAdapter({ chainId: 42161 }))

// Payment call — chain is a parameter, not a code path
const result = await client.pay({
  chain: 'base',           // buyer picks their chain
  payTo: recipientAddress,
  amount: 0.25,
  token: 'USDC'
})

The key design decision: two adapters cover four chains. Solana has its own transaction model (SPL token transfers, Solana-specific signing). But Base, Polygon, Arbitrum, and Ethereum are all EVM-compatible — they use the same smart contract ABI, the same transaction format, and the same signing mechanism. One EVM adapter, parameterized by chain ID, handles all of them.

Architecture: The Registry Pattern

┌─────────────────────────────────────────┐ │ x402-client.js │ │ │ │ pay() verify() detectWallet() │ │ │ │ │ ▼ │ │ ┌─────────────┐ │ │ │ Chain │ .get(chainName) │ │ │ Registry │──────────┐ │ │ └─────────────┘ │ │ │ │ │ │ └─────────┼──────────────────┼─────────────┘ │ │ ┌───────▼──────┐ ┌──────▼───────┐ │ Solana │ │ EVM │ │ Adapter │ │ Adapter │ │ │ │ │ │ buildTx() │ │ buildTx() │ │ sign() │ │ sign() │ │ broadcast() │ │ broadcast() │ │ verify() │ │ verify() │ └──────────────┘ └──────────────┘ │ ┌─────────┼─────────┐ │ │ │ Base Polygon Arbitrum

Each adapter implements the same interface: buildTx(), sign(), broadcast(), and verify(). The framework calls whichever adapter matches the buyer's selected chain. Adding a new EVM chain is a one-line configuration entry — no new code required.

Server-Side: Unified Verification

The server's verification logic uses the same net-delta algorithm regardless of which chain the payment arrived on. The algorithm works like this:

  1. Fetch the transaction receipt from the appropriate chain's RPC endpoint
  2. Parse the token transfer events (SPL transfer on Solana, ERC-20 Transfer event on EVM chains)
  3. Calculate the net change in the recipient's USDC balance from this transaction
  4. Confirm the net delta is greater than or equal to the required payment amount

The details of parsing differ between Solana (instruction data) and EVM (event logs), but the verification question is identical: did the recipient's USDC balance increase by at least the required amount as a result of this specific transaction?

Key insight: The framework was born from a real need. A merchant's checkout needed to accept payments on multiple chains without duplicating 800 lines of code per chain. The registry pattern emerged from that constraint — and it turned out to be the right architecture for any publisher who wants to accept crypto from the broadest possible audience.

Chain Comparison

Not all chains are equal. The framework supports them all, but the buyer's experience varies:

ChainTx FeeConfirmationUSDC LiquidityWallet Support
Solana< $0.01~400msHighPhantom, Solflare
Base~$0.01~2 secondsGrowing fastMetaMask, Coinbase Wallet
Polygon~$0.01~2 secondsHighMetaMask, Rainbow
Arbitrum~$0.03~1 secondHighMetaMask, Rainbow
Ethereum$0.50–$5.00~12 secondsHighestMetaMask, all EVM wallets

For micropayments ($0.10–$1.00), Ethereum's base chain (L1) is impractical — the gas fee exceeds the payment. Solana and the L2 chains (Base, Polygon, Arbitrum) are where micropayments make economic sense. The framework lets the publisher configure which chains to offer, and the buyer sees only the chains they can afford to use.

The Review Process

Multi-chain support is the most architecturally significant change in the progressive demo series. It introduced a reusable framework, new external dependencies (EVM RPC providers, ethers.js), and a broader attack surface. The team treated it accordingly:

ReviewSpecialistFocusOutcome
Architecture Review #1ArchitectRegistry pattern, adapter interface, dependency managementApproved with minor interface adjustments
Architecture Review #2ArchitectServer-side verification unification, chain config structureApproved
Security Audit #1Security specialistSTRIDE threat model, EVM-specific attack vectors36 threats enumerated, all mitigated
Security Audit #2Security specialistCross-chain replay attacks, RPC trust boundariesApproved with RPC provider pinning

Four specialist reviews, 36 threats enumerated and addressed. This is the chapter where x402 stopped being a demo and started becoming a production framework.

Two adapters. Four chains. One verification algorithm. Adding a fifth chain — say, Optimism or Avalanche — requires adding one line to the registry configuration. The adapter, the verification, and the checkout UI all work automatically. The framework scales horizontally without code changes.
Note: Chapters 2 and beyond require running the x402 gateway locally to try the demos. See the project's README for setup instructions, including multi-chain RPC configuration.

What's Next

The framework now accepts payments from any major chain. But there's a platform that Chapters 1 through 4 ignored entirely: mobile. Specifically, iPhones. iOS Safari cannot see browser wallet extensions like Phantom or MetaMask. A buyer on their iPhone hits "Pay" and gets... nothing. No wallet detected.

In Chapter 5: Mobile Crypto for iPhone, we tackle the Safari hurdle with a three-phase solution — from zero-dependency deep links to embedded wallets that let a buyer pay with Face ID.