x402 on Elysium
Quaestor runs an x402 facilitator for Elysium. x402's usual exact scheme on EVM chains pays with EIP-3009 transferWithAuthorization. The bridged USDC on Elysium has EIP-2612 permit but no EIP-3009, so this facilitator uses its own scheme, exact-permit. Testnet only in this release.
The scheme
The payer signs two EIP-712 messages:
- Permit on the token's own domain:
owner = payer,spender = settler,value = price, the token's currentnonces(owner),deadline. - Payment on the settler's domain (
name "Quaestor x402",version "1", chain id, settler address):
Payment(address token,address from,address payTo,uint256 value,uint256 fee,
bytes32 resource,bytes32 nonce,uint256 validAfter,uint256 validBefore)
resource is keccak256(resource URL). nonce is 32 random bytes, used once per payer.
X402PermitSettler.settle(payment, paymentSig, permit) checks the Payment signature (the contract accepts EOA and ERC-1271 signatures; this release's facilitator verifies EOA signatures), marks the nonce used, submits the permit (a permit someone already submitted is fine), then moves value - fee from payer to payTo and fee to the settler's fixed fee recipient, in the same transaction. The settler is ownerless and never holds a balance. A relayer cannot redirect a payment: payTo, amount and fee are inside the payer's signature.
Requirements (the 402 body)
{
"x402Version": 1,
"error": "X-PAYMENT header is required",
"accepts": [{
"scheme": "exact-permit",
"network": "elysium-testnet",
"maxAmountRequired": "2500000",
"resource": "https://api.quaestor.fun/v1/market/signals/12/buy",
"description": "Sealed signal #12",
"mimeType": "application/json",
"payTo": "0xSeller",
"maxTimeoutSeconds": 120,
"asset": "0xUSDC",
"extra": { "settler": "0xSettler", "fee": "0", "feeRecipient": "0x...", "tokenName": "USD Coin", "tokenVersion": "2", "chainId": 99801 }
}]
}
maxAmountRequired is the exact price. extra.fee is the part of it that goes to the fee recipient; third-party services set "0".
Paying
The X-PAYMENT header is base64 JSON:
{ "x402Version": 1, "scheme": "exact-permit", "network": "elysium-testnet",
"payload": { "authorization": { "token": "...", "from": "...", "payTo": "...", "value": "...", "fee": "...",
"resource": "0x...", "nonce": "0x...", "validAfter": "0", "validBefore": "..." },
"signature": "0x...", "permit": { "deadline": "...", "signature": "0x..." } } }
From code, x402Fetch(url, { account, publicClient, maxAmount }) in the SDK does all of it: reads the 402, refuses prices above maxAmount, signs both messages and retries. The response carries X-PAYMENT-RESPONSE with the settlement transaction.
Charging
Put any handler behind a payment with the engine's x402Gate(paymentHeader, requirements, facilitator, handler), or withX402() for a plain Node server. It verifies, runs the handler, settles, and only then sends the response. With a remote facilitator use new HttpFacilitator("https://api.quaestor.fun/v1/x402").
| Facilitator call | Body | Returns |
|---|---|---|
POST /v1/x402/verify |
{ x402Version, paymentPayload, paymentRequirements } |
{ isValid, invalidReason?, payer? } |
POST /v1/x402/settle |
same | { success, errorReason?, transaction, network, payer? } |
GET /v1/x402/supported |
{ kinds: [{ x402Version, scheme, network, extra }] } |
Verify checks scheme and network, that amount, payee, fee, asset, settler and resource match the requirements, the time window, both signatures, the balance and the nonce, and finally simulates settle. The relayer pays gas in HYPE.
Directory
GET /v1/x402/directory lists paid services on Elysium. POST /v1/x402/directory { url, title, description } adds one, but only after Quaestor calls the URL and gets a 402 with an exact-permit offer on this network that settles through this facilitator. Only public https URLs are accepted. Every listed service is re-checked hourly and shown as answering, down or changed, with how many payments it settled here.