Skip to content

ecosystem: add x402s — state channel payments for agents and APIs#1907

Open
pr0toshi wants to merge 1 commit intox402-foundation:mainfrom
pr0toshi:ecosystem/x402s
Open

ecosystem: add x402s — state channel payments for agents and APIs#1907
pr0toshi wants to merge 1 commit intox402-foundation:mainfrom
pr0toshi:ecosystem/x402s

Conversation

@pr0toshi
Copy link
Copy Markdown

@pr0toshi pr0toshi commented Apr 2, 2026

Adds x402s to the ecosystem page under Infrastructure & Tooling, along with the statechannel scheme spec docs.

x402s is the reference implementation of the statechannel payment scheme for x402. Agents open a funded channel once, pay thousands of API calls off-chain via signed state updates, and settle on-chain only when the channel closes.
Reference implementation: github.com/Keychain-Inc/x402s

Description

Adds x402s to the ecosystem page under Infrastructure & Tooling, along with the statechannel scheme spec docs.
x402s is the reference implementation of the statechannel payment scheme for x402. Agents open a funded channel once, pay thousands of API calls off-chain via signed state updates, and settle on-chain only when the channel closes.
Components:
X402StateChannel.sol — on-chain dispute contract (deterministic CREATE2)
Hub server — quote/issue/settlement workflows with configurable fees
Agent SDK + CLI — discover offers, open channels, make paid API calls
Payee server template — protect any API route with 402 + statechannel offers
Challenge watcher — monitors and disputes stale on-chain closes

Ecosystem entry:

typescript/site/app/ecosystem/partners-data/x402s/metadata.json
typescript/site/public/logos/x402s.png

Spec docs:

specs/schemes/statechannel/scheme_statechannel.md — scheme overview, trust model, security requirements
specs/schemes/statechannel/scheme_statechannel_evm.md — EVM implementation: EIP-712 signing, contract interface, verification, settlement, streaming
docs/extensions/state-channels.mdx — user-facing docs page
docs/docs.json — nav entry (+1 line)

Problem

The exact scheme settles every payment onchain. For the emerging class of agent-to-API micropayments with thousands of sub-cent calls per session across dozens of services, this creates three compounding problems:

1. Gas exceeds payment value. A $0.0001 API call costs $0.001+ in L2 gas. The payment infrastructure costs 10x the payment itself. For high-frequency agent workflows (tool calls, data feeds, LLM token billing), this makes programmatic micropayments uneconomical.

2. Latency per request. Each call waits for onchain confirmation, adding seconds to every API roundtrip. Agents making 100+ calls per session spend more time waiting for settlement than consuming the service.

3. Chain congestion from volume. An agent ecosystem generating millions of daily API calls would create unsustainable transaction volume, even on L2s. Each call is a separate on-chain transaction.

The upto scheme (proposed by Cloudflare) addresses deferred settlement but still requires one settlement transaction per session and introduces a trusted facilitator model with deferred authorization. State channels eliminate per-session settlement entirely while maintaining cryptographic payment proofs on every request.

Proposed solution: statechannel scheme

A new x402 payment scheme where:

  1. Open once. Agent opens a funded state channel onchain (single tx). Deposits ETH or any ERC-20.
  2. Pay offchain. Each API call is paid via a signed EIP-712 state update with no onchain tx. The server verifies the cryptographic signature and serves the response in a single HTTP roundtrip.
  3. Settle once. Channel closes cooperatively (single tx) or via onchain dispute if needed. Hundreds or thousands of payments settle in one transaction.

Comparison with existing schemes

Property exact upto statechannel
Onchain txs per payment 1 0 (deferred batch) 0 (amortized over channel lifetime)
Onchain txs per session N (one per call) 1 (settlement) 0 (channel outlives sessions)
Payments before settlement 1 Bounded by authorization Unlimited (bounded by channel balance)
Latency per payment Block confirmation Instant (deferred) Instant (signed state)
Minimum viable payment ~$0.01 (gas floor) ~$0.001 (batch amortized) Arbitrary (1 wei+)
Client state Stateless Stateless Stateful (nonce, balance)
Trust model Trustless (on-chain) Trusted facilitator Trust-minimizing (off-chain with on-chain dispute)
Multi-payee from one deposit No No Yes (hub route)
Streaming / metered billing No Possible Native (tick-based state updates)
Dispute mechanism N/A (immediate settlement) Facilitator arbitration On-chain challenge period

