Permissionless stablecoin payments for commerce.

The internet runs on open protocols. Payments are the exception. rail0 is a single immutable smart contract implementing the full authorize → capture → refund lifecycle for stablecoin payments — with no owner and no privileged operator.

The zero is literal

Four zeros between buyer and merchant.

The zero in rail0 is not branding — it counts what the protocol removes. Nothing sits between the two parties, nothing is skimmed off the top, no one holds a key that can change the rules, and no one decides who is allowed in. It also marks day zero: the moment payments stop being a service rented from someone else's network and become a commodity protocol, the way HTTP is.

0

Intermediaries

Buyer and merchant transact peer-to-peer. The contract routes nothing to anyone else.

0

Protocol fees

Every captured token reaches the merchant in full. The contract takes nothing.

0

Privileged operators

No owner, no admin, no pauser, no upgrade path. The code is fixed at deploy time.

0

Permission

Anyone can deploy the contract. Anyone can use it. No gatekeeper to ask.

Protocol overview

One contract, zero operators.

The buyer signs once off-chain; the merchant submits and pays gas. Funds flow straight from payer to payee through the rail0 escrow — authorize in, capture out, and void, refund, or release back to the buyer. No processor, no gateway, no privileged operator in the path.

rail0 protocol flow: payer authorizes or charges into the rail0 escrow, the payee captures, and refund / void / release return funds to the payer rail0 protocol flow: payer authorizes or charges into the rail0 escrow, the payee captures, and refund / void / release return funds to the payer rail0 protocol flow: payer authorizes or charges into the rail0 escrow, the payee captures, and refund / void / release return funds to the payer rail0 protocol flow: payer authorizes or charges into the rail0 escrow, the payee captures, and refund / void / release return funds to the payer

How it works

One signature. No allowance.

01 — PAYER

Signs, never broadcasts

The buyer signs an EIP-3009 TransferWithAuthorization over the token's domain — like a signed check. Any wallet that signs typed data works: no smart-account wallet, no bundler, no approval.

02 — PAYEE

Submits and pays gas

The merchant submits the transaction and absorbs the cost of acceptance — the way they always have under card networks. On stablecoin-native chains, gas is paid in the same asset being settled.

03 — CONTRACT

Binds terms to the signature

rail0 derives a deterministic EIP-3009 nonce from the exact payment terms. Tamper with any field and the recovered signer won't match — the token reverts. No separate intent typehash needed.

Deployments

Works on multiple chains.

rail0 is not tied to any one chain. It runs on any network that meets two hard requirements: an EVM that compiles Solidity 0.8.27, and tokens that expose the EIP-3009 transferWithAuthorization / receiveWithAuthorization entrypoints — the off-chain signatures the whole protocol is built on. That's the entire bar. Anyone can deploy it, permissionlessly, wherever those conditions hold.

ChainNetworkStablecoinsStatusAddress
Arbitrum Sepolia testnet USDC Live 0x13a4…Ba1F
Arbitrum Mainnet USDC Planned
Arc Testnet USDC, EURC Live 0x13a4…Ba1F
Avalanche Fuji testnet USDC Live 0x13a4…Ba1F
Avalanche Mainnet USDC, EURC Planned
Base Sepolia testnet USDC Live 0x13a4…Ba1F
Base Mainnet USDC, EURC Planned
Celo Sepolia testnet USDC, USD₮ Live 0x13a4…Ba1F
Celo Mainnet USDC, USD₮ Planned
Ethereum Mainnet USDC, EURC Planned
Monad Testnet USDC Live 0x13a4…Ba1F
Monad Mainnet USDC Planned
Optimism Sepolia testnet USDC Live 0x13a4…Ba1F
Optimism Mainnet USDC Planned
Plasma Testnet USDT0 Planned
Polygon Amoy testnet USDC Live 0x13a4…Ba1F
Polygon Mainnet USDC Planned
Sei Testnet USDC Live 0x13a4…Ba1F
Sei Mainnet USDC Planned
Sonic Testnet USDC Live 0x13a4…Ba1F
Sonic Mainnet USDC Planned
Unichain Sepolia testnet USDC Live 0x13a4…Ba1F
Unichain Mainnet USDC Planned
World Chain Sepolia testnet USDC Live 0x13a4…Ba1F
World Chain Mainnet USDC, EURC Planned
Tempo TIP-20 Awaiting EIP-3009

