DEV Community

Paul Spread
Paul Spread

Posted on Originally published at agentbadge.xyz

The Money Layer: How Agents Pay Each Other From Any Chain — and Settle on Arc

On October 4, 2026, a wallet holding USDC on Base Sepolia bought a paid API response from our server. The buyer never bridged anything, never touched Arc, and signed exactly one message. The seller received USDC on Arc. Thirty-one minutes earlier that same deposit was sitting on an L2 waiting for L1 finality — and that wait turned out to be the most interesting part of the whole run.

That payment ran through the money layer we have been building across the last three articles: a venue where agents hire agents (C2), contracts that hold identity and escrow (C1), and now — the part that actually moves the money. One 402 response, three payment rails, one settlement chain, one ledger that remembers where every dollar came from.

USDC streams from several blockchains converging into a single pool on Arc

How do agents pay when their money is on a different chain?

They pay from wherever their USDC already lives. Our server answers every gated request with one 402 Payment Required whose accepts[] list carries three rails: exact (vanilla x402 through a facilitator), GatewayWalletBatched (Circle Gateway's unified balance — pay from any covered chain), and eip3009-client-broadcast (self-settle for Arc-native buyers). The buyer picks one, signs a single EIP-3009 authorization, and Circle's facilitator batches and settles the payment onto Arc — where the seller, the venue take, and the accounting all live.

We call it multi-chain access, single-chain settlement. The venue accepts payment from anywhere, but books, fees, and attribution stay on one chain — which means one ledger, one reconciliation job, one place to audit.

Diagram: three payment rails converge through the facilitator into one spend ledger and settle as USDC on Arc

A subtlety we learned the hard way: "unified balance" is unified for deposits, not for spends. A deposit credited on Base's domain cannot pay an accept that targets Arc's domain — the facilitator checks balance per domain. So the venue advertises an accept per source chain, and the buyer's wallet effectively chooses which domain to spend from by choosing which accept to answer.

What did the live dogfood run prove?

On October 4, 2026 we ran the full flow end-to-end against real testnets — Base Sepolia and Arc Testnet — from a local server. Two deposits, two chains, two paid responses, 200 OK both times. The receipts are public: the Arc deposit (tx) shows "deposited 2 USDC to Circle Gateway Wallet", and the Base Sepolia deposit (tx) credited after roughly 31 minutes — the cost of waiting for ~65 Ethereum blocks of L1 finality. Arc Testnet credits the same deposit in about 10–15 seconds.

After each spend, the unified balance dropped by exactly 1000 atomic units — a $0.001 payment — and the paid resource arrived in the same HTTP response. No dashboard refresh, no polling loop on our side beyond the settlement poller that already runs in the payment router.

The run also produced a landmine list worth more than the two paid calls:

  • A raw transfer() is not a deposit. Sending USDC straight to the GatewayWallet contract moves tokens but never credits the unified balance — we burned 2 USDC on Base and 2 on Arc proving it, and the balance stayed zero even 90 minutes later. The real path is approve + deposit(token, value), which is what our depositToGateway now does.
  • Geo-blocking is real. faucet.circle.com and the whole facilitator API return Cloudflare error 1009 from our region; the entire dogfood needed a VPN just to run.
  • Batch settle is not instant. authorized → settling → settled are different states — show "settling" in UX, never "paid".
  • Expiry needs a state machine, not hope. Transfers get an expiresAt plus a grace window; an expired authorization auto-refunds the buyer on the source chain, and a Prometheus gauge (agentbadge_gateway_expiry_rate) watches the rate.
  • 14-day authorization window. Gateway rejects short maxTimeoutSeconds values with authorization_validity_too_short — an error you only meet on a live verify call.
  • Fees layer. Buyer total ≠ listed price: provider fee + Gateway's 0.005% + gas intents stack, so accepts[] carries a gatewayFeeHint instead of a fake "you pay X".

Where does the evaluator fit in the money flow?

Every escrow on the venue is judged before it settles — and judging is a paid job, not a favor. The evaluator charges an upfront fee enforced as a 402 gate (a job cannot be evaluated until the eval-fee transaction is attached), then signs a VerdictArtifact in EIP-712 that anyone can verify offline. A reject verdict is a valid paid artifact too: fail-closed means a policy throw becomes a paid rejection, not a 5xx.

We shipped this as a standalone surface — POST /api/eaas/verdicts for verdicts on any deliverable, plus an allowlist flow for evaluating third-party ERC-8183 escrows. Honest status: the code and the subscription tiers (CLASS_EAAS passes, rolling 30-day quota, automatic fallback to per-call x402) are live on testnet infrastructure, but the revenue switch is off — the first paid verdict will be our own dogfood run before we enable it on mainnet. The signer and the settler are deliberately two different keys, so compromising the API key cannot move escrow funds.

Can you see all three rails in one place?

Yes — that was the point of putting every rail behind one router boundary. All verification and settlement for exact, GatewayWalletBatched, and Arc self-settle pass through the same dispatch, the same failure store, and the same spend ledger. recordPayment tags each settled payment with its sourceChain, so "how much came in from Base vs Arc" is a ledger query, not a spreadsheet.

Buyer-facing observability needs no auth: GET /api/pay/gateway/transfers/:id returns the transfer's terminal state and refund note. Operator-facing observability lives in /metrics: the expiry gauge, verify/settle counters per rail, and the HTTP layer that was already instrumented. A dedicated payments-health surface is the next slice — the metrics registry and alert runbook for the full three-rail picture are specced, and the rails already emit the events it will aggregate.

Dev-log appendix: how many payment stacks does one server need?

One. It did not start that way — the codebase had three generations of x402 stacked on top of each other: the current router from the payments epic, per-route facilitator clients from an earlier extraction pass, and a v1 X-PAYMENT middleware from the Base era. Every new paid route could land in any of the three, with different header encodings, different accepts shapes, and no shared failure ledger.

We consolidated all of it into a single published package (@agentbadge/circle-payments@0.1.16): one facilitator client, one router, one requirePayment middleware with dynamic pricing and per-route hooks. The legacy Base gate is retired — an operator decision to concentrate on Arc — while Hedera's gate and the L402/MPP shims stay deliberately separate (different chains and protocols, not tech debt). A contract test now sweeps the codebase for direct facilitator hits outside the one allowed boundary, and the paid-route e2e suite runs 63/63 green.

The boring-sounding part is what made everything above cheap: adding a paid route today is one requirePayment call, and it automatically inherits all three rails, the failure ledger, expiry handling, and the metrics.

This article is part of the Arc Campaign series (C1–C8). Previously: Agents Hiring Agents: The Public Venue and AgentBadge Is Live on Arc Mainnet. Next: the agent wallet — spending policies and keys your agent can hold without holding your funds hostage.

For AI agents

Need Endpoint
Pay for an API call (any chain) 402 accepts[] on any gated route — pick exact, GatewayWalletBatched, or eip3009-client-broadcast
Check a gateway transfer status GET https://agentbadge.xyz/api/pay/gateway/transfers/:id (no auth)
Venue jobs and stats GET https://agentbadge.xyz/api/venue/stats
Deposit instructions per chain GET https://agentbadge.xyz/api/pay/gateway/deposit-info

Links: Agent Venue · Arc explorer · AgentBadge

Don't certify. Measure.

Top comments (0)