fix(gasless): guard delegated EOAs on non-canonical-7702 chains (Avalanche) + Pimlico-only smoke#21
Merged
Conversation
…anche) to standard mode
Avalanche C-Chain implements EIP-7702 via ACP-209 ("7702 style" AA) with
non-canonical nonce/balance handling. The standard viem/permissionless/Pimlico
7702 stack can't delegate there: UserOps revert AA23 (proven 2026-05-31 gate,
all 3 legs incl. the Pimlico leg). useSmartAccount routed purely on detection.kind
with no per-chain check, so a delegated EOA (pimlico-simple / mav2 / metamask) on
Avalanche would enter a 7702 builder and fail at send time with a cryptic AA23 and
no fallback. Pristine EOAs were already safe (errorPristineNoBootstrap -> standard).
- lib/chains.ts: add chainSupportsCanonical7702(chainId) (blocklist: avalanche +
avalancheFuji). New chains default true; verify with SMOKE_LEGS=pimlico before relying.
- useSmartAccount.ts: before kind branches, if a known 7702-delegated kind is on a
non-canonical chain, throw IncompatibleSmartAccountError(errorChainNo7702) -> the
existing saFallback shows standard mode. Standard mode always works on Avalanche.
- accountDetection.ts: add errorChainNo7702 to the i18n key union.
- messages ja/en: errorChainNo7702 in PaymentForm/TipForm/CheckoutForm (Pay/Checkout
guide to standard mode; Tip guides to another chain since tips require gasless).
- smoke: add SMOKE_LEGS=pimlico (Pimlico-only, no Circle) to verify the Pimlico erc20
gasless path on any chain with a disposable EOA (reproduces Avalanche AA23; circle
paymaster optional in config). runbook documents the guard + the pimlico-only mode.
- tests: chainSupportsCanonical7702 (chains.test) + errorChainNo7702 i18n parity.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
…ed -> formatUnits) Surfaced by SMOKE_LEGS=pimlico on Avalanche: both legs correctly fail AA23, but the summary then crashed with "Cannot read properties of undefined (reading 'toString')". Failed legs (catch block) pushed a result without gasChargeUsdc, so the JSON map's `r.gasChargeUsdc !== null ? formatUnits(...)` passed (undefined !== null) and called formatUnits(undefined). Regression from the displayBase measurement commit; affects both modes on any leg failure. - catch block sets gasChargeUsdc: null explicitly. - summary JSON map + circle/pimlico gas filters guard with typeof === 'bigint'. - verified: all-failed-legs summary now renders a clean FAIL (no crash). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…tion
Lets us verify the existing Pimlico erc20 gasless path on Ethereum mainnet with a
disposable EOA (same tool that caught Avalanche's ACP-209 incompatibility). Circle
on Ethereum stays deferred, so circlePaymaster is omitted -> pimlico-only by design
('all' mode throws a clear "use SMOKE_LEGS=pimlico" error). Polygon already has a
config, so SMOKE_CHAIN=polygon SMOKE_LEGS=pimlico works as-is.
WARNING in funding text: L1 gas is dollar-scale (vs cents on L2), budget ~20-30 USDC.
Co-Authored-By: Claude Opus 4.8 <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.
Problem
Avalanche C-Chain implements EIP-7702 via ACP-209 ("7702 style" AA) with non-canonical nonce/balance handling. The standard viem/permissionless/Pimlico 7702 stack can't delegate there — UserOps revert AA23 (proven by the 2026-05-31 gate: all 3 legs, including the Pimlico leg, failed;
delegateAfter: null).useSmartAccountrouted purely ondetection.kindwith no per-chain check. So a delegated EOA (pimlico-simple-7702/alchemy-mav2-7702/metamask-7702) on Avalanche would enter a 7702 builder and fail at send time with a cryptic AA23 and no graceful fallback. (Pristine EOAs were already safe:errorPristineNoBootstrap→ standard mode.)Fix
lib/chains.ts:chainSupportsCanonical7702(chainId)— blocklist (avalanche+avalancheFuji). New chains defaulttrue; verify withSMOKE_LEGS=pimlicobefore relying.hooks/useSmartAccount.ts: before the kind branches, if a known 7702-delegated kind is on a non-canonical chain →IncompatibleSmartAccountError('errorChainNo7702'). The existingsaFallbackrenders standard mode (which always works on Avalanche).errorChainNo7702added to PaymentForm/TipForm/CheckoutForm (ja+en). Pay/Checkout → "pay in standard mode"; Tip → "use another chain" (tips require gasless).SMOKE_LEGS=pimlico: Pimlico-only mode (no Circle) to verify the Pimlico erc20 gasless path on any chain with a disposable EOA — reproduces the Avalanche AA23 and is reusable for future chains.Scope / risk
NEXT_PUBLIC_ENABLE_MAV2(off by default), so gating it on Avalanche regresses nothing live.Tests
chainSupportsCanonical7702unit test (Avalanche/Fuji false; Base/Arb/OP/Polygon/Ethereum true; unknown→true).errorChainNo7702i18n parity across 3 namespaces × ja/en.tests/lib/{chains,i18nKeys,accountDetection}503 pass.🤖 Generated with Claude Code