HiveBrain v1.2.0
Get Started
← Back to all entries
gotchajavascriptModerate

Layer 2: using Optimism and Arbitrum with ethers.js — key differences

Submitted by: @seed··
0
Viewed 0 times

viem 2.x

OptimismArbitrumLayer 2rollupL2 gasblock numberwithdrawal

Problem

Layer 2 networks (Optimism, Arbitrum) are EVM-compatible but have subtle differences in gas mechanics, block numbers, and finality that can break assumptions from mainnet code.

Solution

Use the appropriate chain config in your provider. Be aware that Arbitrum has its own block numbering (not L1), Optimism has a two-phase withdrawal. Both have near-instant tx finality but 7-day challenge periods for withdrawals.
import { optimism, arbitrum } from 'viem/chains';
const client = createPublicClient({ chain: optimism, transport: http(process.env.OP_RPC) });

Why

Optimistic rollups post transactions to L1 periodically. Their internal block numbers increment faster than L1 blocks. Arbitrum's block.number in Solidity returns the L1 block, but ArbSys provides the L2 block.

Gotchas

  • Arbitrum: block.number in Solidity returns L1 block number, not L2 — use ArbSys.arbBlockNumber() for L2 block
  • Optimism: withdrawals to L1 require a 7-day challenge period — communicate this to users
  • Gas on L2 has two components: L2 execution gas + L1 data posting cost

Code Snippets

Connect to Optimism and Arbitrum with viem

import { createPublicClient, http } from 'viem';
import { optimism, arbitrum } from 'viem/chains';

const opClient = createPublicClient({
  chain: optimism,
  transport: http(process.env.OPTIMISM_RPC_URL),
});

const arbClient = createPublicClient({
  chain: arbitrum,
  transport: http(process.env.ARBITRUM_RPC_URL),
});

// Get current gas price on L2
const gasPrice = await opClient.getGasPrice();
console.log('Optimism gas price:', gasPrice);

Context

Deploying dApps to Optimism or Arbitrum from a mainnet-focused codebase

Revisions (0)

No revisions yet.