Self-hosted payment facilitator for the x402 protocol. Supports EIP-7702 (any ERC-20, native ETH) and ERC-3009 (USDC) payment mechanisms. Enables gasless transfers on any EVM chain.
The facilitator acts as a trusted relayer between a buyer and seller. The buyer never needs ETH for gas — the relayer pays gas and submits a Type 4 (EIP-7702) transaction that delegates the buyer's EOA to a Delegate contract, which then executes a signed token transfer.
BUYER SELLER FACILITATOR
| | |
|--- GET /resource ------>| |
|<-- 402 + requirements --| |
| | |
| [sign EIP-712 intent] | |
| [sign EIP-7702 auth] | |
| | |
|--- GET + PAYMENT ------>| |
| |--- POST /verify -------->|
| |<-- { isValid: true } ----|
| |--- POST /settle -------->|
| | [submit Type 4 tx]
| | [relayer pays gas]
| |<-- { tx: 0x... } --------|
|<-- 200 + data ----------| |
| Package | Description |
|---|---|
packages/contracts |
Solidity Delegate.sol — EIP-7702 delegate for gasless payment intents |
packages/eip7702 |
EIP-7702 mechanism library — verify + settle any ERC-20 via viem |
packages/server |
Unified CLI server — supports EIP-7702 + ERC-3009 mechanisms |
packages/dash |
Real-time dashboard for monitoring facilitator balances and transactions |
packages/demo |
Interactive demo with dual-token (USDT + USDC) buyer/seller agents |
Requires: Foundry (for Anvil)
curl -L https://foundry.paradigm.xyz | bashnpx @facilitator/demoNote: You can also use
bunx,yarn dlx, orpnpm dlxif you prefer.
Then in a new terminal, run the facilitator command printed by the demo:
npx @facilitator/server \
--relayer-key 0x... \
--delegate-address 0x... \
--chain 31337=http://127.0.0.1:8545Open http://localhost:3030 and click INITIATE.
npx @facilitator/dash- Deploy the Delegate contract (same address on every chain via CREATE2):
forge install melonask/facilitator
forge \
script lib/facilitator/packages/contracts/script/Deploy.s.sol \
--rpc-url <RPC_URL> \
--broadcast- Run the facilitator:
All known chains (default):
npx @facilitator/server --relayer-key 0x...This enables Ethereum, Optimism, BNB Chain, Polygon, Base, Arbitrum, and Avalanche with default public RPCs.
Specific chains:
Three --chain formats are supported:
# Chain ID with custom RPC
--chain 8453=https://mainnet.base.org
# Custom RPC only (chain ID auto-detected)
--chain https://mainnet.base.org
# Chain ID only (uses default public RPC)
--chain 8453The server automatically resolves the Delegate.sol address for known networks (Ethereum, Polygon, Base, Optimism, Arbitrum, BNB Chain, Avalanche). For custom deployments, pass --delegate-address 0x... explicitly.
By default, nonce state and settlement history are stored in memory and lost on restart. To persist them, use --db:
SQLite (local file):
npx @facilitator/server \
--relayer-key 0x... \
--db ./facilitator.dbPostgreSQL (connection string):
npx @facilitator/server \
--relayer-key 0x... \
--db postgres://user:pass@localhost:5432/facilitatorPostgreSQL (environment variables):
PGHOST=localhost PGDATABASE=facilitator PGUSER=postgres PGPASSWORD=secret \
npx @facilitator/server \
--relayer-key 0x...You can also use DATABASE_URL instead of the individual PG* variables. Tables are created automatically on startup.
Note: Without
--dbor PG environment variables, the server falls back to an in-memory store with a warning on startup. This is fine for testing but not recommended for production — nonce replay protection and settlement records will be lost on restart.
TypeScript server HTTP API:
| Endpoint | Method | Description |
|---|---|---|
/verify |
POST |
Verify a signed payment (read-only, no state change) |
/settle |
POST |
Verify + submit Type 4 transaction on-chain |
/supported |
GET |
List supported schemes, networks, and signers |
/healthcheck |
GET |
Server health status |
/info |
GET |
Relayer ETH balance per chain |
/settlements |
GET |
Query settlement history (requires ?payer=0x...; optional &chainId=1) |
Request body for /verify and /settle:
{
"paymentPayload": {
"payload": {
"authorization": {
"contractAddress": "0x...",
"chainId": 1,
"nonce": 0,
"r": "0x...",
"s": "0x...",
"yParity": 0
},
"intent": {
"token": "0x...",
"amount": "1000000",
"to": "0x...",
"nonce": "123",
"deadline": "1700000000"
},
"signature": "0x..."
}
},
"paymentRequirements": {
"scheme": "eip7702",
"network": "eip155:1",
"asset": "0x...",
"amount": "1000000",
"payTo": "0x..."
}
}The facilitator performs these checks before settlement:
- Recover signer from EIP-7702 authorization
- Verify delegate contract address is trusted
- Verify EIP-712 intent signature matches authorization signer
- Check intent matches payment requirements (recipient, amount, asset)
- Check deadline has not expired
- Check nonce has not been used (replay protection)
- Check payer has sufficient token/ETH balance on-chain
This facilitator supports both mechanisms simultaneously:
ERC-3009 (exact scheme) |
EIP-7702 (eip7702 scheme) |
|
|---|---|---|
| Token support | Only tokens with transferWithAuthorization (USDC) |
Any ERC-20 (USDT) + native ETH |
| Mechanism | Token-level authorization | Account-level delegation |
| Smart wallets | Requires EIP-6492 for counterfactual | Direct EOA delegation |
| Gas | Relayer pays gas | Relayer pays gas |
| Chain support | Chains with USDC deployment | Any EVM chain with EIP-7702 |
- Add a skill to your agent.
npx skills add melonask/facilitator- Ask AI agent to create a x402 project.
/x402-facilitator
"Create an image generation API using the OpenRouter API model black-forest-labs/flux.2-klein-4b, with a fee of 0.1 USDT per request via the x402 protocol. For testing, create an agent that will purchase image generation via the API, and test it on the live Foundry Anvil blockchain. Create the UI/UX for this project and for tracking balances."
MIT


