The Scaling Challenge
Ethereum mainnet processes approximately 15-30 transactions per second (TPS), which is far too slow for mass adoption. During peak usage, gas fees can spike to hundreds of dollars per transaction. Layer 2 (L2) solutions address this by processing transactions off the Ethereum mainnet (Layer 1) while inheriting its security guarantees. L2s can achieve thousands of TPS at a fraction of the cost.
L2 Scaling Approaches
- Optimistic Rollups: Assume transactions are valid by default, use fraud proofs to challenge invalid ones. 7-day withdrawal period. (Optimism, Arbitrum, Base)
- ZK-Rollups: Generate cryptographic validity proofs for every batch of transactions. Faster finality, no challenge period. (zkSync, StarkNet, Polygon zkEVM, Scroll)
- State Channels: Two parties transact off-chain and only settle the final state on L1. Best for repeated interactions between the same parties. (Lightning Network for Bitcoin)
- Validiums: Like ZK-Rollups but store data off-chain. Even cheaper but with different security tradeoffs.
Optimistic Rollups
Optimistic Rollups batch hundreds of transactions into a single L1 transaction. They are "optimistic" because they assume all batched transactions are valid. If someone detects an invalid transaction, they can submit a fraud proof during a challenge period (typically 7 days). If the fraud proof succeeds, the invalid batch is reverted and the sequencer is penalized.
Major L2 Networks
| Network | Type | TPS | Key Feature |
|---|---|---|---|
| Arbitrum One | Optimistic | ~4,000 | Largest TVL, Nitro engine |
| Optimism (OP Mainnet) | Optimistic | ~2,000 | OP Stack, Superchain vision |
| Base | Optimistic | ~2,000 | Coinbase L2, built on OP Stack |
| zkSync Era | ZK-Rollup | ~2,000 | Account abstraction native |
| Polygon zkEVM | ZK-Rollup | ~2,000 | EVM-equivalent ZK proofs |
Deploying to L2 with Hardhat
// hardhat.config.ts — Add L2 networks
import { HardhatUserConfig } from "hardhat/config";
import "@nomicfoundation/hardhat-toolbox";
const config: HardhatUserConfig = {
solidity: "0.8.24",
networks: {
// Arbitrum
arbitrumOne: {
url: "https://arb-mainnet.g.alchemy.com/v2/YOUR_KEY",
accounts: [process.env.PRIVATE_KEY!],
chainId: 42161,
},
arbitrumSepolia: {
url: "https://arb-sepolia.g.alchemy.com/v2/YOUR_KEY",
accounts: [process.env.PRIVATE_KEY!],
chainId: 421614,
},
// Optimism
optimism: {
url: "https://opt-mainnet.g.alchemy.com/v2/YOUR_KEY",
accounts: [process.env.PRIVATE_KEY!],
chainId: 10,
},
// Base
base: {
url: "https://base-mainnet.g.alchemy.com/v2/YOUR_KEY",
accounts: [process.env.PRIVATE_KEY!],
chainId: 8453,
},
baseSepolia: {
url: "https://base-sepolia.g.alchemy.com/v2/YOUR_KEY",
accounts: [process.env.PRIVATE_KEY!],
chainId: 84532,
},
},
etherscan: {
apiKey: {
arbitrumOne: process.env.ARBISCAN_API_KEY!,
optimisticEthereum: process.env.OPTIMISTIC_API_KEY!,
base: process.env.BASESCAN_API_KEY!,
},
},
};
// Deploy: npx hardhat run scripts/deploy.ts --network arbitrumSepolia
// Verify: npx hardhat verify --network arbitrumSepolia CONTRACT_ADDRESS
Multi-Chain Frontend Configuration
// wagmi config supporting multiple L2s
import { createConfig, http } from 'wagmi';
import { mainnet, arbitrum, optimism, base } from 'wagmi/chains';
export const config = createConfig({
chains: [mainnet, arbitrum, optimism, base],
transports: {
[mainnet.id]: http(),
[arbitrum.id]: http('https://arb-mainnet.g.alchemy.com/v2/KEY'),
[optimism.id]: http('https://opt-mainnet.g.alchemy.com/v2/KEY'),
[base.id]: http('https://base-mainnet.g.alchemy.com/v2/KEY'),
},
});
// Contract addresses per chain
const CONTRACT_ADDRESSES: Record<number, string> = {
1: '0xMainnetAddress...',
42161: '0xArbitrumAddress...',
10: '0xOptimismAddress...',
8453: '0xBaseAddress...',
};
// Hook to get the right address for the connected chain
import { useAccount } from 'wagmi';
function useContractAddress() {
const { chain } = useAccount();
return chain ? CONTRACT_ADDRESSES[chain.id] : undefined;
}
Bridging Between L1 and L2
Moving assets between L1 and L2 requires bridges. Each L2 has a native bridge that is the most secure option, as it inherits the security of the rollup itself. Third-party bridges (like Across, Stargate, Hop) offer faster transfers but introduce additional trust assumptions. When bridging from an Optimistic Rollup back to L1, the native bridge requires a 7-day challenge period. ZK-Rollup withdrawals are faster since validity proofs provide immediate finality.
L2 Development Tips
- Same Solidity, different costs: Your contracts deploy the same way, but gas costs are 10-100x cheaper on L2
- L1 data costs dominate: On rollups, the main cost is posting transaction data to L1. EIP-4844 (blobs) significantly reduces this.
- Test on L2 testnets: Use Arbitrum Sepolia, Base Sepolia, or OP Sepolia before mainnet deployment
- Consider L2-specific features: Some L2s offer native account abstraction (zkSync) or custom precompiles
- Cross-chain messaging: Use the rollup's native messaging system for L1-L2 communication