Skip to content

docs: ERC-4337 Account Abstraction developer guide for Arc Testnet - #114

Open
osr21 wants to merge 2 commits into
circlefin:mainfrom
osr21:docs/erc-4337-on-arc-testnet
Open

docs: ERC-4337 Account Abstraction developer guide for Arc Testnet#114
osr21 wants to merge 2 commits into
circlefin:mainfrom
osr21:docs/erc-4337-on-arc-testnet

Conversation

@osr21

@osr21 osr21 commented Jun 3, 2026

Copy link
Copy Markdown

Summary

Adds docs/erc-4337.md — a comprehensive developer guide for building ERC-4337 account abstraction applications on Arc Testnet.

This guide was produced from hands-on experience deploying and debugging ERC-4337 Paymasters on Arc Testnet. It documents three Arc-specific constraints that have silent failure modes (no helpful revert, just zero bytecode or rejected UserOps), which are not currently covered in the Arc docs.

What's new

docs/erc-4337.md covers:

Arc-specific constraints (the critical stuff)

Constraint Symptom if missed Fix
No PUSH0 opcode Deployment mines but cast code returns 0x Compile with evmVersion: "paris" in Hardhat/Foundry/solc
Two-immutable constructor reverts Same silent zero-bytecode failure Keep entryPoint as constant, not immutable
nonReentrant on validatePaymasterUserOp Bundler silently drops UserOp, no on-chain error Remove it; onlyEntryPoint is sufficient under ERC-7562

General ERC-4337 on Arc

  • EntryPoint v0.7 address and how to verify it's live
  • Pimlico bundler setup for chain ID 5042002
  • Smart account deployment and funding via permissionless.js
  • USDC-as-gas decimal handling: 18-decimal native Wei vs 6-decimal ERC-20 — with the conversion formula (÷ 1e12)
  • USDC Paymaster pattern with a reservation system (locked[user]) for concurrent UserOps
  • ERC-7562 storage restriction rules for unstaked Paymasters
  • Deterministic finality and CCTP minFinalityThreshold guidance (Arc = 2000 / finalized)
  • Full worked example: batched approve + depositForBurn (CCTP V2) in a single gasless UserOp
  • Debugging checklist covering all known silent failure modes

Why this matters

Arc's USDC-as-gas model makes ERC-4337 Paymasters particularly compelling — users can bridge, swap, and transact with zero native token holdings. But the three Arc-specific deployment constraints aren't documented anywhere, and each one produces a silent failure that is very difficult to diagnose without prior knowledge.

Testing

The contracts, addresses, and code samples in this guide were validated against the live Arc Testnet (5042002) running multiple bridge UserOps through Pimlico's bundler.

Covers the three Arc-specific constraints:
- Compile with evmVersion: "paris" (no PUSH0 on Arc Testnet)
- Keep entryPoint as constant to avoid 0x60c0 silent revert
- No nonReentrant on validatePaymasterUserOp (ERC-7562)

Also documents:
- USDC-as-gas decimal handling (18-dec native vs 6-dec ERC-20)
- EntryPoint v0.7 address and Pimlico bundler setup
- USDC Paymaster pattern with reservation system
- Deterministic finality and CCTP minFinalityThreshold guidance
- Full worked example: gasless USDC bridge burn via CCTP V2
- Debugging checklist with all known silent failure modes
Comment thread docs/erc-4337.md Outdated
Comment on lines +34 to +35
| **No PUSH0 opcode** | Arc Testnet (and Avalanche Fuji) reject the `PUSH0` opcode introduced in EVM Shanghai | Any Paymaster or AA wallet compiled with `solc ≥ 0.8.20` defaults to Shanghai; redeployments silently fail |
| **Single-immutable init code** | Contracts whose constructor initialises two or more `immutable` variables emit a `0x60c0` init prefix that reverts on Arc | Paymasters that store `entryPoint` **and** a second value as `immutable` will deploy with zero bytecode |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tested on arc testnet, there is PUSH0 opcode, and it supports more than one immutable init code

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right on both counts, @weikangsong — thank you for testing. I re-verified live against Arc Testnet just now (eth_chainId0x4cef52) and both constraints are gone:

PUSH0: state-override eth_call executing 0x5f5f5260205ff3 (PUSH0, PUSH0, MSTORE, PUSH1 32, PUSH0, RETURN) succeeds and returns the expected word.

Multi-immutable init code: a create-style eth_call with a 0x60c0-prefixed init code returns its runtime bytecode, and eth_estimateGas succeeds for the same deployment — including a variant with PUSH0 inside the init code itself (0xdb92 gas).

Both constraints were real when this guide was written in June from live deployment debugging, but a network upgrade since then (testnet is now on a Shanghai/Prague-era EVM) lifted them. The guide was stale.

Fixed in f182731: removed both deployment-constraint sections and the corresponding debugging-checklist rows, reframed the "what's different" table around the two things that still hold (USDC-as-gas decimal split, ERC-7562 validation rules), and added an explicit note that the evmVersion: "paris" workaround is no longer required — while noting contracts already compiled with it remain fully compatible, so nobody reading the old advice needs to redeploy. The rest of the guide (EntryPoint v0.7 usage, Pimlico setup, USDC Paymaster pattern with the reservation system, CCTP worked example, remaining debugging rows) is unaffected by the upgrade.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation ecosystem Component: ecosystem

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants