Back to browse
We put ZK attribute proofs inside x402 payment headers

We put ZK attribute proofs inside x402 payment headers

by aggre·Apr 28, 2026·2 points·1 comment

AI Analysis

●●SolidBig BrainBold Bet

ZK proofs inside x402 headers solve the anonymous wallet problem for AI agents.

Strengths
  • Binds document oracle proofs to on-chain Merkle commitments in a single round trip.
  • Live implementation on Base Sepolia with verifiable issuer identity bundles.
Weaknesses
  • Depends entirely on x402 adoption, which remains speculative infrastructure.
  • Complexity of ZK verification may limit usage to high-value agent transactions.
Target Audience

Backend developers building agentic payment systems

Similar To

Lemma · x402 · EIP-3009

Post Description

Every x402 settlement in this repo carries a ZK proof bundle in PAYMENT-RESPONSE: issuer identity, payment settlement, and data integrity, independently verifiable. Live on Base Sepolia.

(Recap: x402 is Coinbase's revival of HTTP 402. Server returns 402, client signs an EIP-3009 USDC auth on Base, retries with PAYMENT-SIGNATURE, facilitator settles. Spec: https://x402.org)

I'm the CTO of FRAME00. We've been building Lemma, a document oracle that binds ZK attribute proofs to on-chain Merkle commitments. Three weeks ago I started asking whether the same proof bundle could ride inside an x402 round trip instead of a separate verification step. This repo is the answer.

The gap x402 leaves: the server gets a wallet address and a tx hash. It doesn't know who authorized the payment, under what policy, or whether the data arrives intact. As agents become the payer, a wallet address is an anonymous primitive, not a principal.

What this adds to the x402 flow:

Phase 1 Agent hits any x402-protected endpoint with @x402/fetch. -> standard 402 with accepts[]. Nothing Lemma-specific. Phase 2 Wallet signs EIP-3009 USDC auth, retries with PAYMENT-SIGNATURE, facilitator settles. -> PAYMENT-RESPONSE carries extensions.lemma = { proof, inputs, circuitId, generatedAt }. A registered x402 extension, not a sidecar. Phase 3 Agent checks SHA-256(body) against attributes.integrity in the proof. No round trip. Phase 4 POST /query for BBS+ selective disclosure. Released only when the caller's x402 payment satisfies condition.circuitId = "x402-payment-v1" -- today this is API-level access gating; the binding is moving into the BBS+ challenge itself (see below).

The demo wraps Phase 1 in a free GET /article returning an X-Lemma-Attestation header pointing at /verify/:hash. Point @x402/fetch at any paid resource directly and Phase 1 is just standard 402.

Server side is a drop-in for @x402/hono:

import { paymentMiddleware, x402ResourceServer, ExactEvmScheme } from "@lemmaoracle/x402";

const server = new x402ResourceServer(facilitatorClient) .register("eip155:84532", new ExactEvmScheme()); app.use("*", paymentMiddleware(routes, server));

paymentMiddleware auto-attaches a hook that writes extensions.lemma into PAYMENT-RESPONSE. Route handlers don't change.

Agent side uses stock @x402/fetch; no Lemma SDK on the client:

const x402Fetch = wrapFetchWithPayment(fetch, client); const res = await x402Fetch(`${WORKER_URL}/example/verify/${hash}`); const settle = JSON.parse(atob(res.headers.get("PAYMENT-RESPONSE"))); // settle.extensions.lemma = { proof, inputs, circuitId }

What this doesn't claim:

* Data source is not on-chain. We bind SHA-256 of the body to a chain commitment; not authorship. * The issuer's BBS+ key is the trust anchor. Identity, settlement, and integrity proofs are independent. * Facilitator is a liveness dependency (x402 design). Fail-closed. Swap or self-host any x402-compatible one.

What is shipping next:

* Agent-side identity. did:key -> agentId with role, scope, spendLimit. Lifts the paying wallet from anonymous primitive to verifiable principal. * Cryptographic settlement binding. Today condition.circuitId is enforced at the API layer; the BBS+ proof itself verifies offline once obtained. We are folding the x402 settlement record into the BBS+ challenge so re-use without a fresh payment becomes infeasible at the proof layer.

Both are on-axis with the thesis: payment is the trigger; verifiable trust rides on top.

Repo: https://github.com/lemmaoracle/example-x402 x402 SDK: https://www.npmjs.com/package/@lemmaoracle/x402 Lemma SDK: https://www.npmjs.com/package/@lemmaoracle/sdk

Questions on the circuit layer, BBS+ binding, or DID roadmap welcome.

Similar Projects