Every live deployment above is rail0 1.3.0 at the same address — the deployer's nonce was 0 on each chain, and a CREATE address derives only from (sender, nonce). Pin it per chain anyway and do not assume cross-deployment compatibility: the EIP-712 domain binds the version, so a payment signed against one version does not verify against another. Mainnets are planned on every chain whose testnet runs today; the README carries the full split.

Quickstart

The lifecycle in three cast calls.

Authorize, capture, refund — the full path with Foundry's cast. In production a wallet SDK handles the EIP-712 signing; here's the bare metal.

1 — Authorize a payment

The buyer signs an EIP-3009 TransferWithAuthorization off-chain; the merchant submits and pays gas.

shell authorize
# 1. Compute the deterministic EIP-3009 nonce rail0 expects
CONFIG_HASH=$(cast call $RAIL0 "hashPayment($PAYMENT_TYPE)(bytes32)" "$PAYMENT" --rpc-url $RPC)
NONCE=$(cast call $RAIL0 "authorizeNonce(bytes32,bytes32)(bytes32)" $PAYMENT_ID $CONFIG_HASH --rpc-url $RPC)

# 2. Buyer signs the EIP-3009 digest over the token's domain (off-chain)
#    validAfter = 0, validBefore = p.authorizationExpiry — pinned by rail0
SIG=$(cast wallet sign --no-hash --private-key $PAYER_KEY $DIGEST)
R=0x${SIG:2:64}; S=0x${SIG:66:64}; V=0x${SIG:130:2}

# 3. Merchant submits the transaction and pays gas
cast send $RAIL0 "authorize(bytes32,$PAYMENT_TYPE,uint8,bytes32,bytes32)" \
  $PAYMENT_ID "$PAYMENT" $V $R $S \
  --rpc-url $RPC --private-key $PAYEE_KEY

2 — Capture an authorized payment

Merchant only. Pulls escrowed funds to the merchant before authorizationExpiry — partial or full, across one or more calls.

shell capture
# Capture 100 USDC (6 decimals) of the escrowed authorization
cast send $RAIL0 "capture(bytes32,$PAYMENT_TYPE,uint256)" \
  $PAYMENT_ID "$PAYMENT" 100000000 \
  --rpc-url $RPC --private-key $PAYEE_KEY

3 — Refund a captured payment

Captured funds live in the merchant's wallet, so the merchant signs an EIP-3009 refund and submits it; the funds return to the buyer. No allowance, no approve.

shell refund
# 1. Refund nonce for the CURRENT refundable balance (here: 50 USDC)
NONCE=$(cast call $RAIL0 "refundNonce(bytes32,bytes32,uint120)(bytes32)" $PAYMENT_ID $CONFIG_HASH 50000000 --rpc-url $RPC)

# 2. Merchant signs the EIP-3009 digest (validBefore = p.refundExpiry)
SIG=$(cast wallet sign --no-hash --private-key $PAYEE_KEY $DIGEST)
R=0x${SIG:2:64}; S=0x${SIG:66:64}; V=0x${SIG:130:2}

# 3. Merchant submits — funds always reach $PAYER
cast send $RAIL0 "refund(bytes32,$PAYMENT_TYPE,uint256,uint8,bytes32,bytes32)" \
  $PAYMENT_ID "$PAYMENT" 50000000 $V $R $S \
  --rpc-url $RPC --private-key $PAYEE_KEY