Skip to content

robinhood chain deployments#137

Merged
david-uniswap merged 8 commits into
mainfrom
david-nick/robinhood-chain
May 29, 2026
Merged

robinhood chain deployments#137
david-uniswap merged 8 commits into
mainfrom
david-nick/robinhood-chain

Conversation

@david-uniswap

Copy link
Copy Markdown
Collaborator

Pull Request

Description

Uniswap v2/v3/v4 deployment to Robinhood Chain (chain ID 4663). Arbitrum Orbit chain, parent L1 mainnet, ArbOS 51, ETH gas token.

Pre-existing infrastructure (not deployed by this run)

  • Permit2: 0x000000000022D473030F116dDEE9F6B43aC78BA3 (canonical)
  • WETH9: 0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73 (Robinhood-provided)
  • CREATE2 deterministic deployer: 0x4e59b44847b379578588920cA78FbF26c0B4956C
  • Multicall3: 0xcA11bde05977b3631167028862bE2a173976CA11 (Offchain Labs predeploy)

Newly deployed

  • v2: UniswapV2Factory, UniswapV2Router02
  • v3: UniswapV3Factory, UniswapInterfaceMulticall, QuoterV2, TickLens, NonfungibleTokenPositionDescriptor (proxy + impl + ProxyAdmin), NonfungiblePositionManager, NFTDescriptor (library)
  • swap-router-contracts: SwapRouter02
  • v4: PoolManager, PositionDescriptor (proxy + impl + ProxyAdmin), PositionManager, V4Quoter, StateView

Full address list in deployments/json/4663.json.

Deploy notes

Deploy was split across two passes. The first attempted full deploy landed v2/v3 factories on chain but halted on a setOwner(self) no-op where forge reported a failed receipt due to an Arbitrum gas accounting edge case. The second pass marked the three already-deployed contracts as deploy: false with their addresses and ran the remaining 14 txs. All on-chain wiring verified correct end-to-end.

Verification

All 19 deployed contracts have source code viewable on Blockscout:

  • 15 directly verified via forge verify-contract
  • 2 EIP-1967 proxies auto-linked to their verified impls
  • 1 ProxyAdmin twin-matched to its identical verified counterpart
  • 1 library (NFTDescriptor) source visible via its verified parent NonfungibleTokenPositionDescriptor; direct standalone library verification on Blockscout hits a known quirk

Blockscout: https://8crv4vmq6tiu1yqr.blockscout.com/

Ownership

Currently held by deployer EOA 0x9701fb0aDe1E269c8f64Ec0C7b3cfADB31A13A52. Transfer to aliased L1 Uniswap Timelock (0x2BAD8182C09F50C8318D769245BEA52C32BE46CD) planned in a follow-up after a verification window.

Follow-ups (separate PRs)

  • UniversalRouter (v2.0 or v2.1, contingent on Across SpokePool availability on Robinhood)
  • Ownership transfer to aliased L1 Uniswap Timelock
  • Subgraph deployment for indexing

How Has This Been Tested?

