RH402 Docs

RH402 documentation

RH402 is a payment layer for USDG on Robinhood Chain (chain id 4663). You use it with the wallet you already have (MetaMask, Rabby, OKX, Coinbase Wallet, any injected wallet). A username such as @ada is optional: an ERC-721 token whose owner receives every payment sent to that name. Sending is gasless for you: RH402 keeps your wallet topped up with the ETH it needs.

Your wallet, no gas

Connect a wallet at rh402.xyz/app. The app adds Robinhood Chain (chain id 4663) to the wallet if it is missing. You keep your keys and sign every transaction yourself; RH402 only makes sure the gas is there.

Before each transaction the app calls POST /v1/gas/drip with the exact transaction it is about to send. RH402 simulates that transaction from your wallet (it must be an RH402 or USDG call that would succeed, so a wallet with nothing to spend gets nothing), computes the gas it needs, and sends only the part your wallet is missing, capped at 0.00005 ETH. A wallet can therefore never hold more than one transaction's worth of gas from RH402, which makes farming pointless. Top-ups are also limited per wallet and per network, and the whole platform has a daily gas budget.

The first payment needs two confirmations in your wallet (a one-time USDG allowance for the router, then the payment). After that, one confirmation per payment.

Agent accounts (EIP-7702)

For servers, bots and AI agents that hold their own key, RH402 offers a fully relayed path. USDG on Robinhood Chain has no permit and no transferWithAuthorization, so the agent's address is upgraded instead: the first relayed transaction carries an EIP-7702 authorization that delegates the address to RH402Account. From then on:

  • Every action is an EIP-712 intent: Execute(Call[] calls, uint256 nonce, uint256 deadline) signed by the account key. The domain is {name:"RH402Account", version:"1", chainId:4663, verifyingContract:<the account address>}.
  • Anyone may submit an intent; only the account's own key can produce a valid signature. There are no spending limits and no third-party keys.
  • The relayer simulates first, refuses calls to contracts outside RH402 and USDG, and rate-limits per account and IP to protect its gas.
  • The account still works as a normal EOA. Funds never move without the key.
  • Browser wallets do not sign third-party 7702 authorizations, which is why the app uses the gas top-up path above instead.

Usernames

Lowercase a-z 0-9 _, 2 to 32 characters, lifetime, no renewal. Price depends on length and is paid once in USDG or in $RH402 at the live price with a slippage guard (maxAmount). Half of every $RH402 payment is burned.

LengthPrice
22,000 USD
3500 USD
4100 USD
520 USD
6 and more5 USD

The first name an address receives becomes its primary name. Names are NFTs: transfer them, or list them in the market (10% fee on sale). Reverse lookup: GET /v1/names/of/<address>. Forward: GET /v1/names/resolve/<name>.

Paying

All payments go through RH402Router so they are indexed with sender, receiver, amount, memo and optional invoice id:

pay(address to, uint256 amount, bytes32 invoiceId, string memo)
payName(string name, uint256 amount, bytes32 invoiceId, string memo)
payInvoice(bytes32 id, string memo)

The API builds the calls for you: POST /v1/pay/calls {name|to, amount, memo, invoiceId} returns [approve, pay]. An invoice id is one-time: a second payment against the same id reverts, and an id registered with createInvoice can only be settled through payInvoice.

Invoices and QR

  • GET /v1/qr/<name>.svg?amount=&memo=: a styled QR that opens the pay page. Any phone camera reads it.
  • POST /v1/invoice/calls {amount, memo, expiresAt}: on-chain invoice with exact amount and payee; GET /v1/qr/invoice/<id>.svg renders it, GET /v1/invoice/<id> shows its status.
  • GET /v1/explorer/card/<tx>.svg: a shareable receipt card for any payment.

Escrow market

Goods and services are bought through RH402Escrow. The buyer's USDG sits in the contract until the order resolves:

StateWhoWhat
Openbuyerfunded; buyer may withdraw until the seller accepts
Acceptedsellerthe 3-day clock starts; the seller can note delivery
Releasedbuyer or timebuyer confirms, or anyone releases after 3 days; 10% fee, rest to the seller
Reportedbuyerclock frozen; only an arbiter can resolve
Resolvedarbiteronly after a report: split by basis points, with a written note
Refundedseller or RH402full refund; RH402 can refund the buyer at any time before release

Every order has a report at GET /v1/order/<id> with the full timeline and outcome. Usernames are sold atomically (payment and NFT transfer in one transaction) and do not use escrow.

