Skip to content
Layer 2 Scaling — Explained with Examples

Layer 2 Scaling — Explained with Examples

DodaTech Updated Jun 15, 2026 9 min read

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: 123456789

Zero-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.

FeatureOptimistic RollupZK Rollup
Finality~7 days (challenge period)Minutes (proof generation)
SecurityEconomic (fraud proofs)Cryptographic (ZK proofs)
EVM compatibilityHigh (Arbitrum, Optimism)Limited (zkSync Era improving)
Withdrawal time~7 daysMinutes
Gas savings10-100x100-1000x
ExamplesArbitrum, Optimism, BasezkSync, 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/100

Gas 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

  1. 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.
  2. 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.
  3. Forgetting to bridge native tokens: Sending ETH directly to an L2 address from L1 doesn’t work. You must use the official bridge.
  4. Ignoring L2-specific gas patterns: L2s have different cost models. Optimize for calldata on rollups (data costs more than computation).
  5. Using the wrong RPC provider: Each L2 has a unique RPC endpoint. Hardcoding Ethereum mainnet RPC will fail on L2 environments.

Practice Questions

  1. What is the main difference between Optimistic and ZK rollups?
  2. Why is there a 7-day withdrawal delay on Optimistic rollups?
  3. How does Polygon’s security differ from Arbitrum’s?
  4. What is a state channel?
  5. Which L2 solution offers the best EVM compatibility?

Answers:

  1. Optimistic rollups assume validity and use fraud proofs (7-day challenge). ZK rollups use cryptographic proofs for instant verification — no delay.
  2. 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.
  3. 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.
  4. 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.
  5. 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:

  1. Connects to Ethereum, Arbitrum, Optimism, zkSync, and Polygon RPCs
  2. Fetches current gas prices from each
  3. Simulates a standard ERC-20 transfer on each chain
  4. Calculates the total cost in USD (gwei × gas limit × ETH price)
  5. Estimates the time to finality on each chain
  6. Generates a comparison table with cost and security ratings
  7. 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.

Related topics: Ethereum, DeFi, Web3, Smart Contracts, NFTs

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro