Skip to content

feat(x402): the signed domain follows the 402's network — Arc, Base, Base Sepolia - #44

Merged
VickyXAI merged 1 commit into
mainfrom
feat/arc-network
Sep 16, 2026
Merged

VickyXAI merged 1 commit into
mainfrom
feat/arc-network

Conversation

@VickyXAI

Copy link
Copy Markdown
Contributor

Why

One EIP-712 domain was signed whatever the 402 said — Base's USDC ("USD Coin" v2, chainId 8453, 0x8335…), with accepted.asset always Base's. Against arc.blockrun.ai (eip155:5042, USDC at 0x3600…, domain name USDC) every payment was a signature over the wrong domain: the facilitator recovered a different signer and answered 401 after the SDK had reported a payment. Same for testnet.blockrun.ai (Base Sepolia).

What

  • EVM_NETWORKS maps a 402's network to the SDK's own chainId, USDC address and domain (Base, Arc, Base Sepolia); createPaymentPayload signs those.
  • The 402 selects the network and supplies nothing else — the rule the single constant enforced (a hostile 402's extra cannot steer a signature onto another contract) still holds.
  • Unknown network → refused, naming what is supported. 402 asset ≠ that network's USDC → refused before signing. Every EVM call site passes the 402's asset through.
  • New exports: EVM_NETWORKS, evmNetwork(), ARC_CHAIN_ID, USDC_ARC. README "Arc Support" section. 3.16.0.

Verified

Against arc.blockrun.ai with an unfunded throwaway key: Circle's /verify answers insufficient_funds and recovers the throwaway's own address as payer — the signature verifies on Arc's domain; only the balance is missing.

Six new tests: verifyTypedData against Arc's domain passes and against Base's fails; Base unchanged; unknown network and asset mismatch refused; a 402's extra ignored. 365 tests, tsc and eslint clean.

🤖 Generated with Claude Code

…Base Sepolia

One EIP-712 domain was signed whatever the 402 said: Base's USDC, "USD Coin"
v2, chainId 8453, 0x8335…, with `accepted.asset` always Base's. Against
arc.blockrun.ai (eip155:5042, USDC at 0x3600…, domain name "USDC") every
payment was a signature over the wrong domain — the facilitator recovered a
different signer and answered 401 after the SDK had reported a payment. Same
for testnet.blockrun.ai (Base Sepolia, whose USDC is also named "USDC").

EVM_NETWORKS maps a 402's `network` to the SDK's OWN chainId, USDC address
and domain; createPaymentPayload signs those. The 402 SELECTS the network
and supplies nothing else, so the rule the single constant enforced — a
hostile 402's `extra` cannot steer a signature onto another contract —
still holds. An unknown network is refused naming what is supported; a 402
whose `asset` is not that network's USDC is refused before signing. Every
EVM call site passes the 402's asset through.

Verified against arc.blockrun.ai with an unfunded throwaway key: Circle's
/verify answers insufficient_funds and recovers the throwaway's own address
as payer — the signature verifies on Arc's domain and only the balance is
missing. Six new tests pin the domain per network (verifyTypedData against
Arc's domain passes, against Base's fails), the refusals, and that `extra`
from a 402 is ignored. 365 tests, tsc and eslint clean. 3.16.0.
@VickyXAI
VickyXAI merged commit 8672a5b into main Sep 16, 2026
3 checks passed
@VickyXAI
VickyXAI deleted the feat/arc-network branch September 16, 2026 18:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant