fix(x402-evm): inject EIP-712 USDC domain (verified on Base mainnet)#33
Merged
Merged
Conversation
… on Base mainnet) Found while mainnet-testing Talha's original EVM x402 path: the EVM "exact" scheme (EIP-3009) needs the token's EIP-712 domain (name + version) in PaymentRequirements.extra, or the facilitator rejects verify with `invalid_exact_evm_missing_eip712_domain`. The rail wasn't adding it, so EVM verify failed unless the caller hand-built the requirements. - Add EVM_USDC_EIP712_DOMAINS (Base, Base Sepolia, Ethereum, Polygon, Arbitrum, Optimism) and X402RailConfig.eip712Domain override. - createChallenge auto-injects extra.name/version for EVM (mirrors the Solana feePayer injection); forwarded to the facilitator on verify/settle. - src/__tests__/x402-evm-rail.test.mjs: domain auto-injection, testnet variant, explicit override, no feePayer for EVM, and that verify forwards the domain. Verified live: with the domain, a 0.001 USDC self-transfer settled on Base mainnet via PayAI, gasless (tx 0xc18b14ef94c7ebd5589bf0816f6c8c8820d87e77c4ace5f118486a3f3c2a42f9). Status: x402 EVM -> Beta (verified on Base mainnet). Full suite: 233 passing. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
tkorkmazeth
pushed a commit
that referenced
this pull request
Jun 25, 2026
When a payment is verified + executed but settlement fails after the fact
(facilitator/RPC blip), it was a dead-end trace (settlement_uncertain) with the
provider unpaid. Phase B turns that into a recovery loop:
- src/settlement-recovery.ts:
- settleWithRetry() — bounded exponential backoff over settlePayment.
- PendingSettlementStore + InMemoryPendingSettlementStore — durable queue of
verified-but-unsettled payments.
- SettlementReconciler — drains the queue through each rail adapter; removes
what settles, keeps the rest with attempts/lastError for the next pass.
- TollGate: pendingSettlementStore config (default in-memory), `pendingSettlements`
getter, `enqueueSettlement()`, and `reconcileSettlements(opts)`.
- MCP adapter: settle now retries (configurable via settleRetry); anything still
unconfirmed is queued and the trace records attempts + queued:true.
Tests (src/__tests__/settlement-recovery.test.mjs): retry success/exhaustion,
store ops, reconciler drain/keep/no-adapter, and an end-to-end loop through
TollGate + the MCP adapter (settle fails -> queued -> reconciled).
Built on the merged Solana Beta (#32) and EVM EIP-712 (#33) work. Full suite: 242 passing.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Mainnet-testing Talha's original EVM x402 path surfaced a real bug: the EVM "exact" scheme (EIP-3009) requires the token's EIP-712 domain (
name+version) inPaymentRequirements.extra, or the facilitator rejects verify withinvalid_exact_evm_missing_eip712_domain. The rail never added it, so EVM verify failed unless the caller hand-built the requirements. (This is the EVM analogue of the SolanafeePayergap.)Fix
EVM_USDC_EIP712_DOMAINStable (Base, Base Sepolia, Ethereum, Polygon, Arbitrum, Optimism) +X402RailConfig.eip712Domainoverride for custom tokens.createChallengeauto-injectsextra.name/extra.versionfor EVM networks (mirrors the SolanafeePayerinjection); forwarded to the facilitator on verify/settle.Tests
src/__tests__/x402-evm-rail.test.mjs(offline): auto-injection for Base mainnet, the Base Sepolia variant, explicit override, nofeePayerfor EVM, and that verify forwards the domain inpaymentRequirements. Full suite: 233 passing.Verified live (Base mainnet)
Before the fix:
invalid_exact_evm_missing_eip712_domain. With the domain: a 0.001 USDC self-transfer settled on Base mainnet via PayAI, gasless (signer held 0 ETH):0xc18b14ef…2a42f9— status success, gas paid by the facilitator.Status: x402 EVM Experimental → Beta (verified on Base mainnet); x402 mainnet row notes EVM + Solana live smoke settles.
🤖 Generated with Claude Code