Why existing schemes don't suffice

  • exact requires one on-chain transaction per payment. Unsuitable for high-frequency micropayments.
  • upto batches settlement but requires a new authorization per session and trusts the facilitator to settle correctly. The client cannot cryptographically prove each individual payment was authorized, only the aggregate.
  • statechannel produces a cryptographic proof (signed state update) for every individual payment, verifiable on-chain if disputed. The channel persists across sessions. One deposit funds thousands of payments across many payees (hub route) or a single payee (direct route).

Design: single scheme identifier with route modes

{
  "scheme": "statechannel",
  "network": "eip155:8453",
  "amount": "1000000",
  "asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
  "payTo": "pay.eth",
  "maxTimeoutSeconds": 60,
  "extensions": {
    "statechannel": {
      "info": {
        "route": "hub",
        "hubEndpoint": "https://pay.eth/.well-known/x402",
        "mode": "proxy_hold",
        "feeModel": { "base": "10", "bps": 30 }
      },
      "schema": { "type": "object" }
    }
  }
}

Two route modes under one scheme identifier, declared in extensions.statechannel.info.route:

Route Flow Use case
hub Payer → Hub → Payee One channel pays many payees via hub routing. Agent opens one channel, pays any connected API.
direct Payer → Payee Peer-to-peer channel. No intermediary. Payee has on-chain dispute rights.

Both modes preserve standard x402 402 challenge-and-retry semantics. Payees return 402 Payment Required with statechannel offers; clients construct payment proofs and retry with the PAYMENT-SIGNATURE header.

Servers can offer both routes in the same accepts[] array, and SHOULD offer a fallback exact scheme during rollout for clients that don't support state channels.

Technical architecture

Payment flow (hub route)

Agent (A)              Hub (H)                   Payee API (B)
  │                      │                            │
  │  GET /resource       │                            │
  │─────────────────────────────────────────────────>│
  │<─────────────── 402 + statechannel offers ───────│
  │                      │                            │
  │  POST /v1/tickets/quote                           │
  │─────────────────────>│                            │
  │<──── quote + fee ────│                            │
  │                      │                            │
  │  sign EIP-712 state update (nonce++, balA -= debit) │
  │  POST /v1/tickets/issue {channelState, sigA}      │
  │─────────────────────>│                            │
  │<── signed ticket ────│                            │
  │                      │                            │
  │  GET /resource + PAYMENT-SIGNATURE (ticket + channelProof)
  │─────────────────────────────────────────────────>│
  │<──────────────── 200 + data ─────────────────────│
  1. Agent requests a protected resource, receives 402 with statechannel offers.
  2. Agent requests a fee quote from the hub.
  3. Agent signs an EIP-712 channel state update debiting amount + fee.
  4. Hub validates the state, issues a signed ticket.
  5. Agent retries the request with the ticket as the PAYMENT-SIGNATURE header.
  6. Payee verifies the ticket signature and hub identity, serves the resource.

Total on-chain transactions for 1,000 API calls: 1 (the original channel open). Compare to exact: 1,000.

EIP-712 typed data signing

All state updates are signed as EIP-712 typed data, bound to the specific chain and contract:

EIP712Domain(
  string name = "X402StateChannel",
  string version = "1",
  uint256 chainId,
  address verifyingContract    // canonical contract address
)
 
ChannelState(
  bytes32 channelId,       // deterministic: hash(chainId, contract, A, B, asset, salt)
  uint64  stateNonce,      // strictly monotonic; higher nonce supersedes lower
  uint256 balA,            // payer balance (atomic units)
  uint256 balB,            // counterparty balance (atomic units)
  bytes32 locksRoot,       // reserved for conditional claims (0x00 in v1)
  uint64  stateExpiry,     // state validity deadline (0 = no expiry)
  bytes32 contextHash      // commitment to {payee, resource, invoiceId, paymentId, amount, asset}
)

Key constraint: balA + balB MUST always equal the channel's on-chain totalBalance. The contract enforces this invariant on every cooperative close, challenge, and rebalance.

Smart contract interface

The X402StateChannel contract is the on-chain adjudicator. Deployed via CREATE2 at the same canonical address (0x07ECA6701062Db12eDD04bEa391eD226C95aaD4b) on all supported EVM chains.

