0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

x402 v2で「支払ったらEVMをsimulationするAPI」を作ってみた

0
Last updated at Posted at 2026-10-23

x402 v2で「支払ったらEVMをsimulationするAPI」を作ってみた

AI Agentが自分でオンチェーントランザクションを組み立てるなら、送信前に「このcallは今のstateで通るのか」を機械的に確認したくなります。

そこで、Base/EVM向けのread-only Transaction Preflight Engineと、x402によるpay-per-requestの支払い境界をTypeScriptで分離実装し、最後に統合しました。

この記事では、まだmainnetでサービス提供していない段階の実装と、実際にテストして分かった落とし穴をまとめます。

構成

Client / AI Agent
      ↓ POST /preflight
x402 payment verification
      ↓
Preflight Engine
      ↓ eth_chainId / eth_blockNumber / eth_call / eth_estimateGas
Operator-configured RPC
      ↓
x402 settlement
      ↓
Result

支払いコードとsimulation engineは独立させています。Engine側はx402を知りませんし、x402側もtransaction schemaの内部実装を持ちません。

使用しているもの

現在の検証環境はNode.js 24.19.0。x402 PoCでは @x402/core / @x402/evm / @x402/express / @x402/fetch 2.28.0、Express 5.3.0、viem 2.57.10を使用しています。

PoCの支払い条件は以下です。

項目 現在のPoC
Network Base Sepolia (eip155:84532)
Token test USDC
x402 v2 / exact
Authorization EIP-3009
仮価格 0.001 USDC / request
Production候補 Base mainnet + USDC(未有効化)

0.001 USDCはあくまでPoC価格です。本番価格は別途検討しています。

Preflight Engine

入力はかなり小さくしています。

{
  "schemaVersion": 1,
  "chain": "eip155:84532",
  "from": "0x1111111111111111111111111111111111111111",
  "to": "0x2222222222222222222222222222222222222222",
  "value": "0",
  "calldata": "0x"
}

valueをJSON numberではなく10進文字列にしているのは、uint256をJavaScript numberで扱って精度を落とさないためです。

EngineはRPCのchain IDを確認し、block numberを取得して、そのblockに eth_call と可能なら eth_estimateGas を固定します。

返却statusは主に次の5種類です。

  • success
  • revert
  • invalid_request
  • unsupported_network
  • error

revertについては Error(string)、Panic(uint256)、custom error、empty revertを区別します。分からないABIを勝手に推測して「それっぽい理由」を返さないようにしています。

x402の支払い境界

未払いの POST /preflight はHTTP 402になります。

payment-aware clientはchallengeを確認し、許可したnetwork / token / amount / payToであることを検証した上でauthorizationに署名し、再リクエストします。

ローカルテストでは資金を持たない一時キーとtest-only facilitatorを使っています。署名・金額・recipient・有効期間・nonceなどは確認しますが、実際のオンチェーン送金ではありません。

ここは重要で、syntheticなsettlement receiptが返ったからといって「USDCが動いた」とは言えません。

Engineとx402を統合する

統合後は、未払いならEngineを一度も実行しません。

一方、支払いverificationが成功した場合はEngineを実行し、その後settlementが成功して初めて結果を返します。

実際のintegration testでは次を確認しています。

  • unpaid request → Engine/RPCを呼ばず402
  • paid request → simulation resultを返す
  • EVM revert → normalizedなrevert結果を返す
  • verification failure → Engine/RPCを呼ばない
  • settlement failure → simulation済みでも結果を開示しない
  • 実際のserver entry pointを起動して同じフローを通す

CIの結果

記事作成時点で、GitHub ActionsのCore checksは成功しています。

npm run check はlint、typecheck、全テストを実行します。

テスト内訳は次の通りでした。

Suite Passed
Infra 5
Preflight Engine 19
x402 payment 15
Integration + Security 13
合計 52

fail / skippedは0でした。

Security担当を別にしたら、ちゃんと問題が出た

今回、実装担当とは別のAI Agentにsecurity reviewをさせました。

そこで見つかったproduction blockerが2つあります。

1. settlement前に計算コストを使う

x402 middlewareのフローでは、payment verification後にhandlerが動き、その後settlementします。

つまりsettlementが最終的に失敗しても、RPC simulation自体は既に走っている場合があります。

同じauthorizationを並列利用された場合などに、高コストな処理だけ複数回実行させられる可能性があります。

現在これはresource admission、in-flight authorization、concurrency、timeoutなどを含めて修正中です。

2. 「役に立たない結果」に課金してよいのか

もう1つは技術というよりbilling policyの問題です。

例えばRPC providerが落ちて RPC_FAILURE になったとき、HTTPレスポンスとしてJSONを返せてしまうと、genericなpayment adapterではsettlement対象になる可能性があります。

一方、EVMの revert は「そのtransactionが失敗する」と事前に分かった有用なsimulation結果なので、無料にするとは限りません。

つまり、

success              → charge?
revert               → charge?
invalid_request      → charge?
unsupported_network  → charge?
RPC_FAILURE          → charge?

をプロダクトとして明示的に決める必要があります。

このbilling semanticsも本番公開前のblockerとして修正しています。

ローカルでの確認

リポジトリ全体のチェックは次の構成です。

npm ci
npm run install:packages
npm run check

統合APIは環境変数にBase Sepolia RPCと受取先などを設定した上で、

npm run start:api

で起動します。

ただし現時点の統合環境はproduction serviceではありません。秘密鍵・mainnet資金を使わずに確認できるローカルfixture中心の実装です。

まとめ

今回やってみて、x402をHTTP APIに付けること自体よりも、何を「支払う価値のある結果」と定義するかの方が難しいと感じました。

また、transaction simulationも eth_call が成功しただけでは安全性の保証にはなりません。provider trust、reorg、mempool、asset delta、traceなど、見えていないものは多くあります。

だからAPIも「safe / unsafe」を雑に返すのではなく、観測できた事実とlimitationsを返す設計にしています。

現在はproduction blockerを修正中です。次はtestnetで実際のx402 settlementを確認し、その後、人間の承認を挟んでBase mainnetでの公開を検討します。

本番売上はまだ0ドルです。最終目標は、第三者のAI Agent / developerがこのAPIに本当にお金を払うのかを検証することです。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?