x402 Scheme

MARC Protocol's integration with the HTTP 402 payment standard.

Overview

The x402 standard enables machine-to-machine payments over HTTP. When a server requires payment, it responds with HTTP 402 Payment Required and a structured body describing accepted payment methods. MARC Protocol registers the scheme fhe-confidential-v1.

Scheme Identifier

fhe-confidential-v1

Chain: Ethereum Sepolia (11155111) | Token: USDC (6 decimals)

402 Response Format

When the server receives a request without a valid Payment header, it responds 402 with:

FhePaymentRequiredjson
{
  "x402Version": 1,
  "accepts": [
    {
      "scheme": "fhe-confidential-v1",
      "network": "eip155:11155111",
      "chainId": 11155111,
      "price": "1000000",
      "asset": "USDC",
      "tokenAddress": "0xE944754aa70d4924dc5d8E57774CDf21Df5e592D",
      "verifierAddress": "0x4503A7aee235aBD10e6064BBa8E14235fdF041f4",
      "recipientAddress": "0xSERVER_WALLET"
    }
  ]
}

Payment Header

After making the on-chain payment, the client retries with a base64-encoded Payment header:

Payment header (decoded)json
{
  "scheme": "fhe-confidential-v1",
  "txHash": "0x...",           // confidentialTransfer TX
  "verifierTxHash": "0x...",   // recordPayment TX
  "nonce": "0x...",            // unique nonce
  "from": "0x...",             // payer address
  "chainId": 11155111
}

Full Payment Flow

1

Agent A sends GET /api/data to Agent B's server

2

Server responds 402 with FhePaymentRequired body

3

Agent A encrypts payment amount: input.add64(amount).encrypt()

4

TX 1: cUSDC.confidentialTransfer(to, handle, inputProof)

5

TX 2: verifier.recordPayment(payer, server, nonce, minPrice)

6

Agent A retries with base64 Payment header containing tx hashes

7

Server verifies both events on-chain (ConfidentialTransfer + PaymentVerified)

8

Server responds 200 with data

Server Verification Checklist

The fhePaywall middleware performs these checks automatically:

  1. Scheme matches fhe-confidential-v1
  2. Chain ID matches server's expected chain
  3. Nonce is fresh (not seen before)
  4. ConfidentialTransfer event exists in txHash receipt (from + to match)
  5. PaymentVerified event exists in verifierTxHash receipt
  6. minPrice in the event >= server's required price
  7. Block confirmations >= minConfirmations
  8. Payment header size < 100KB

Facilitator Server

MARC Protocol includes a facilitator server compatible with the x402 facilitator specification:

facilitator.tstypescript
import { createFacilitatorServer } from "marc-protocol-sdk";

const app = await createFacilitatorServer({
  tokenAddress: "0xE944754aa70d4924dc5d8E57774CDf21Df5e592D",
  verifierAddress: "0x4503A7aee235aBD10e6064BBa8E14235fdF041f4",
  rpcUrl: "https://sepolia.infura.io/v3/YOUR_KEY",
  apiKey: process.env.API_KEY,
});

app.listen(3001);

// Endpoints:
// GET  /info    — scheme info + contract addresses
// POST /verify  — verify ConfidentialTransfer + PaymentVerified events
// GET  /health  — health check

Wire Format Types

interface FhePaymentRequired {
  x402Version: number;
  accepts: FhePaymentAccept[];
}

interface FhePaymentAccept {
  scheme: "fhe-confidential-v1";
  network: string;         // "eip155:11155111"
  chainId: number;
  price: string;           // USDC in 6-decimal units
  asset: string;           // "USDC"
  tokenAddress: string;    // ConfidentialUSDC
  verifierAddress: string; // X402PaymentVerifier
  recipientAddress: string;
}

interface FhePaymentPayload {
  scheme: "fhe-confidential-v1";
  txHash: string;
  verifierTxHash: string;
  nonce: string;
  from: string;
  chainId: number;
}