End-to-end smoke tests for v2, v3, and v4 (LP + swap where applicable) were written and dry-run successfully against a local Nitro follower node syncing chain 4663. Scripts live in script/smoke/ (not committed in this PR — they're local validation tools).

On-chain sanity check covered:

  • v2 Router → factory + WETH wiring
  • v3 Factory → owner + all 4 fee tiers (500/3000/10000/100)
  • v3 NPM → factory + WETH9 + token descriptor (proxy)
  • v4 PoolManager → owner = deployer EOA
  • v4 PositionManager → poolManager + permit2 (canonical) + WETH
  • SwapRouter02 → v2 factory + v3 factory + NPM + WETH
  • Both ProxyAdmins → owner = deployer EOA

Checklist

Before deployment (N/A — this PR deploys bytecode from the locked-down briefcase; contract-level testing/audits live in their respective source repos)

  • deployment scripts ready (Deploy-all.s.sol + task-pending.json for 4663)

After deployment

  • transfer ownership after deployments — planned for a follow-up after a 1-2 week verification window
  • generate deployment/upgrade log files (chronicles output committed)

Considerations

  • I have performed a self-review of my own code
  • I have made corresponding changes to the documentation (deployments/4663.md + deployments/index.md)
  • My changes generate no new warnings

Additional context

Robinhood Chain uses an Arbitrum Orbit setup with a sequencer-only write endpoint and a Blockscout read endpoint. The deploy was executed against a self-hosted Nitro v3.10.0 follower node (not committed to repo) that aggregates reads from the L1 batches via Quicknode + a public beacon RPC, and forwards writes to the sequencer.

Uniswap v2/v3/v4 deployment to Robinhood Chain (chain ID 4663).
Arbitrum Orbit chain, parent L1 mainnet, ArbOS 51, ETH gas token.

Pre-existing infrastructure (not deployed by this run):
- Permit2:          0x000000000022D473030F116dDEE9F6B43aC78BA3 (canonical)
- WETH9:            0x0Bd7D308f8E1639FAb988df18A8011f41EAcAD73 (Robinhood-provided)
- CREATE2 deployer: 0x4e59b44847b379578588920cA78FbF26c0B4956C

Newly deployed:
- v2: UniswapV2Factory, UniswapV2Router02
- v3: UniswapV3Factory, UniswapInterfaceMulticall, QuoterV2, TickLens,
      NonfungibleTokenPositionDescriptor (proxy + impl + ProxyAdmin),
      NonfungiblePositionManager, NFTDescriptor (library)
- swap-router-contracts: SwapRouter02
- v4: PoolManager, PositionDescriptor (proxy + impl + ProxyAdmin),
      PositionManager, V4Quoter, StateView

Deploy was split across two passes. The first attempted full deploy
landed v2/v3 factories on chain but halted on a setOwner(self) no-op
where forge reported a failed receipt due to an Arbitrum gas accounting
edge case. The second pass marked the three already-deployed contracts
as deploy:false with their addresses and ran the remaining 14 txs.
All on-chain wiring verified correct end-to-end.

Ownership held by deployer EOA 0x9701fb0aDe1E269c8f64Ec0C7b3cfADB31A13A52.
Transfer to aliased L1 Uniswap Timelock (0x2BAD8182C09F50C8318D769245BEA52C32BE46CD)
planned in a follow-up after a verification window.

Blockscout source-code verification deferred to a follow-up PR.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
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 (Arc, Tempo, etc.).

ERC7914Detector deployed via CREATE2 at
0xc470458fc6a7e43471b31e6a2eb2612215a7102e (same as Arc + 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 Robinhood: confirmed via BLS12-381 G1ADD
  precompile probe (EIP-2537, bundled with EIP-7702 in Pectra).
- CREATE2 deployer at canonical 0x4e59...956C: present.
- Calibur target address: empty pre-deploy.

Deploy details:
- Arbitrum Orbit chain, parent L1 mainnet, ArbOS 51.
- Deployer: 0x9701fb0aDe1E269c8f64Ec0C7b3cfADB31A13A52 (swap-test EOA).
- CaliburEntry tx: 0xfc5d58bca306b47501d741bbbb88d8278f8f19d2bd44051076525b25d4b85a60
  (block 19833, 5,624,905 gas).
- ERC7914Detector tx: 0xd25a20ee2c22a20620ab0b73846ca31282be387a0ca618f180697f44fe778d0e
  (block 19834, 252,606 gas).
- Total cost: 0.000588 ETH at 0.1 gwei (`--with-gas-price 300000000`,
  ~3x base fee for headroom).

Broadcast routed through the self-hosted Nitro follower node at
localhost:8547 (write-forward to sequencer + local reads), the same
RPC setup used for the prior Robinhood v2/v3/v4 deploys.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Redeploys UniversalRouter using the regenerated briefcase (stacked on
briefcase initcode in that PR was frozen at a submodule pin that
predated the v2.1.1 commit upstream.

Deployed:
- UniversalRouter (v2.1.1): 0x8876789976decbfcbbbe364623c63652db8c0904
  Tx:                       0x422569c99e80a452d45680fbf16cf04cd4ae79cd2b0d7a6a89cf6603009ed1fa
  Initcode hash:            0x6dba80c0116a490d48657845492bb38374489ed49c296ac50614265f97221510
  Bytecode size:            26,404 bytes (vs 23,587 for v2.1.0)

UnsupportedProtocol (0x7332D11BD10d18A04B119Cd4671a96f3148002c4) is
unchanged — same source, same initcode hash, still deployed at the same
address. Reused as the `acrossSpokePool` placeholder.

Old v2.1.0 UR at 0x248a454ac3584c2a48d1fcb28d3910a6b6ea00af is moved to
.history in deployments/json/4663.json and labeled as orphaned. The
contract still exists onchain but nothing integrates with it.

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

Verification:
- Onchain immutables match expected wiring (SPOKE_POOL =
  UnsupportedProtocol, V3/V4 position managers, PoolManager).
- Bytecode dispatcher contains command 0x07 dispatch (4 instances of
  PUSH1 0x07 in the deployed bytecode).
- Deployed bytecode length matches compiled artifact length (49,095
  chars; differences are immutable bake-in only).
- V4 smoke test simulation passes against the new UR after updating
  ExactInputSingleParams struct to include minHopPriceX36 (smoke test
  update will land separately on david-nick/robinhood-smoke-tests).
- Blockscout verification passed on first attempt — no submodule
  alignment dance needed since briefcase now matches the current
  submodule pin.

Cost: 0.000555 ETH (5.55M gas at 0.1 gwei chain base fee).
forge-chronicles' index regen overwrites named chain labels with
"Chain N" fallbacks for chains not in its bundled chains.json. Restore
"Tempo Mainnet" (4217) and set "Robinhood Mainnet" (4663) explicitly.
deploy Universal Router 2.1.1 to Robinhood Chain (replaces #141)
gretzke
gretzke previously approved these changes May 29, 2026
@david-uniswap david-uniswap merged commit cc21694 into main May 29, 2026
4 checks passed
@gretzke gretzke deleted the david-nick/robinhood-chain branch May 29, 2026 22:57
david-uniswap added a commit that referenced this pull request Jun 3, 2026
Adds the standard SwapProxy entry to each deployments/json/{chainId}.json
`latest` block, matching the existing schema used by other CREATE2 / vanity
contracts (Permit2, CaliburEntry): {address, proxy, deploymentTxn, timestamp,
commitHash}. CREATE2 salt/initcode/build stay in .swapproxy-deploy/create2.json
(the registry never stores those).

Address 0x0000000085E102724e78eCd2F45DC9cA239Affad on all 13 chains. Timestamps
are the real per-chain deploy block times. Supersedes the legacy 0x02e5 entry
tracked in PR #150/#137.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

2 participants