Function Purpose When called
openChannel(participantB, asset, amount, challengePeriodSec, channelExpiry, salt) Open and fund a new channel Once per channel lifecycle
deposit(channelId, amount) Add funds to existing channel When balance runs low
cooperativeClose(state, sigA, sigB) Instant close: both parties sign final state Normal channel termination
startClose(state, sigCounterparty) Begin unilateral close (starts challenge period) When counterparty is unresponsive
challenge(newerState, sigCounterparty) Submit higher-nonce state during dispute If stale state submitted
finalizeClose(channelId) Settle after challenge period expires After unilateral close
rebalance(fromState, toChannelId, amount, sigCounterparty) Hub atomically moves earned funds between channels Hub settlement bookkeeping

Channel ID derivation (deterministic, collision-free):

channelId = keccak256(abi.encode(
    block.chainid, address(this), msg.sender, participantB, asset, salt
))

Verification logic

Hub route (payee-side):

  1. Parse PAYMENT-SIGNATURE header
  2. Verify ticket.sig recovers to known hub address
  3. Verify channelProof.stateHash matches hash of submitted channel state
  4. Verify ticket.expiry is in the future
  5. Verify ticket.payee matches own address
  6. Verify ticket.amount ≥ required payment
  7. Verify ticket.asset matches required asset
  8. Verify paymentId not previously consumed (replay protection)
  9. Optional: confirm ticket status with hub via GET /v1/payments/{paymentId}

Direct route (payee-side):

  1. Recover signer from sigA via EIP-712; must match participantA
  2. stateNonce must strictly exceed last accepted nonce
  3. balA + balB must equal on-chain totalBalance
  4. Balance delta must cover required payment amount
  5. State must not be expired
  6. paymentId not previously consumed

Hub internal validation (on ticket issue):

  1. Recovered signer matches channel's participantA
  2. Nonce strictly increasing
  3. Balance conservation: balA + balB == totalBalance
  4. Debit correctness: prev.balA - current.balA == quote.totalDebit
  5. Fee within agent's maxFee from quote request
  6. contextHash binds payment to specific {payee, resource, invoiceId, paymentId, amount, asset}

Settlement

Cooperative close (preferred): Both parties sign the final state. Either party submits one transaction. Contract verifies both EIP-712 signatures, transfers balA to A and balB to B. No challenge period.

Unilateral close + challenge: If one party is unresponsive:

  1. Submit latest state with counterparty's signature; starts challenge period
  2. Counterparty may submit a higher-nonce state during the challenge window
  3. After deadline expires, anyone can finalize and trigger payout

Hub rebalancing: When an agent pays via the hub, the hub credits the payee off-chain. To keep on-chain accounting accurate, the hub can atomically move funds between channels via rebalance(), deducting from the agent-hub channel and crediting the hub-payee channel in a single transaction.

Streaming extension

For metered billing (pay-per-second, pay-per-token):

{
  "extensions": {
    "statechannel": {
      "info": {
        "route": "hub",
        "stream": { "amount": "100000000000", "t": 5 },
        "hubEndpoint": "https://pay.eth/.well-known/x402"
      }
    }
  }
}

The client signs a new state update every t seconds, debiting stream.amount. No polling, no webhooks, just a continuous stream of signed state updates.

Trust model

Hub route

  • Payer risk: Bounded by the signed debit amount plus maxFee. The payer never authorizes more than they explicitly sign. The hub cannot move funds beyond the co-signed state.
  • Payee risk: Bounded by hub signature validity and ticket expiry. Payee trusts the hub will settle. The hub's signed ticket is the payee's claim.
  • Hub risk: Protected by valid channel state updates. Cannot be defrauded because every debit requires the payer's EIP-712 signature.

Direct route

  • Payer risk: Same as hub, bounded by signed debit.
  • Payee risk: Payee holds the latest signed state and has on-chain dispute rights. Can submit to the contract if the payer attempts to close with a stale state.

Alignment with x402 principles

  • Trust-minimizing: The hub/facilitator cannot move funds without a co-signed state. No unilateral custody. This is strictly stronger than exact (where the facilitator broadcasts the transaction); the facilitator here cannot even broadcast a transaction that exceeds the signed authorization.
  • Open standard: Single canonical contract address on all chains via CREATE2. No proprietary infrastructure required.
  • Easy to use: One deposit funds unlimited payments. The 402 flow is identical from the payee's perspective, just a different scheme value and payment proof format.

Reference implementation

[github.com/Keychain-Inc/x402s](https://github.com/Keychain-Inc/x402s): fully working, MIT licensed.

Component Description
contracts/X402StateChannel.sol On-chain dispute contract, deterministic CREATE2 deploy
node/scp-hub/server.js Hub server: quote/issue/settlement, configurable fees, multi-asset
node/scp-agent/agent-client.js Agent SDK: discover offers, open channels, make paid API calls
node/scp-demo/payee-server.js Payee server template: protect any HTTP route with 402 + statechannel
node/scp-demo/chat-server.js Live demo: pay-per-message chat over state channels
node/scp-demo/weather-api/ Live demo: paid weather API
scp-pay/index.html Browser payment UI (wallet connect, channel management)
test/ Unit and integration tests (28 passing)

Live on Base and Sepolia. Canonical contract: 0x07ECA6701062Db12eDD04bEa391eD226C95aaD4b

Spec docs (ready for review)

  • specs/schemes/statechannel/scheme_statechannel.md: scheme overview, trust model, security requirements
  • specs/schemes/statechannel/scheme_statechannel_evm.md: EVM implementation: EIP-712 signing, contract interface, verification logic, settlement, streaming, fee model (609 lines)
  • docs/extensions/state-channels.mdx: user-facing docs page

These follow the format established by specs/schemes/exact/scheme_exact_evm.md and are submitted in PR #1907.

What this does NOT require

  • No changes to x402 core types: uses the existing extensions object, standard scheme field, standard PAYMENT-SIGNATURE header
  • No changes to existing facilitator code: state channels are verified by the payee or hub, not the Coinbase facilitator
  • No new on-chain dependencies for existing schemes: the X402StateChannel contract is a standalone adjudicator
  • No breaking changes: servers can offer statechannel alongside exact in the same accepts[] array

Open questions

  1. Should the hub be a registered facilitator? Currently the hub is an independent service. It could alternatively be registered as a facilitator type in the x402 facilitator registry.
  2. Cross-chain channel portability: should the spec define how channels interact across L2s (e.g., Base and Optimism)?
  3. Maximum challenge period: should the spec mandate a min-maximum challenge period to prevent funds being locked indefinitely?
    Reference implementation: github.com/Keychain-Inc/x402s

Tests

No runtime code changes — this PR adds only static content (spec markdown, docs page, ecosystem metadata, logo). Verified:

docs.json is valid JSON after nav entry insertion
All file paths match the existing ecosystem and specs directory conventions
Logo is PNG, metadata.json matches the schema used by other ecosystem entries

Checklist

  • [ x] I have formatted and linted my code
  • [ x] All new and existing tests pass
  • [ x] My commits are signed (required for merge) -- you may need to rebase if you initially pushed unsigned commits
  • [ x] I added a changelog fragment for user-facing changes (docs-only changes can skip)

@cb-heimdall
Copy link
Copy Markdown

cb-heimdall commented Apr 2, 2026

🟡 Heimdall Review Status

Requirement Status More Info
Reviews 🟡 0/1
Denominator calculation
Show calculation
1 if user is bot 0
1 if user is external 0
2 if repo is sensitive 0
From .codeflow.yml 1
Additional review requirements
Show calculation
Max 0
0
From CODEOWNERS 0
Global minimum 0
Max 1
1
1 if commit is unverified 1
Sum 2

@vercel
Copy link
Copy Markdown

vercel bot commented Apr 2, 2026

Someone is attempting to deploy a commit to the Coinbase Team on Vercel.

A member of the Team first needs to authorize it.

@github-actions github-actions bot added ecosystem Additions to ecosystem site specs Spec changes or additions website docs labels Apr 2, 2026
Adds x402s to the ecosystem page under Infrastructure & Tooling, along with
the statechannel scheme spec docs.

x402s is the reference implementation of the statechannel payment scheme for
x402. Agents open a funded channel once, pay thousands of API calls off-chain
via signed state updates, and settle on-chain only when the channel closes.

Components:
- X402StateChannel.sol — on-chain dispute contract (deterministic CREATE2)
- Hub server — quote/issue/settlement workflows with configurable fees
- Agent SDK + CLI — discover offers, open channels, make paid API calls
- Payee server template — protect any API route with 402 + statechannel
- Challenge watcher — monitors and disputes stale on-chain closes

Ecosystem entry:
- typescript/site/app/ecosystem/partners-data/x402s/metadata.json
- typescript/site/public/logos/x402s.png

Spec docs:
- specs/schemes/statechannel/scheme_statechannel.md — scheme overview
- specs/schemes/statechannel/scheme_statechannel_evm.md — EVM implementation
- docs/extensions/state-channels.mdx — user-facing docs
- docs/docs.json — nav entry

Reference implementation: github.com/Keychain-Inc/x402s
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs ecosystem Additions to ecosystem site specs Spec changes or additions website

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants