Skip to content

deploy Uniswap to Arc Mainnet (chain 5042)#144

Merged
david-uniswap merged 7 commits into
mainfrom
david-nick/arc-deploy
May 29, 2026
Merged

deploy Uniswap to Arc Mainnet (chain 5042)#144
david-uniswap merged 7 commits into
mainfrom
david-nick/arc-deploy

Conversation

@david-uniswap

Copy link
Copy Markdown
Collaborator

Summary

Deploys the Uniswap stack (v2 + v3 + v4 + SwapRouter02 + UniversalRouter v2.1.1) to Arc Mainnet (chain id 5042).

Five commits, deploy-only changes. No code changes outside the cherry-picked briefcase update from #142.

What's in this PR

Commit Description
534603a deploy UnsupportedProtocol to Arc (Step 0)
5c5f27d deploy v2/v3/v4 + SwapRouter02 to Arc (Step 3)
02fd176 update UR briefcase initcode to v2.1.1 (cherry-pick from #142)
e5d4153 deploy Universal Router v2.1.1 to Arc (Step 7)
c038023 record Arc deployments JSON + markdown

Arc-specific design choices

Arc's native gas token is USDC, with a dual-entry ERC-20 view at 0x3600...0000. The ERC-20 view does NOT implement deposit() or withdraw(). Per consensus in #acp-proj-arc with @eric Sanchirico and @alice Henshaw, WETH9 is wired to UnsupportedProtocol (0x8bcEaA40B9AcdfAedF85AdF4FF01F5Ad6517937f):

  • Every wrap/unwrap code path now reverts with UnsupportedProtocolError() (selector 0xea3559ef) instead of bare 0x reverts. Wallets and aggregators can detect and route around.
  • The same UnsupportedProtocol address is reused as the UR acrossSpokePool placeholder (Across not on Arc; command 0x40 reverts with the same named error).
  • Pure ERC-20 paths and V4 native-currency-sentinel paths work normally.
  • PR #779 in v4-core (CELO-style native ERC-20 double-spend fix) confirmed present in the briefcase: PoolManager.sol's sync() short-circuits on address(0) so the native dual-entry double-credit is impossible.

nativeCurrencyLabel is set to "USDC" on both v3 and v4 PositionDescriptors.

Deployed addresses (also in deployments/json/5042.json)

Contract Address
UnsupportedProtocol 0x8bcEaA40B9AcdfAedF85AdF4FF01F5Ad6517937f
Permit2 (pre-existing canonical) 0x000000000022D473030F116dDEE9F6B43aC78BA3
UniswapV2Factory 0x89e5DB8B5aA49aA85AC63f691524311AEB649eba
UniswapV2Router02 0x1f7d7550B1b028f7571E69A784071F0205FD2EfA
UniswapV3Factory 0xf0db7b58379503491d857dB50AC9ece64c653918
UniswapInterfaceMulticall 0x33e885eD0Ec9bF04EcfB19341582aADCb4c8A9E7
QuoterV2 0x7DfD4F31be6814D2906BDE155c3e1B146EAc1468
TickLens 0x9EB8600665b55d10C1eB2316Ca5127A9cA6E2E76
NFTDescriptor (lib) 0x2e9D45BB7b30549F5216813ada9A6b7982C5B3ED
NonfungibleTokenPositionDescriptor 0x73991a25C818Bf1f1128dEAaB1492D45638DE0D3
NonfungiblePositionManager 0x39654A85A4C05127f5Fd6ED22CAeC077A0fB1377
PoolManager (v4) 0x8366a39CC670B4001A1121B8F6A443A643e40951
PositionDescriptor (v4) 0x516b8a945700D6bBfDeDaa6dcFc4586bA60B8707
PositionManager (v4) 0x6049c9a0e26405C0985f9E3685c87d0aE917f82b
V4Quoter 0x8DC178efB8111bB0973dD9d722EbeFF267c98F94
StateView 0xF3334192d15450CDd385c8b70E03f9a6Bd9E673B
SwapRouter02 0x53Bf6B0684eC7eF91e1387dA3d1A1769Bc5A6F77
UniversalRouter v2.1.1 0x4fca4a51ab4f23a7447b3284fbd7d73289a89fb1

Plus two auto-deployed ProxyAdmins (v3 0xc2a60f5f..., v4 0x418195b3...), both owned by deployer 0x9701...3A52.

Dependency on #142

Commit 02fd176 is cherry-picked from #142 (still open). The Arc PR depends on #142's v2.1.1 briefcase initcode. Merge order options:

  1. Land update UR briefcase initcode to v2.1.1 #142 first → rebase this PR (cherry-picked commit drops cleanly as duplicate).
  2. Land this PR with the cherry-pick included → update UR briefcase initcode to v2.1.1 #142 becomes a no-op when it merges (same change).

Reviewer's call; the cherry-pick is byte-identical to #142.

Outstanding

  • Verification (Phase 6): explorer.arc.io is behind Cloudflare Access SSO. forge verify-contract cannot reach it from the CLI without a Circle service token. Following up separately on the auth path.
  • Ownership transfer (Phase 8): deployer EOA holds all owner / feeToSetter / proxyAdminOwner slots. Scheduled 1-2 weeks post-deploy, after Foundation forum post. Target address still TBD with Foundation (Arc is an independent L1; aliased L1 Timelock pattern does not apply).
  • Smoke tests: the existing V2/V3 smoke tests assume working WETH wrap/unwrap. Need Arc-aware variants (or just V4 native-currency smoke tests) before declaring Arc fully shipped.

Test plan

  • Onchain spot-checks (already done): PoolManager.owner == deployer, V3Factory.owner == deployer, NPM.WETH9() == UnsupportedProtocol, UnsupportedProtocol fallback reverts with 0xea3559ef. Verified.
  • Phase 6 contract verification on explorer.arc.io (blocked on Cloudflare Access auth path).
  • V4 smoke test using native-currency sentinel pool (TBD).

🤖 Generated with Claude Code

david-uniswap and others added 5 commits May 26, 2026 16:56
Step 0 of the Arc chain (5042) deploy. UnsupportedProtocol is being used
as the WETH9 placeholder for the base deploy (Arc's native is USDC, with
a dual-entry ERC-20 view at 0x3600...0000 that does not implement
deposit/withdraw) and as the spokePool placeholder for the upcoming
UR v2.1 follow-up (Across is not on Arc).

Deployed at 0x8bcEaA40B9AcdfAedF85AdF4FF01F5Ad6517937f.
Tx: 0x779c69c6887c1088030cf6e958bd37d6d34344ba3bd851a9bf96c291e9d70ce1.

deployments/json/5042.json will be regenerated via forge-chronicles
after Step 7 (UR v2.1) in one pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Step 3 of the Arc chain (5042) deploy. Base contracts wired against the
UnsupportedProtocol address (0x8bcEaA40...937f) deployed in Step 0 as
the WETH9 placeholder. Permit2 pre-seeded at canonical address.

19 broadcast txs, 0 reverts, total cost 1.045 USDC at 20 gwei. Deployer
EOA holds all owner / feeToSetter / proxyAdminOwner slots; ownership
transfer to Foundation-designated address scheduled 1-2 weeks post-
deploy (Phase 8).

Key addresses:
- UniswapV2Factory:           0x89e5DB8B5aA49aA85AC63f691524311AEB649eba
- UniswapV2Router02:          0x1f7d7550B1b028f7571E69A784071F0205FD2EfA
- UniswapV3Factory:           0xf0db7b58379503491d857dB50AC9ece64c653918
- NonfungiblePositionManager: 0x39654A85A4C05127f5Fd6ED22CAeC077A0fB1377
- PoolManager (v4):           0x8366a39CC670B4001A1121B8F6A443A643e40951
- PositionManager (v4):       0x6049c9a0e26405C0985f9E3685c87d0aE917f82b
- SwapRouter02:               0x53Bf6B0684eC7eF91e1387dA3d1A1769Bc5A6F77

nativeCurrencyLabel set to "USDC" on both v3 and v4 PositionDescriptors
to reflect Arc's native asset.

deployments/json/5042.json will be regenerated via forge-chronicles
after Step 7 (UR v2.1) in one pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
src/pkgs/universal-router is a git submodule. The briefcase hex literal
in UniversalRouterDeployer.sol was last regenerated against an old
submodule pin that predated the v2.1.1 commit (PR #470 upstream). The
monorepo's submodule pin has since advanced past v2.1.1, but no one
re-ran ./script/util/create_briefcase.sh, so deploys via the briefcase
were silently shipping v2.1.0 bytecode.

This patch rewrites only the hex literal in UniversalRouterDeployer.sol
with the v2.1.1 bytecode. The briefcase protocols/ source reference
files are intentionally NOT touched in this PR — they're documentation
and can drift relative to the deployer without affecting deployments.
A follow-up can sync them when convenient.

Bytecode diff:
- Old size:     23,587 bytes
- New size:     26,404 bytes (~12% larger)
- Old keccak:   0x7171fed0bc0dd1a41b55969fe1ebdb60d3eeb80750c3fa8d7230ea06142db561
- New keccak:   0x6dba80c0116a490d48657845492bb38374489ed49c296ac50614265f97221510

v2.1.0 → v2.1.1 brings:
- PAY_PORTION_FULL_PRECISION command (slot 0x07) with 1e18 precision
- Per-hop slippage on v2/v3 swaps via minHopPriceX36
- minHopPriceX36 field on V4 ExactInputSingleParams struct
- Command space expanded (mask 0x3f → 0x7f)
- v2 fee-on-transfer slippage fix (uses actual balance change)
- OZ audit fixes m01, l03, n05, n08

Verification:
- forge build clean
- New initcode keccak matches a fresh forge compilation of the current
  submodule pin's UniversalRouter source.
Step 7 of the Arc chain (5042) deploy. UR v2.1.1 deployed via the
canonical CREATE2 deployer (0x4e59...956c) at
0x4fca4a51ab4f23a7447b3284fbd7d73289a89fb1.

Wired against the base contracts deployed in Step 3:
- permit2:                canonical 0x000...22D473...
- weth9:                  UnsupportedProtocol 0x8bcEaA40...937f (Step 0)
- v2Factory:              0x89e5DB8B...9eba
- v3Factory:              0xf0db7b58...3918
- v4PoolManager:          0x8366a39C...0951
- v3NFTPositionManager:   0x39654A85...1377
- v4PositionManager:      0x6049c9a0...f82b
- acrossSpokePool:        UnsupportedProtocol 0x8bcEaA40...937f (Across
                          not on Arc; command 0x40 reverts with
                          UnsupportedProtocolError() selector 0xea3559ef)

protocols.swap-router-contracts.deploy=false in the task file to avoid
the duplicate-SwapRouter02 deploy landmine on subsequent runs.

Briefcase requires PR #142 (cherry-picked at 02fd176) for v2.1.1
initcode. PR #142 should land in main independently; this branch can
rebase afterwards or merge cleanly.

Tx: 0xf07bb4c6eaccb5b7e128625b0c4fc6bc79f727f9b647a6e81a886bde905345b8
Cost: 0.107 USDC. Deployer balance after: 9.85 USDC.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replayed forge-chronicles against each broadcast (Step 0, Step 3, Step 7)
to build deployments/json/5042.json with all 18 contracts in .latest and
3 history entries.

Manual patches per the chronicles-quirks documented in the
uniswap-new-chain-deploy skill:

- NonfungibleTokenPositionDescriptor: chronicles couldn't disambiguate
  the v3 NFT descriptor's TransparentUpgradeableProxy from other proxy
  CREATE entries in the Step 3 broadcast. Patched manually with proxy
  metadata (impl 0x6F84..., proxy 0x73991a25..., proxyAdmin
  0xc2a60f5f...) extracted from the broadcast file + EIP-1967 admin
  slot.
- Permit2: pre-existing canonical contract on Arc, not in any broadcast
  file. Added with a note.
- spokePool address truncation in the UR history entry: chronicles
  occasionally drops a trailing hex char; patched back to the full
  0x8bcEaA40B9AcdfAedF85AdF4FF01F5Ad6517937f.
- deployments/index.md chain name: chronicles defaulted to
  "Chain 5042" for unknown-to-it Arc; restored to "Arc Mainnet".

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ericneil-sanc
ericneil-sanc previously approved these changes May 27, 2026
@david-uniswap david-uniswap requested a review from gretzke May 27, 2026 16:09
@david-uniswap david-uniswap marked this pull request as ready for review May 27, 2026 16:09
Comment thread src/briefcase/deployers/universal-router/UniversalRouterDeployer.sol Outdated
Calibur (CaliburEntry) deployed via canonical CREATE2 deployer at the
shared vanity address 0x000000009b1d0af20d8c6d0a44e162d11f9b8f00
(salt 0x...eca2ad36bee3874a279d0010). Matches the Calibur address on
every other chain that has it (Tempo, etc.).

ERC7914Detector deployed via CREATE2 at
0xc470458fc6a7e43471b31e6a2eb2612215a7102e (same as Tempo, since the
detector's initcode binds the Calibur address as a constructor arg
and Calibur lives at the same canonical address everywhere).

Pre-deploy verification:
- Pectra/EIP-7702 active on chain: confirmed by STATICCALL-ing the
  BLS12-381 G1ADD precompile at 0x0b via init-code probe (returndatasize
  > 0). EIP-2537 and EIP-7702 both ship in Pectra/Prague.
- CREATE2 deployer at canonical 0x4e59...956C: present.
- Calibur target address: empty pre-deploy.

Deploy details:
- Deployer: 0x9701fb0aDe1E269c8f64Ec0C7b3cfADB31A13A52 (same EOA used
  for v2/v3/v4/UR Arc deploys).
- CaliburEntry tx: 0xd4a920ba5642739caaaa0c0aa7f2a13b0d43b1877be35407197d04293ff40dca
  (block 2104601, 5,332,636 gas).
- ERC7914Detector tx: 0x8d33c8e683b9c779978cec88bd487896dd2fee5dbb9bd0808cad243e8da741b5
  (block 2104605, 232,624 gas).
- Total cost: 0.139 ETH at 25 gwei (base fee 20 gwei).

First broadcast attempt at 1 gwei stuck in mempool (under Arc's 20-gwei
base fee); replaced via re-broadcast at 25 gwei. Captured as a forge
gas-price lesson in the uniswap-new-chain-deploy skill.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
# Conflicts:
#	src/briefcase/deployers/universal-router/UniversalRouterDeployer.sol
@david-uniswap david-uniswap merged commit 4460a88 into main May 29, 2026
4 checks passed
@david-uniswap david-uniswap deleted the david-nick/arc-deploy branch May 29, 2026 18:35
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.

3 participants