Status

What actually runs

Built during Flare Summer Signal, on Coston2. Everything on this page has been run and its output checked, and every claim has a transaction behind it.

The state of each piece

PieceState
Chain probe - resolves FXRP, verifies the EIP-712 domain live Coston2
ScripFacilitator.sol deployed + source-verified live Coston2
settle() end to end, real FXRP, real signatures verified on a fork
Attack coverage - payee substitution, replay, permit grief verified on a fork
Gasless settlement against the deployed facilitator live Coston2
FTSO USD pricing - invoices priced at the live XRP/USD feed live Coston2
x402 facilitator service + Express middleware hosted and public
An agent paying a 402 end to end, holding no gas token pays the hosted facilitator
MCP server - an assistant prices, quotes and pays in conversation runs locally, settles on live Coston2
Payee allowlist - the relayer spends gas only for payees it was configured to serve enforced on the hosted facilitator
A spent invoice is answered with a fresh quote, and the client re-signs working, live Coston2
Invoice ids namespaced per payer - a stranger cannot burn a quote live Coston2
Zero-amount settlements refused live Coston2

Where it runs

The facilitator is public, at scrip-production.up.railway.app. Nothing needs installing to see it work:

curl https://scrip-production.up.railway.app/health
curl https://scrip-production.up.railway.app/price
curl -i https://scrip-production.up.railway.app/api/haiku

The last one answers 402 Payment Required with a price in USD, the FXRP it converts to, the FTSO rate it was derived from, and a single-use invoice id - priced at the moment you ask, and payable for ten minutes.

Open that endpoint in a browser and you get the raw JSON body, which looks like an error page and is not one. A 402 is the server quoting a price rather than refusing to answer: the terms are the response. It reads better through curl -i, where the status line is visible above the body:

HTTP/2 402
content-type: application/json

{
  "x402Version": 1,
  "error": "payment required: $0.25 in FXRP (0.247794 FTestXRP at $1.008904/XRP)",
  "accepts": [{
    "scheme": "exact-permit2612",
    "maxAmountRequired": "247794",
    "priceUsd": "0.25",
    "rate": { "feedId": "0x0158...", "value": "1008904", "decimals": 6 },
    "payTo": "0xaA34e14a0e0B2fdD8Ad10F06bC0907fA0b1D02Bd",
    "asset": "0x0b6A3645c240605887a5532109323A3E12273dc7",
    "invoiceId": "0x98913e13...",
    "deadline": "1786655791"
  }]
}

Everything needed to pay is in there, and the rate is included so a client can recompute the FXRP amount from the USD price and refuse if the two disagree. The agent in this repository does exactly that before it signs anything.

To pay one, clone the repository and point the agent at the hosted endpoint:

npm run agent -- https://scrip-production.up.railway.app/api/haiku

The payments that actually happened

Transactions on live Coston2, all paid for by the relayer, all from a payer whose C2FLR balance was zero before and after. These are the receipts behind every claim on this site.

WhatResult
Direct settlement, 0.5 FXRP invoice 0x4bea1e37 · block 33961376 · 222,790 gas
Agent paying a $0.25 x402 invoice 0x975a5ac6 · block 33961951 · 205,702 gas
Direct settlement, 0.1 FXRP invoice 0x1e512e96 · block 33962211 · 205,698 gas
An assistant paying $0.25 through the MCP pay tool 0xeeef2e1d · block 34018086 · 205,698 gas
An agent paying the hosted facilitator 0xe3cb0532 · block 34022538 · 205,722 gas
A payment under the current contract, invoice namespaced per payer 0x10ff52e5 · block 34035592 · 206,561 gas

The first payment costs about 17,000 more gas than the ones after it. That is not noise: it is the payer's EIP-2612 nonce slot going from zero to one, which is a cold storage write the first time and a warm one forever after. The steady-state figure is the one quoted on the home page.

402 payment required
  price              $0.25
  amount             0.244356 FTestXRP
  XRP/USD            $1.023099
  PASS  quoted amount matches the quoted rate
  PASS  intent digest agrees with the facilitator

signed two messages, sent no transaction

200 OK
  delivered          0.244356 FTestXRP
  gas paid by        0xaA34e14a0e0B2fdD8Ad10F06bC0907fA0b1D02Bd
  payer C2FLR        0 -> 0

  PASS  the agent paid for an API call holding no gas token at all

What has been verified, and how

npm run test:fork forks live Coston2, deploys the facilitator onto the fork, and settles a real invoice against the real FXRP contract - the deployed vendored FAsset, resolved through AssetManagerFXRP.fAsset(), not a mock. Each property below is asserted, and the attacks are run as attacks.

attack: relayer substitutes itself as payee
  PASS  payee substitution rejected with IntentNotSignedByPayer

settle
  PASS  delivered == requested (1500000 == 1500000)
  PASS  payer native balance still 0 - the payment was gasless
  PASS  relayer paid the gas

replay: same invoice again
  PASS  replay rejected with AlreadySettled

front-runner replays the permit directly to FXRP
  PASS  front-runner consumed the nonce (3 -> 4)
  PASS  settle() still succeeded after the permit was front-run
How the payer is funded on the fork.

The token is the real deployed FAsset, and the signatures are real. The payer's balance is written directly into the token's balance mapping, because minting FAssets legitimately requires an XRP payment proof that no test can produce - so the fork exercises the contract logic and the signing path against the genuine token. The funding route itself is covered live instead: the payments above are on Coston2, from a payer holding FXRP it was actually sent.

What comes next

Each of these is a known piece of work with a known shape, listed in the order it would be done.

  1. Concurrent payments from one payer

    EIP-2612 nonces are sequential, so an agent paying two endpoints at once has the second permit fail on a consumed nonce. EIP-3009's random nonces avoid this and FXRP does not implement EIP-3009, so payments are serialised per payer today. The MCP server pays for one resource at a time for the same reason - paying for two means solving this, not calling the tool twice.

  2. Mainnet FXRP

    Everything here is Coston2. The signing path is unchanged on mainnet, but the facilitator would need redeploying and auditing against the real asset.