x402: HTTP 402 in native USDC
x402 is HTTP 402 Payment Required: a resource answers unpaid requests with a quote, the client signs, and a facilitator settles on chain. No account, no API key, no gas token.
On POA the unit is native USDC, not an ERC-20. Stock ExactEvm would call transferWithAuthorization on Ethereum mainnet USDC (0xa0b86991…) or Permit2. That is the wrong scheme here. The on-chain method is the NativeTransferAuth precompile at 0x2D00…0006, which implements the same EIP-3009-shaped ABI against state.accounts. Permit2 is unused. The facilitator cannot mint. Public GET /faucet stays unpublished.
Public URLs (chain 77)
Section titled “Public URLs (chain 77)”| Surface | URL |
|---|---|
| Demo resource | GET https://poa.net/77/x402/demo — unpaid is HTTP 402 with PAYMENT-REQUIRED |
| Facilitator | GET https://poa.net/77/x402/facilitator/supported |
POST https://poa.net/77/x402/facilitator/verify | |
POST https://poa.net/77/x402/facilitator/settle |
The explorer page is https://poa.net/77/docs/x402. This is not the Agent Gateway (/77/agent/v1) and not the invite faucet (POST /77/agent/v1/faucet).
curl -sS -D - https://poa.net/77/x402/demo -o /tmp/x402-demo.jsonRequirements advertise scheme=exact, network=eip155:77, asset=0x2D00…0006, and extra of assetTransferMethod=eip3009, paymentFlow=authorization, kind=native, EIP-712 name USDC, version 2, 6 decimals.
The 402 JSON body is the quote; the PAYMENT-REQUIRED header is that same JSON in Base64 — use the body. It has resource and accepts. PAYMENT-SIGNATURE is Base64 of this envelope — not the EIP-712 digest and not payload.authorization alone. Copy resource from the 402 as-is. Copy the selected accepts[i] object as accepted. authorization.to must equal accepted.payTo, authorization.value must equal accepted.amount. validAfter / validBefore are unix seconds; keep validBefore within accepted.maxTimeoutSeconds of now. nonce is 32 random bytes. Copy addresses from the 402 as-is; their case may include a checksum. Omitting resource.url or accepted is invalid_payload in the 402 JSON error field (and in PAYMENT-RESPONSE after a failed settle).
{ "x402Version": 2, "resource": { "url": "https://poa.net/77/x402/demo", "mimeType": "application/json", "description": "…" }, "accepted": { "scheme": "exact", "network": "eip155:77", "asset": "0x2d00000000000000000000000000000000000006", "amount": "10000", "payTo": "0x…", "maxTimeoutSeconds": 60, "extra": { "assetTransferMethod": "eip3009", "paymentFlow": "authorization", "kind": "native", "name": "USDC", "version": "2", "decimals": 6, "symbol": "USDC" } }, "payload": { "signature": "0x…", "authorization": { "from": "0x…", "to": "0x…", "value": "10000", "validAfter": "0", "validBefore": "…", "nonce": "0x…" } }}POST /77/x402/facilitator/verify and settle take { "x402Version": 2, "paymentPayload": <envelope>, "paymentRequirements": <accepted> }.
How a wallet pays
Section titled “How a wallet pays”Works today: an EOA that holds native USDC and can EIP-712-sign.
- Hold native USDC on chain 77 (bridge in).
- Sign EIP-712
TransferWithAuthorizationforNativeTransferAuth(name=USDC,version=2,verifyingContract=0x2D00…0006,chainId=77). Amounts are 6-decimal USDC units. - Retry the resource with
PAYMENT-SIGNATUREset to Base64 of the envelope above. The public facilitator at/77/x402/facilitator/*is the same in-process facilitator the demo uses; it broadcaststransferWithAuthorizationfrom a settler key. The demo returns 200 only after the settler tx is included with receipt status0x1. A missing receipt issettlement_pending(402), not success. Worker502/504after settle does not mean the payment failed — reconcile the tx hash /(from, nonce)before signing again. - The same
(from, nonce)cannot settle twice. The operator-pool address (the genesis bridge operator, blocked from ordinary transfers) cannot be the EIP-712from.
Assigned wallets: call POST /77/agent/v1/x402/authorize with an API bearer token that has transfer capability. Send the quote as payment_required and a fresh 32-byte hex nonce; the signer returns the payment authorization. This requires x402 enablement and an operator-approved amount and recipient. The MCP adapter does not wrap this endpoint. See Agent Gateway.
Why a precompile
Section titled “Why a precompile”POA has no token contract. A client pointed at Ethereum mainnet USDC would debit the wrong chain. NativeTransferAuth is a closed precompile in the 0x2D00… set, same model as HTLC and bridge mint: Elixir, operator-shipped, no bytecode. Details: Precompiles.