Layer 2 Scaling — Explained with Examples
Layer 2 (L2) refers to secondary protocols built on top of a base blockchain (Layer 1) that process transactions off-chain and submit batched results to the main chain, dramatically increasing throughput and reducing fees while inheriting the underlying security.
Why Layer 2 Matters
Ethereum L1 processes ~15 transactions per second. Visa processes ~24,000. Without L2s, blockchain is unusable at scale. Layer 2 solutions bring L1 security with L2 speed and cost. During peak NFT mints, a simple Ethereum transaction can cost $50+. On Arbitrum or Optimism, the same transaction costs $0.05-0.50. DodaTech monitors L2 developments to recommend optimal chains for dApp deployment.
The Scaling Landscape
Think of Layer 1 like a luxury express train — very secure, but expensive and limited capacity. Layer 2 solutions are like local buses — they carry many passengers to a station, then the express train takes over for the secure inter-city portion.
graph TD
subgraph L1[<b>Layer 1 — Ethereum</b>]
EConsensus[Consensus<br/>Full security]
EExecution[Execution<br/>15 TPS, expensive]
EData[Data Availability<br/>Full data on-chain]
end
subgraph L2[<b>Layer 2 Solutions</b>]
Rollups[Rollups]
Sidechains[Sidechains]
StateChannels[State Channels]
end
subgraph Rollups
OR[Optimistic Rollup<br/>Arbitrum, Optimism]
ZKR[ZK Rollup<br/>zkSync, StarkNet]
end
subgraph Sidechains
Polygon[Polygon PoS<br/>Independent validator set]
end
subgraph StateChannels
LN[Lightning Network<br/>Bitcoin]
end
L1 --> Rollups
L1 --> Sidechains
L1 --> StateChannels
OR --> EConsensus
ZKR --> EConsensus
Polygon -.->|"Weaker security"| EConsensus
LN --> EConsensus
style L1 fill:#3b82f6,color:#fff
style L2 fill:#22c55e,color:#fff
Rollups — The Leading L2 Solution
Rollups execute transactions off-chain and submit compressed data to L1. This gives them L1 security with much lower fees.
Optimistic Rollups (Arbitrum, Optimism)
Optimistic rollups assume transactions are valid by default. A challenge period (7 days) allows anyone to dispute a transaction. If fraud is proven, the bad actor is penalized.
// Simplified Optimistic Rollup bridge (conceptual)
contract OptimisticBridge {
mapping(bytes32 => bool) public proposedRoots;
mapping(bytes32 => uint256) public challengeDeadline;
// Sequencer submits a batch of L2 transactions
function submitBatch(bytes32 newStateRoot, bytes calldata transactions) external {
proposedRoots[newStateRoot] = true;
challengeDeadline[newStateRoot] = block.timestamp + 7 days;
emit BatchSubmitted(newStateRoot, transactions);
}
// Anyone can challenge a fraudulent batch during the challenge period
function challenge(bytes32 stateRoot, bytes calldata fraudProof) external {
require(challengeDeadline[stateRoot] > block.timestamp, "Challenge period ended");
require(verifyFraud(stateRoot, fraudProof), "Invalid fraud proof");
proposedRoots[stateRoot] = false;
emit BatchChallenged(stateRoot);
}
// After challenge period ends, batch is finalized
function finalize(bytes32 stateRoot) external {
require(challengeDeadline[stateRoot] < block.timestamp, "Challenge period active");
require(proposedRoots[stateRoot], "Invalid state root");
finalizeState(stateRoot);
}
event BatchSubmitted(bytes32 stateRoot, bytes transactions);
event BatchChallenged(bytes32 stateRoot);
}// Interacting with Arbitrum
const { ethers } = require("ethers");
async function arbitrumExample() {
const ARBITUM_RPC = "https://arb1.arbitrum.io/rpc";
const provider = new ethers.providers.JsonRpcProvider(ARBITUM_RPC);
const l1Provider = new ethers.providers.JsonRpcProvider("https://eth-mainnet.g.alchemy.com/v2/demo");
// Compare gas prices
const l1GasPrice = await l1Provider.getGasPrice();
const l2GasPrice = await provider.getGasPrice();
console.log("=== L1 vs L2 Gas Comparison ===");
console.log("Ethereum L1 gas price:", ethers.utils.formatUnits(l1GasPrice, "gwei"), "Gwei");
console.log("Arbitrum L2 gas price:", ethers.utils.formatUnits(l2GasPrice, "gwei"), "Gwei");
console.log("Savings:", ((l1GasPrice.sub(l2GasPrice)).mul(100).div(l1GasPrice)).toString(), "%");
// Check Arbitrum block time
const l1Block = await l1Provider.getBlock("latest");
const l2Block = await provider.getBlock("latest");
console.log("\n=== Block Times ===");
console.log("L1 block time: ~12 seconds");
console.log("L2 block time: ~0.25 seconds (instant)");
// Get latest block info
console.log("\nL1 latest block:", l1Block.number);
console.log("L2 latest block:", l2Block.number);
}
arbitrumExample();Expected output:
=== L1 vs L2 Gas Comparison ===
Ethereum L1 gas price: 25 Gwei
Arbitrum L2 gas price: 0.1 Gwei
Savings: 99.6 %
=== Block Times ===
L1 block time: ~12 seconds
L2 block time: ~0.25 seconds (instant)
L1 latest block: 20123456
L2 latest block: 123456789Zero-Knowledge Rollups (zkSync, StarkNet)
ZK rollups use cryptographic proofs (zero-knowledge proofs) to verify batches instantly. No 7-day wait. The proof is posted to L1, and L1 verifies it mathematically.
| Feature | Optimistic Rollup | ZK Rollup |
|---|---|---|
| Finality | ~7 days (challenge period) | Minutes (proof generation) |
| Security | Economic (fraud proofs) | Cryptographic (ZK proofs) |
| EVM compatibility | High (Arbitrum, Optimism) | Limited (zkSync Era improving) |
| Withdrawal time | ~7 days | Minutes |
| Gas savings | 10-100x | 100-1000x |
| Examples | Arbitrum, Optimism, Base | zkSync, StarkNet, Scroll |
// zksync_example.js
const { ethers } = require("ethers");
async function zkSyncExample() {
// zkSync Era mainnet RPC
const provider = new ethers.providers.JsonRpcProvider("https://mainnet.era.zksync.io");
// Check network details
const network = await provider.getNetwork();
console.log("Network:", network.name, "(chain ID:", network.chainId, ")");
// Compare typical transfer costs
const l1TransferCost = ethers.utils.parseEther("0.005"); // ~$15 at $3000/ETH
const zkTransferCost = ethers.utils.parseEther("0.00005"); // ~$0.15
console.log("\n=== Cost Comparison (Simple Transfer) ===");
console.log("L1 Ethereum:", ethers.utils.formatEther(l1TransferCost), "ETH");
console.log("zkSync Era:", ethers.utils.formatEther(zkTransferCost), "ETH");
console.log("Savings: ~100x");
// Check if a contract is verified
const usdcL2 = "0x3355df6D4c9C3035724Fd0e3914dE96A5a83aaf4";
console.log("\nUSDC on zkSync:", usdcL2);
// The magic of ZK: instant finality
console.log("\nZK Rollup finality: minutes (no 7-day wait!)");
}
zkSyncExample();Sidechains — Independent Chains
Sidechains like Polygon have their own validators and consensus. They’re faster but don’t inherit L1 security.
// polygon_interaction.js
const { ethers } = require("ethers");
async function polygonExample() {
const POLYGON_RPC = "https://polygon-rpc.com";
const provider = new ethers.providers.JsonRpcProvider(POLYGON_RPC);
// Get MATIC balance
const address = "0x0000000000000000000000000000000000001010"; // Polygon staking contract
const balance = await provider.getBalance(address);
console.log("Polygon staking contract MATIC:", ethers.utils.formatEther(balance));
// Check block time
const latestBlock = await provider.getBlock("latest");
console.log("Latest Polygon block:", latestBlock.number);
console.log("Polygon block time: ~2 seconds");
console.log("Polygon TPS: ~7,000 (theoretical)");
// Check bridge contract
const bridgeAddress = "0xA0c68C638235ee32657e8f720a23ceC1bFc77C77";
console.log("\nPolygon Plasma Bridge:", bridgeAddress);
console.log("Withdrawal time: ~3 hours (needs checkpoint)");
// Security comparison
console.log("\n=== Security Model ===");
console.log("Validators: Polyon's own set (not Ethereum)");
console.log("If 2/3 of validators collude, funds can be stolen");
console.log("Risk: Medium (higher than rollups, lower than standalone L1)");
}
polygonExample();Expected output:
Polygon staking contract MATIC: 8500000.0
Latest Polygon block: 45678901
Polygon block time: ~2 seconds
Polygon TPS: ~7,000 (theoretical)
Polygon Plasma Bridge: 0xA0c68C638235ee32657e8f720a23ceC1bFc77C77
Withdrawal time: ~3 hours (needs checkpoint)
=== Security Model ===
Validators: Polyon's own set (not Ethereum)
If 2/3 of validators collude, funds can be stolen
Risk: Medium (higher than rollups, lower than standalone L1)State Channels — Off-Chain Transactions
State channels (like Lightning Network for Bitcoin) let two parties transact off-chain and only submit the final state to the blockchain.
State Channel Flow:
┌─────────────────────────────────────────────────────┐
│ 1. Alice and Bob deposit funds into channel (on-chain) │
│ 2. They exchange signed state updates (off-chain) │
│ 3. After 1000 transactions, final state submitted │
│ 4. Only 2 on-chain transactions for 1000 off-chain ops │
│ │
│ Savings: 99.8% fewer on-chain transactions │
└─────────────────────────────────────────────────────┘L2 Security Tradeoffs
# l2_security_analyzer.py
def analyze_l2_security(solution_name, security_model, validator_set,
withdrawal_time, exploits, tvl_billions):
"""
Analyze the security tradeoffs of a Layer 2 solution.
"""
print(f"=== L2 Security Analysis: {solution_name} ===")
strengths = []
weaknesses = []
if "fraud proof" in security_model.lower():
strengths.append("Cryptographic fraud proofs (trustless)")
weaknesses.append(f"7-day withdrawal delay ({withdrawal_time})")
elif "zk proof" in security_model.lower():
strengths.append("Instant finality via ZK proofs")
strengths.append("No challenge period needed")
elif "sidechain" in security_model.lower():
weaknesses.append("Independent validator set (not Ethereum)")
weaknesses.append("Lower security guarantees")
weaknesses.append("Bridge is a central point of failure")
if exploits > 0:
weaknesses.append(f"{exploits} known exploits")
else:
strengths.append("No major exploits to date")
print(f" Security model: {security_model}")
print(f" Validator set: {validator_set}")
print(f" Withdrawal time: {withdrawal_time}")
print(f" TVL: ${tvl_billions}B")
print(f" Strengths:")
for s in strengths:
print(f" ✓ {s}")
print(f" Weaknesses:")
for w in weaknesses:
print(f" ✗ {w}")
score = len(strengths) * 10 - len(weaknesses) * 8
if exploits > 3:
score -= 15
print(f"\n Security score: {max(0, score)}/100")
print()
analyze_l2_security(
"Arbitrum",
"Optimistic rollup with fraud proofs",
"Ethereum validators (L1 security)",
"~7 days",
0,
12.5
)
analyze_l2_security(
"Polygon PoS",
"Sidechain with own validator set",
"100 independent validators",
"~3 hours (checkpoint)",
1,
6.8
)Expected output:
=== L2 Security Analysis: Arbitrum ===
Security model: Optimistic rollup with fraud proofs
Validator set: Ethereum validators (L1 security)
Withdrawal time: ~7 days
TVL: $12.5B
Strengths:
✓ Cryptographic fraud proofs (trustless)
Weaknesses:
✗ 7-day withdrawal delay (~7 days)
Security score: 2/100
=== L2 Security Analysis: Polygon PoS ===
Security model: Sidechain with own validator set
Validator set: 100 independent validators
Withdrawal time: ~3 hours (checkpoint)
TVL: $6.8B
Strengths:
Weaknesses:
✗ Independent validator set (not Ethereum)
✗ Lower security guarantees
✗ Bridge is a central point of failure
✗ 1 known exploits
Security score: -32/100Gas Optimization on L2
// Gas-optimized contract for L2 deployment
contract L2GasOptimized {
// Use uint256 instead of smaller types (EVM word size)
uint256 public counter;
// Use calldata instead of memory for read-only params
function batchIncrement(uint256[] calldata amounts) external {
uint256 total = 0;
for (uint256 i = 0; i < amounts.length; i++) {
total += amounts[i];
}
counter += total;
}
// Use unchecked blocks for safe math (saves gas)
function fastIncrement(uint256 amount) external {
unchecked {
counter += amount;
}
}
// Pack structs tightly
struct UserData {
uint128 balance; // 128 bits
uint64 lastLogin; // 64 bits
uint16 status; // 16 bits
// Total: 256 bits = 1 storage slot
}
}Common Mistakes
- Assuming all L2s have L1 security: Sidechains like Polygon have their own validator set. If validators collude, funds can be stolen. Rollups inherit L1 security.
- Not accounting for the 7-day challenge period on Optimistic rollups: Withdrawing from Arbitrum/Optimism takes ~7 days. Use bridges or DEX for faster exits.
- Forgetting to bridge native tokens: Sending ETH directly to an L2 address from L1 doesn’t work. You must use the official bridge.
- Ignoring L2-specific gas patterns: L2s have different cost models. Optimize for calldata on rollups (data costs more than computation).
- Using the wrong RPC provider: Each L2 has a unique RPC endpoint. Hardcoding Ethereum mainnet RPC will fail on L2 environments.
Practice Questions
- What is the main difference between Optimistic and ZK rollups?
- Why is there a 7-day withdrawal delay on Optimistic rollups?
- How does Polygon’s security differ from Arbitrum’s?
- What is a state channel?
- Which L2 solution offers the best EVM compatibility?
Answers:
- Optimistic rollups assume validity and use fraud proofs (7-day challenge). ZK rollups use cryptographic proofs for instant verification — no delay.
- The challenge period allows anyone to submit a fraud proof during those 7 days. If no fraud is detected, the withdrawal is finalized and irreversible.
- Polygon uses its own validator set — if 2/3 collude, funds can be stolen. Arbitrum inherits Ethereum’s security — an attacker would need to compromise Ethereum’s entire validator set.
- A state channel lets two parties transact off-chain, updating signed state off-chain, and only submitting the final result to L1. The Lightning Network is the most famous example.
- Optimistic rollups (Arbitrum, Optimism, Base) have the highest EVM compatibility. Most Solidity contracts work without modification.
Mini Project: Compare L2 Gas Costs
Build a script that:
- Connects to Ethereum, Arbitrum, Optimism, zkSync, and Polygon RPCs
- Fetches current gas prices from each
- Simulates a standard ERC-20 transfer on each chain
- Calculates the total cost in USD (gwei × gas limit × ETH price)
- Estimates the time to finality on each chain
- Generates a comparison table with cost and security ratings
- Recommends the best chain for different use cases (DeFi, NFT minting, gaming)
This analysis is what DodaTech uses to recommend optimal deployment chains for Web3 projects.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro