← Back to blog

We tried to pay ERC-8004 agents over x402. 0 of 3 payable Base agents interoperated with a stock v1 client.

A buyer-side field test on the Base x402 agent-payments economy. Four post-tightening Base Transact-ready ERC-8004 agents scanned, three payable at a $0.05/call cap after payTo dedupe, zero delivered end-to-end on a stock EIP-3009 v1 EVM client. Three distinct failure classes. Zero USDC moved on-chain. A re-run after a dual-version client fix returned isValid:true on verify-only for both of the two protocol failures — so the plumbing is reachable, but a cold buyer cannot assume it.

Published 11 October 2026 · Companion to the x402 Bazaar listing-census findings and the x402 quickstart · CC BY 4.0.

We publish this because the gap has three steps: listed is not reachable, reachable is not payable, payable is not delivered. The failure modes are specific and fixable, not a vague ‘ecosystem not ready’.

Selling over x402? These are the failures buyers hit. Test your own endpoint. It takes seconds and is free. Test your endpoint → Read the launch post: Can agents actually pay you?

How we tested

We used a purpose-built test buyer, hard-capped at $0.05 per request and $5.00 in total, paying from a dedicated test wallet. Candidate set: every post-tightening Base Transact-ready ERC-8004 agent (four rows). For each candidate the pipeline is: probe the common /pricing / /.well-known/x402.json / agent-card paths, parse the 402 challenge, filter to Base-mainnet USDC accepts with a listed price ≤ $0.05 after payTo dedupe, sign an EIP-3009 payload, and submit it to the agent's own endpoint on a paid retry. We did not rotate across unknown facilitator endpoints; we signed against each agent's own 402 and submitted to each agent's own URL.

The baseline client is a stock EIP-3009 v1 EVM payload shape — the same shape our own /v1/intel/* paywall advertises and the same shape a generic autonomous buyer would default to. No per-vendor glue, no bearer-token bootstrap, no version-switching logic. If the ecosystem is interoperable, it pays. If it isn't, we record what fails and why.

Headline

  • Candidates scanned: 4
  • Payable at the $0.05 cap after payTo dedupe: 3
  • Attempted paid requests: 3
  • Delivered + substantive responses: 0
  • Failed at paid retry: 3
  • Total USDC spent on-chain: $0.00
  • Distinct failure classes recorded: 3

Zero USDC moved because an x402 facilitator-rejected or auth-gated paid retry never broadcasts the EIP-3009 transfer: the signature is handed to the facilitator for /verify before any /settle. The payer wallet's Base USDC balance was identical pre- and post-run.

The three failure classes

We describe the sellers as agent A, agent B, agent C and the fourth candidate (not attempted) as agent D. Specific agent identities are not surfaced here — the point is the shape of the failure mode a buyer-side client has to handle, not a league table.

Agent Paid-retry status Failure class What the buyer has to do
A HTTP 401 auth_walled x402 is a billing surface on top of session auth, not instead of. A cold agent-to-agent payment is impossible without a prior bearer-token bootstrap step out of band.
B HTTP 402 + payment_requirement_mismatch version_mismatch Challenge advertises x402Version=2; the stock v1 envelope is rejected before the signature is checked. Buyer must speak v2.
C HTTP 402 + Payment verification failed facilitator_mismatch Payments route through a facilitator that does not accept a Circle-native Base USDC EIP-712 payload as sent. The 402 omits an extra:{name,version} field and leaves the buyer to guess the EIP-712 domain. A naive buyer silently guesses wrong.
D not attempted no_cheap_402_exposed Only priced tool is behind a static bearer; no cheap bare GET/POST priced ≤ $0.05 exposes an x402 challenge. The agent is Transact-ready in principle but has no path for an anonymous payer.

Three different reasons; zero paid deliveries. On a buyer-side stock EIP-3009 v1 EVM client — the shape a cold autonomous caller would default to today — the Base agent-economy's x402 Transact-ready cohort is not interoperable at all.

v1 vs v2 on the wire — what actually changed

The two protocol-level failures (B and C) are specific and fixable. Here is what we learned re-writing a dual-version client against the live 402s and the public facilitator.payai.network /verify endpoint:

  • Envelope shape. v1 is flat: {x402Version:1, scheme, network, payload:{authorization, signature}}. v2 nests the full PaymentOption inside accepted: {x402Version:2, accepted:{scheme, network, amount, payTo, asset, maxTimeoutSeconds, extra}, payload:{authorization, signature}}. A partial accepted block is rejected by payai with invalid_payload: expected string, received undefined.
  • Header name. v1 sends the signed envelope in X-PAYMENT; v2 sends it in PAYMENT-SIGNATURE. Picking the wrong header is a silent-reject failure mode on the server because the request looks unpaid rather than mis-paid.
  • uint256 serialisation. authorization.validAfter and validBefore must be strings. JSON-number uint256 fields are rejected by payai with unrecognized EVM payment payload. Send them as strings: a buyer that sends JSON numbers is rejected by third-party facilitators.
  • paymentRequirements shape. The facilitator's /verify contract is also version-aware: v2 uses amount, v1 uses maxAmountRequired. A mismatch returns invalid_payment_requirements: x402Version 2 requires V2 payment requirements before any signature check.
  • Challenge-driven dispatch. Read x402Version off the 402 body and build the matching envelope — do not hard-code the version a buyer client speaks. There is no manual flag that substitutes for this.

The EIP-712 USDC domain gotcha

Agent C's failure is not an x402-protocol problem; it's an EIP-712-domain problem that looks like an x402 problem. Base USDC's Circle-native domain is:

  • name = "USD Coin"
  • version = "2"
  • chainId = 8453
  • verifyingContract = 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913

If a 402 accept carries an extra:{name, version} field, honor it — a self-describing agent is telling you which domain to sign under. If the accept omits extra, fall back to the Circle-native defaults by resolved chainId. Do not guess for unknown chains. And on a known chain where the asset address does not match Circle USDC, the buyer should refuse to sign rather than produce a signature against the wrong verifyingContract — a wrong-contract EIP-712 signature is a cross-contract-replay risk even if the facilitator politely rejects it today.

A naive v1 client that silently guesses the domain is the failure mode we observed for agent C. A client that honors extra, falls back to Circle defaults by chainId, and refuses on asset-mismatch is accepted.

Auth walls in front of 402

Agent A returns HTTP 401 before any 402 challenge fires. x402 is designed to replace a static bearer with a per-request payment — but a seller that layers x402 on top of a bearer-token bootstrap (CLI setup, Discord-issued key, account-manager approval) breaks the cold-flow premise. A buyer-side agent can only clear this with an out-of-band onboarding step; there is no protocol-level way to pay in.

This is worth naming as a failure class in its own right because a listing / registry can plausibly carry an agent as “x402 payable” while the first actual request from a cold caller returns 401. The 401 is an important signal: the agent isn't x402-first for strangers, regardless of what its signpost says.

How to test without spending — verify-only

The cheapest audit tool for a buyer-side x402 integration is verify-only: build and sign the payment payload exactly as a settle call would, then POST {x402Version, paymentPayload, paymentRequirements} to the facilitator's /verify endpoint instead of the seller. /verify returns isValid:true or false without broadcasting the EIP-3009 transfer. No USDC moves. No seller is paid. The facilitator tells you whether the payload shape, header, version, domain and signature would be accepted.

We re-ran our own client after fixing the three issues above:

  • Agent B (v2) via facilitator.payai.network — isValid:true.
  • Agent C (v1) via facilitator.payai.network — isValid:true.
  • Coinbase CDP Facilitator (api.cdp.coinbase.com/platform/v2/x402/*) — both /verify and /supported return HTTP 401 without a CDP API key. We did not provision one for this test. Indirect evidence: payai's /supported advertises eip155:8453 v2 with transferMethod=eip3009 — the same primitive the CDP TypeScript SDK builds — and payai said isValid:true on the same payload envelope.

Verify-only is cheap, deterministic, and the right default pattern for anyone wiring a new buyer-side integration or validating a client after upgrade. It also makes “x402 interoperability” a measurable property rather than a brand — you get a boolean back, with a specific error string on false.

Checklist: what a buyer agent must handle to actually pay a 402 today

  1. Read x402Version off the challenge first. Dispatch to the matching envelope + header name. Do not hard-code v1.
  2. Encode validAfter and validBefore as strings. JSON numbers get rejected by at least one public facilitator; strings are accepted by both ends.
  3. Set paymentRequirements to the version's own shape. v2: amount. v1: maxAmountRequired.
  4. Honor the extra:{name, version} field if the 402 accept carries one. If not, fall back to the token's canonical EIP-712 domain by resolved chainId. For Base USDC that is USD Coin / 2 / 8453 / 0x833589f…13.
  5. Refuse to sign on asset-mismatch. If the accept's asset doesn't match the known Circle USDC on a resolved chainId, don't sign — a wrong-verifyingContract signature is a cross-contract-replay vector.
  6. Treat HTTP 401 before the first 402 as a hard failure. The seller is not x402-first for cold callers; a protocol-only buyer cannot proceed.
  7. Validate with /verify before /settle. The verify-only pattern makes every integration dry-run-able at zero cost. Reserve /settle for CI runs on a seller you've already verified against.

Honest limits

Sample size. 4 candidates, 3 attempted. This is the population of Base Transact-ready ERC-8004 agents after the 9 October 2026 readiness update (a cap on bulk publishers and a check for test-style names, described in our post on tightened readiness scoring). It is the whole group we tested, not a random sample. The field-test finding is a lower-bound measurement on a specific population at a specific date; it is not an extrapolation.

Buyer client. We tested with a stock EIP-3009 v1 EVM client. The field-test finding is specifically about cold interoperability; a buyer willing to maintain per-vendor payload adapters, bearer-token bootstrap, and facilitator-specific domain handling can and does clear two of the three failures. The verify-only re-run above is the existence proof.

Chain and network. Base mainnet USDC only. The pilot's hard-coded guard rejects non-Base accepts and non-USDC assets. The finding does not generalise to Solana-first facilitators or non-Circle stablecoins without a separate test run.

CDP coverage. We did not provision a Coinbase CDP API key for this test, so CDP's /verify acceptance is indirect — via payai acceptance of the same v2 envelope shape the CDP TypeScript SDK builds. A direct CDP confirmation is a reasonable follow-up and does not change the buyer-side checklist above.

Methodology / scoring unchanged. This piece is a measurement. It does not change the Readiness or Trust composite, the Transact-ready / Promising / Not ready bucket thresholds, or any published methodology. It also does not re-rank or demote any specific agent — the sellers are anonymised as A / B / C / D so the published finding is about the shape of the gap rather than any individual operator's score.

How we kept the test safe

A dedicated test wallet, a $0.05 limit per request and $5.00 in total (actual spend: $0.00), payment only to the address in each agent's own 402 challenge, no approvals or allowances, no assets other than USDC, and no redirects to other hosts. We did not contact any seller and we do not name any agent.

If you're wiring up x402 as a buyer today

Start with the x402 quickstart, then read the companion Bazaar listing census for the shape of the listed catalog, the client-compatibility census (2026-10-12) for how many live 402 bodies the frozen legacy v1 npm [email protected] actually parses (17.5% of 280) vs what moves to v2 under @x402/[email protected], and ERC-8183 vs ERC-8004 for how identity + payment compose. Our paid /v1/intel/* API joins listing to on-chain identity (publisher, feedback count, counterparty profile) — pay-per-call via x402, no account required. The free /mcp server exposes six read-only tools for pre-payment counterparty checks — including an agent_trust_teaser you can call before you commit to a /settle.

Cite as

Onchain Agent Intel (2026). We tried to pay ERC-8004 agents over x402. 0 of 3 payable Base agents interoperated with a stock v1 client. Buyer-side field test of x402 agent-payments interoperability, 2026-10-11. CC BY 4.0. https://onchainagentintel.io/blog/x402-agent-payment-interop-field-test