What this is
A pay-per-call gas oracle for Base mainnet that AI agents can use without an API key, a signup, or a subscription. Payment settles in USDC on Base (eip155:8453) through the Coinbase CDP production facilitator.
Who it is for
Developers building AI agents that transact on Base. And, secondarily, developers evaluating x402 as a way to sell their own APIs: all of it is open source and readable as a reference implementation.
Why not just call an RPC?
An RPC tells you the current gas price but not whether it is high or low, because it has no memory. This service samples Base every five minutes, so it can answer:
- Is gas cheap, normal, expensive, or flat right now?
- How does Base compare to OP Mainnet, Arbitrum One, and Ethereum?
- Would waiting for a cheaper hour actually help?
The 402 part
HTTP 402 Payment Required has been reserved and unused since 1997. x402 finally uses it. Your agent requests data, the server answers 402 with a price, the agent pays in USDC, and the data comes back. One round trip, no account.
See it for yourself. This costs nothing, you never pay the challenge itself:
curl -i https://base-gas-x402-production.up.railway.app/gas
Setup
Three ways in. Pick one.
1. Agent skill (recommended)
npx skills add memosr/base-gas-skill --all --yes
Then ask the agent: What is gas on Base right now?
The paid routes need a funded AgentCash wallet:
npx agentcash@latest onboard
npx agentcash@latest balance
2. MCP server
npx agentcash@latest install -y
npx skills add memosr/base-gas-skill/mcp --all --yes
Published on npm as base-gas-mcp.
3. Direct HTTP
curl -s https://base-gas-x402-production.up.railway.app/health
npx agentcash@latest fetch "https://base-gas-x402-production.up.railway.app/gas?gasLimit=180000"
Full docs live with the code: API repo, skill repo, OpenAPI.
Five routes
| Route | Price | Returns |
|---|---|---|
| GET /gas | $0.005 | Base fee, priority tiers, gas price, cost for any gasLimit |
| GET /gas/compare | $0.01 | Base, OP Mainnet, Arbitrum One, Ethereum, cheapest first |
| GET /gas/history | $0.012 | Time series, min/max/avg/median, verdict, spreadPercent |
| GET /gas/cheapest-window | $0.02 | hasDailyCycle, recommendation, hourly averages |
| GET /health | free | Samples, hours covered, interval, retention |
/gas and /gas/compare take gasLimit (21000 to 30000000). /gas/history and /gas/cheapest-window take hours (1 to 168).
| Operation | gasLimit |
|---|---|
| ETH transfer | 21000 |
| ERC-20 transfer | 65000 |
| NFT mint | 85000 |
| Uniswap swap | 180000 |
| Contract deploy | 1500000 |
Real response: /gas/compare
Base comes second here, not first. That is left in on purpose: anyone can call the endpoint and check.
{
"gasLimit": 21000,
"chains": [
{ "chain": "optimism", "label": "OP Mainnet", "gasPrice": "0.001000371",
"estimatedCost": { "eth": "0.000000021007791" } },
{ "chain": "base", "label": "Base", "gasPrice": "0.006",
"estimatedCost": { "eth": "0.000000126" } },
{ "chain": "arbitrum", "label": "Arbitrum One", "gasPrice": "0.02",
"estimatedCost": { "eth": "0.00000042" } },
{ "chain": "ethereum", "label": "Ethereum", "gasPrice": "0.046909277",
"estimatedCost": { "eth": "0.000000985094817" } }
],
"cheapest": "optimism",
"baseRank": 2,
"baseVsEthereum": "Base is 7.8x cheaper than Ethereum",
"unavailable": []
}
Real response: /gas/cheapest-window
{
"hasDailyCycle": false,
"recommendation": "No meaningful daily gas cycle on this chain: the gap between the cheapest and priciest hour is 0%. Timing a transaction by hour of day will not save anything. Transact whenever you need to.",
"savingsPercent": 0
}
This is the answer you will usually get on Base. Measured across two independent 15-hour windows, the gap between the cheapest and priciest hour was effectively zero.
Advantages and differences
Several Base gas endpoints exist, including multi-chain toolkits covering seven chains to this one's one. Here is where this one differs.
- Focused, not a dumping ground
- Five routes, one question each. Competitors ship 67, 307, and 353 endpoints; the AgentCash validator warns above 40, because a large surface eats an agent's token budget.
- Honest about its own data
/healthis free and reports how much history exists, so you can decide whether a paid history call is worth it. Every paid response carries acoverageobject. No competitor does this.- It tells you when there is nothing to do
- On the fee floor,
/gas/historyreturnsflatand/gas/cheapest-windowreturnshasDailyCycle: false. An endpoint that always names a "cheapest hour" is selling a decision that cannot be made. - Priced per operation
- Pass
gasLimit, get the cost of the thing you are about to do, not a gwei figure to multiply yourself. - Fails partially, not totally
/gas/comparereads four chains independently. One dead RPC lands inunavailableinstead of killing the response you paid for.- Open source, end to end
- API, MCP server, and skill are public and MIT licensed. The skill ships rules that steer agents away from overspending.
- Cheapest current-gas endpoint in the category
/gasat $0.005, against $0.01, $0.013, $0.05, and $0.10. Only for/gas:/gas/historyat $0.012 is not the cheapest, a $0.001 competitor exists.
What it is not: not the only or first Base gas API, and not the cheapest overall. It will not save you money by timing transactions on Base, because there is nothing there to time. Single instance on Railway, no uptime guarantee and no SLA. No usage numbers to quote, it is new.
Findings
Two x402 failure modes found while building this. Both are reproducible and both cost hours. If you run an x402 origin, they may save you an afternoon.
1. A missing trust proxy silently blocks discovery
Railway and most PaaS edges terminate TLS and forward plain HTTP. Express reports req.protocol as http, x402 advertises an http:// resource, and Bazaar registration fails hourly with:
resource must start with 'https://' when protocol type is http
Nothing surfaces it: the discovery CLI reports zero warnings and the endpoints stay live and payable, while the index never updates. One line fixes it:
app.set("trust proxy", true);
2. The CDP facilitator size-limits the payment payload
The bazaar metadata from the 402 challenge is echoed back inside the payment payload. Past a threshold the facilitator reports it as a schema error:
'paymentPayload' is invalid: must match one of [x402V2Pay...
Measured on Base, same wallet and client: 4188 bytes accepted, 4260 bytes rejected. One endpoint stopped accepting payment purely because its description was longer than the others. Writing better documentation made it unpayable.