X402 rail

X402 lets any API or AI agent charge USDG per request. The exchange is two round trips:

GET /resource
→ 402 Payment Required
  PAYMENT-REQUIRED: base64(JSON requirement)

GET /resource
  PAYMENT: base64(JSON signed intent)
→ 200 OK
  PAYMENT-RESPONSE: base64({"txHash":"0x…","invoiceId":"0x…"})

A requirement looks like this. The calls array is exactly what the payer's account must execute; the facilitator refuses anything else.

{ "version": 1, "scheme": "rh402-intent", "network": "eip155:4663",
  "asset": "0x5fc5…d168", "assetSymbol": "USDG", "decimals": 6,
  "amount": "10000", "payTo": "0x…", "invoiceId": "0x…", "memo": "…",
  "expiresAt": 1790000000, "facilitator": "https://api.rh402.xyz/v1/402",
  "calls": [ { "to": "<USDG>", "data": "approve(router, amount)" },
             { "to": "<Router>", "data": "pay(payTo, amount, invoiceId, memo)" } ] }

Your server never holds a key. It asks RH402 for a requirement, sends it in the 402, and when the client retries it forwards the PAYMENT header to /v1/402/settle. A settled requirement cannot be paid twice.

Server side (any language)

# 1. create a requirement for this request
curl -X POST https://api.rh402.xyz/v1/402/requirements \
  -H 'content-type: application/json' \
  -d '{"payTo":"0xYourAddress","amount":"250000","memo":"weather api","resource":"/v1/weather"}'
# → { paymentRequired: {...}, header: "eyJ2…" }   put header in PAYMENT-REQUIRED, answer 402

# 2. when the client retries with PAYMENT, settle it
curl -X POST https://api.rh402.xyz/v1/402/settle \
  -H 'content-type: application/json' \
  -d '{"payment": <decoded PAYMENT header JSON>}'
# → { txHash, invoiceId }   serve the resource, echo PAYMENT-RESPONSE

Try it: GET https://api.rh402.xyz/v1/402/demo charges 0.01 USDG.

Facilitator API

EndpointPurpose
POST /v1/402/requirementscreate a requirement (payTo, amount, memo, resource, ttlSec)
GET /v1/402/requirement/:idread it back, see if it was settled
POST /v1/402/verifysimulate a payment without sending it
POST /v1/402/settlerelay the intent, return the tx hash
POST /v1/relay/executegeneric intent relay for delegated accounts
POST /v1/relay/delegatefirst transaction: EIP-7702 authorization plus optional intent
GET /v1/account/:addressdelegation state, intent nonce, balances, names
GET /v1/configchain id, contract addresses, EIP-712 types, price table

Client SDK

The browser app and the tests share one client (web/src/rh402-client.mjs, viem based). It signs locally and posts only signatures.

import { RH402 } from './rh402-client.mjs';
const c = RH402.fromPrivateKey('https://api.rh402.xyz', pk);
await c.registerName('ada');                     // delegates + registers in one relayed tx
await c.pay({ name: 'ada', amount: 5_000000, memo: 'thanks' });
const r = await c.fetch402('https://api.rh402.xyz/v1/402/demo'); // pays automatically

Contracts

ContractAddress
loading from /v1/config…
  • RH402Account: EIP-7702 delegate, ERC-7201 storage, sequential nonce, ERC-1271, token receivers.
  • RH402Names: ERC-721 usernames, price table by length, USDG or $RH402 via oracle, reserved names, primary names, pausable registrations.
  • RH402Router: pay by address or name, one-time invoice ids, registered invoices, optional fee (0 by default, hard cap 10%).
  • RH402Escrow: orders with accept window, 3-day release window (cannot be set longer), reports, arbiter split (reported orders only), emergency refund, pause.
  • RH402Market: name listings (atomic sale, 10% fee) and goods listings (escrow orders).
  • RH402Oracle: $RH402 price pushed by the RH402 feeder, 30% jump guard per push, 15-minute freshness.

Security notes

  • RH402 never holds your key: you sign every transaction in your own wallet. The gas top-up is a plain ETH transfer to your address.
  • Intents carry a deadline and a nonce; a captured signature cannot be replayed.
  • The relayer only executes calls that target RH402 contracts or USDG, after simulating them.
  • Contract owners can pause the router, escrow and market. Escrow funds can only leave to the buyer, the seller, or the treasury fee, never elsewhere.