Skip to main content
A payment seal struck per request, verified and settled on GIWA x402 is an open payment protocol that activates the HTTP 402 Payment Required status code. A server answers an unpaid request with a 402 and a machine-readable payment requirement; the client signs a payment authorization and retries; a facilitator verifies the signature and settles it on-chain. The protocol is chain-agnostic, with requirements keyed by CAIP-2 network IDs such as eip155:91342, and is governed by the x402 Foundation under the Linux Foundation, initiated by Coinbase. Two EVM schemes matter here:
  • exact: settle one fixed amount. With an ERC-3009 asset, the facilitator calls transferWithAuthorization directly on the token.
  • upto: authorize a signed maximum, settle the actual measured amount. In x402-rs this scheme is Permit2-only, signing a PermitWitnessTransferFrom for a fixed Upto proxy address, because an ERC-3009 authorization fixes its amount at signing time.

Why self-hosted on GIWA

GIWA does not officially support x402, and Coinbase’s hosted facilitator does not list GIWA. Tokscale ported the stack and answered the hardest open question, whether x402 works on GIWA at all, on the public chain. Three pieces make it work:
  1. Pinned self-hosted facilitator: ghcr.io/x402-rs/x402-facilitator@sha256:89ab5c03…, mapped to x402-rs 2.0.2 revision 0b14f39a. The image refused to start for eip155:91342 until two hardcoded startup-check contracts existed on the chain, so Tokscale deployed them: the canonical Exact Permit2 Proxy and the ERC-6492 UniversalSigValidator, both at their canonical CREATE2 addresses.
  2. Canonical Permit2 proxies: upto hardcodes the Upto proxy address in x402-rs, so no substitute deployment is possible. Tokscale deployed the canonical Upto Permit2 Proxy from pinned upstream source and byte-verified it against the x402-rs constants. Permit2 itself (0x000000000022D473030F116dDEE9F6B43aC78BA3) is an OP Stack preinstall whose observed runtime hash matches the pinned rebuild.
  3. An isolated adapter process: the workspace is on axum 0.7.9, while x402-rs 2.0.2 is built on axum 0.8, so linking it in would force a framework upgrade across every crate. Instead the adapter is a standalone process outside the workspace, hand-written against three dependencies (base64, serde_json, sha2), and it speaks to the pinned facilitator image over HTTP. The gateway reaches it over a bearer-authenticated local JSON interface (POST /v1/verify, /v1/settle, /v1/recover). No x402-rs crate is linked anywhere in the repository and no x402-rs type crosses the seam, so the adapter is the only component that talks to the facilitator, the chain RPC, and the settlement journal.
Every contract above is Tokscale-operated public infrastructure on GIWA Sepolia, verifiable in the explorer and listed in The Public Chain.

The 402 flow

When a request arrives with x-giwa-payment-mode: x402 but no payment signature, the gateway fails closed to HTTP 402.
1

Quote a body-aware maximum

The gateway computes the maximum from the canonical request bounds and the sealed catalog price. The quote query is side-effect free: an upto challenge never creates a payment intent before its authorization verifies.
2

Return the 402 challenge

The response carries the quote and a freshly issued expiry of 60 seconds. A native 402 writes nothing durable.
3

Accept the signed retry

The client retries with a signed PAYMENT-SIGNATURE header. The gateway rebinds to the originally issued expiry carried inside the signature, because recomputing from the wall clock would derive a different Permit2 nonce. Stale or extended expiries are rejected with a fresh 402 rather than silently repriced, and only then does the gateway verify through the adapter.
4

Persist the authorization

Only after a successful verify does the gateway write the intent, outbox, and immutable payment authorization in one transaction.
For the exact challenge payload and the five error categories the boundary can return, see Gateway API.

Two stages, two schemes

The same ported stack carries both payment models, and they exist for different reasons: The design rule shared by both: a token transfer is never treated as payment unless it matches an already persisted intent. ERC-3009 itself warns that a public transferWithAuthorization can be front-run when an application needs a wrapper-specific action, so an ordinary transfer to the treasury credits nothing. The full mechanics live on one page each: the intent state machine and the exactly-once credit rule in Stage A: Credit Top-Up, and the request binding, the settlement journal, and response-loss recovery in Stage B: Per-Request Settlement. Public proof for Stage A (GIWA Sepolia, 2026-07-23): the pinned facilitator advertised exact for eip155:91342, rejected a mismatched chain, asset, and tampered signature at /verify, settled one 1.0 tUSD authorization (tx 0xad1a2f7b…fcb9f8), and rejected a replay of the same authorization with the ERC-3009 authorization-used selector.
On public GIWA Sepolia the canonical Upto proxy is deployed and byte-verified, but public upto facilitator advertisement and settlement remain open gates. Every upto proof is local-topology evidence, not public-chain proof.

Preventing a double settlement

Stage B is defended three times over, at three different layers, so no single failure can produce two payments:
  • On-chain: the Permit2 unordered nonce is derived from the request binding digest, so a second settle for the same request reverts against the nonce bitmap.
  • In the adapter process: an append-only journal records a prepared entry before the sole settlement side effect. If a prepared entry exists without a transaction hash, the adapter refuses to broadcast again and recovers read-only instead.
  • In the database: admission is idempotent, and finalize is fenced by both a lease and the transaction hash.
The same discipline governs Stage A from the other direction: the reconciler never sends a transaction at all, so recovery cannot duplicate a payment even in principle.

What the gateway stores

The gateway never holds a payer private key and never broadcasts. After a successful verify it stores only the admission record: intent and project IDs, request fingerprint, network, asset, treasury, payer, authorization nonce, maximum amount, the adapter’s payment commitment hash, and the opaque signed header. No prompt, completion, or key material. The adapter token renders as <redacted> in debug output, and presented API keys are redacted at the execution boundary.

Evidence

Two test-only overlays inject real failures into the sealed localnet. The first kills the reconciler after a real EIP-3009 settlement lands but before it observes the candidate, then force-recreates it. The proof is exactly one credit, exactly one canonical settlement, and a same-value ordinary transfer that was not credited:
The second drops the adapter’s settle response after a real on-chain settlement. The leased recovery worker resolves the stranded payment from chain evidence, a mined receipt plus decoded settle calldata, never by rebroadcasting:

Next steps