Developing a Rollup Solution (Optimistic/ZK)
A rollup is an L2 solution that executes transactions outside the main blockchain (off-chain) and publishes the result on L1. Two fundamentally different approaches to proving the correctness of these results divide the space into Optimistic Rollups and ZK Rollups. Choosing between them is one of the key architectural decisions that determines the entire development stack.
Optimistic vs ZK: Fundamental Difference
Optimistic Rollup considers transactions correct by default ("optimistically"). If someone thinks a transaction is fraudulent — they submit a fraud proof during the challenge window (usually 7 days). If the fraud proof is accepted — the transaction is reverted, the challenger gets a reward, the sequencer loses stake.
ZK Rollup publishes along with the transaction batch a cryptographic proof of correctness (validity proof). L1 verifies the proof via a smart contract. If the proof passes — transactions are guaranteed to be correct without trust in the sequencer.
| Characteristic | Optimistic Rollup | ZK Rollup |
|---|---|---|
| L1 Finality | 7 days (withdrawal) | ~1–30 min (after proof publication) |
| Trust Assumptions | Honest challenger (1-of-N) | Correctness of ZK scheme + verifier code |
| Computation Overhead | Low (no proof generation) | High (proof generation CPU/GPU intensive) |
| EVM Compatibility | Full (EVM-equivalent) | Partial or full (depends on implementation) |
| Development Complexity | Moderate | High |
| Maturity | High (Arbitrum, OP since 2021) | Growing (zkSync, Scroll, Polygon zkEVM) |
For most application-specific rollup tasks in 2024, the choice is OP Stack or Arbitrum Orbit. ZK stack is justified if: you need fast finality, have specific privacy requirements, or need a rollup for custom ZK logic.
OP Stack: Deploying an Optimistic Rollup
OP Stack — a framework from Optimism for creating your own L2/L3 chains (superchain). Used by Base, Zora, Mode, Blast.
OP Stack Components
L1 (Ethereum) ← → op-batcher (publishes tx data to L1)
op-proposer (publishes state roots to L1)
L2:
op-geth (modified geth, execution engine)
op-node (consensus/derivation layer, reads L1 data)
Requirements for Development/Testnet
L1 node (or Sepolia RPC endpoint from Alchemy/Infura)
L2 server: 8 CPU, 16 GB RAM, 500 GB SSD
Deploy OP Stack via optimism-package
# Install kurtosis (orchestration tool)
curl -s https://raw.githubusercontent.com/kurtosis-tech/kurtosis/main/install.sh | bash
# Run full OP Stack locally
kurtosis run github.com/ethpandaops/optimism-package \
--args-file local-config.yaml
Configuration local-config.yaml:
optimism_package:
chains:
- participants:
- el_type: op-geth
cl_type: op-node
network_params:
network_id: "42069"
seconds_per_slot: 2
name: "my-rollup"
additional_services:
- blockscout # explorer
- prometheus_grafana
Production Deploy: L1 Contracts
git clone https://github.com/ethereum-optimism/optimism
cd optimism
# Install dependencies
pnpm install
pnpm build
# Set environment variables
export L1_RPC_URL="https://eth-sepolia.g.alchemy.com/v2/YOUR_KEY"
export PRIVATE_KEY="0x..." # deployer key with ETH on L1
# Deploy L1 smart contracts (DisputeGameFactory, OptimismPortal, L1CrossDomainMessenger...)
cd packages/contracts-bedrock
forge script scripts/Deploy.s.sol:Deploy \
--rpc-url $L1_RPC_URL \
--private-key $PRIVATE_KEY \
--broadcast \
--verify
After deploying contracts, a deployments/ directory with addresses is saved — they're needed for L2 component configuration.
Arbitrum Orbit: Alternative for L2/L3
Arbitrum Orbit allows creating an L2 (relative to Ethereum) or L3 (relative to Arbitrum One/Nova) chain:
# Orbit chain deployer
git clone https://github.com/OffchainLabs/orbit-setup-script
cd orbit-setup-script
yarn install
# Configuration
cp config.example.json config.json
# Edit: chain ID, owner address, validators
# Deploy (on Sepolia or Arbitrum Sepolia for testnet)
PRIVATE_KEY=0x... yarn run deploy-rollup-chain
Orbit gives choice: AnyTrust (data availability via DAC committee, cheaper) or Rollup (data on L1, safer).
ZK Rollup: ZK Stack (zkSync)
For ZK rollup development, the most mature framework — ZK Stack from Matter Labs:
# Install ZK Stack CLI
curl -L https://raw.githubusercontent.com/matter-labs/zksync-era/main/zkstack_cli/zkstackup/install | bash
# Initialize ecosystem (deploy L1 node, postgres, etc. via docker)
zkstack ecosystem init --dev
# Create new chain
zkstack chain create \
--chain-name my-zk-chain \
--chain-id 12345 \
--prover-mode no-proofs \ # for development without ZK proofs
--wallet-creation localhost
# Deploy L1 contracts
zkstack chain deploy-l1 --chain my-zk-chain
# Run
zkstack server --chain my-zk-chain
In production mode instead of --prover-mode no-proofs you need a real prover. Boojum (zkSync Era's proof system) requires a GPU server (A100/H100) or scaled CPU cluster for proof generation.
Proof Generation: Most Expensive in ZK
For ZK rollup production deployment, the most expensive component is the prover. Options:
Own prover cluster — requires serious hardware:
GPU prover: 1x NVIDIA A100 80GB → ~100-200 TPS throughput
CPU prover: 64-core AMD EPYC → 10-20x slower than GPU
Outsourced proving — Gevulot, Lagrange, Fermah (proof marketplace, pay for proof generation).
Validium mode — data stored off-chain in Data Availability Committee, not published on L1. Much cheaper, but reduces security guarantees.
Data Availability: Key Component
Rollup must publish transaction data so anyone can recalculate state. Options:
Ethereum calldata — maximum security, most expensive. After EIP-4844 (blobs) 10-100x cheaper.
EIP-4844 Blobs — with Dencun upgrade (Ethereum March 2024) rollups publish data as blob transactions. Blobs are stored 18 days, cost order of magnitude cheaper than calldata.
Celestia / EigenDA / Avail — external DA layers. Even cheaper, but require trust in a separate network.
For new rollup: use EIP-4844 blobs as DA — optimal balance of cost and security for 2024–2025.
Sequencer: Centralization and Paths to Decentralization
All production rollups today have a centralized sequencer — this is an honest compromise with performance. Current state:
- Arbitrum — working on BoLD (Bounded Liquidity Delay) for permissionless validation
- Optimism — Bedrock + fault proofs model (Cannon), moving toward decentralized sequencer
- zkSync — centralized sequencer, roadmap to shared sequencing
For custom rollup: centralized sequencer at launch is normal, main thing — escape hatch mechanism (ability to withdraw funds without sequencer consent via L1 directly).
Development Stages
| Phase | Content | Timeline |
|---|---|---|
| Stack choice and architecture | OP Stack vs Orbit vs ZK Stack, DA choice | 1 week |
| Testnet deploy (devnet) | Local environment, testing | 2–3 weeks |
| L1 contracts and bridges | Deploy, bridge testing | 2 weeks |
| L2 infrastructure | Sequencer, RPC, explorer | 2–3 weeks |
| Public testnet | Load testing, bug bounty | 2–4 weeks |
| Mainnet | Gradual launch, monitoring | 1–2 weeks |
| ZK prover (ZK only) | Setup, optimization, outsourcing | +4–8 weeks |
Realistic timeline from start to production mainnet: 2–4 months for Optimistic (OP Stack/Orbit), 4–6+ months for ZK with real proofs.
Monitoring and Operational Security
// Monitor rollup health: check that batcher doesn't lag
const l1Block = await l1Provider.getBlockNumber()
const latestBatch = await l2Bridge.latestBatchIndex()
// If gap grows — batcher not publishing data
// Alert if withdrawals don't finalize
const pendingWithdrawals = await portal.pendingWithdrawals()
if (pendingWithdrawals > THRESHOLD) {
alert('Withdrawal queue growing, check proposer')
}
For production rollup, 24/7 monitoring is mandatory with alerts: sequencer state, batcher lag, proposer health, bridge balance, and dispute window for Optimistic rollup.







