Skip to Content
DocsBuild with AvailDeploy a Rollup on Avail DAOptimiumOP StackDeploy an Avail-Powered OP Stack Alt-DA Optimium

How to Use the OP Stack with Avail

Introduction

Embark on setting up your own Avail-Optimism chain. This guide targets Ethereum’s Sepolia testnet and Avail Turing testnet. For a detailed understanding, review the Optimism Documentation.

Prerequisites

Ensure you have installed the following software.

Installation commands are based on Ubuntu 20.04 LTS:

SoftwareVersion
GitOS default
Go1.21
Node^20
Pnpm8.5.6
MakeOS default
jqOS default
direnvLatest
Foundry^0.2.0
# Install Git sudo apt install -y git curl make jq # Install Go wget https://go.dev/dl/go1.21.linux-amd64.tar.gz tar xvzf go1.21.linux-amd64.tar.gz sudo cp go/bin/go /usr/bin/go sudo mv go /usr/lib echo export GOROOT=/usr/lib/go >> ~/.bashrc # Install Node.js curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - sudo apt-get install -y nodejs npm # Install Pnpm sudo npm install -g pnpm # Install Make sudo apt install -y make # Install jq sudo apt install -y jq # Install direnv sudo apt install -y direnv
Use the following releases while following the guide:
  • op-node/v1.9.1
  • op-proposer/v1.9.1
  • op-batcher/v1.9.1
  • op-geth v1.101408.0

Setup Avail DA-server

Run avail-da server ( manually ).

  1. Navigate to
git clone https://github.com/availproject/avail-alt-da-server.git cd avail-alt-da-server
  1. Build Avail DA Server: make da-server

  2. Run your DA sidecar: ./bin/avail-da-server ./cmd/avail --addr=localhost --port=8000 --avail.rpc=<WS url to an avail node> --avail.seed=<> --avail.appid=<>

Run using docker

  • Copy .env.example to .env. Fill the values inside.

  • Run the following commands:

    docker-compose build docker-compose up

Build the Adapter Source

  1. Clone and navigate to the Avail adapter:

    git clone https://github.com/ethereum-optimism/optimism.git cd optimism git fetch --tag --all git checkout v1.9.1 git submodule update --init --recursive
  2. Install modules:

    pnpm install
  3. Compile the necessary packages:

    make op-node op-batcher op-proposer pnpm build

Build the Optimism Geth Source

  1. Clone and navigate to op-geth:

    git clone https://github.com/ethereum-optimism/op-geth.git cd op-geth git fetch --tag --all git checkout v1.101408.0
  2. Compile op-geth:

    make geth

Get Access to a Sepolia Node

For deploying to Sepolia, access an L1 node using a provider like Alchemy or run your own Sepolia node.

Generate and Secure Keys

Create four essential accounts with private keys:

  • Admin (contract upgrade authority)
  • Batcher (publishes Sequencer data to L1)
  • Proposer (publishes L2 results to L1)
  • Sequencer (signs blocks on the p2p network)

You can use cast wallet in the contracts-bedrock package for key generation:

  1. In the Optimism repo, navigate to the contracts-bedrock package:

    cd ~/optimism/packages/contracts-bedrock
  2. Generate accounts:

    echo "Admin:" cast wallet new echo "Proposer:" cast wallet new echo "Batcher:" cast wallet new echo "Sequencer:" cast wallet new

    You should see an output similar to:

    Admin: Successfully created new keypair. Address: 0xc4A01194958DE0D90A876e8A5fc9D7B530072148 Private key: 0xb8e39bd94a210e410c4024e1cc91014de45a5eb1e42f3aa99a368b5a5ac19b45 Proposer: Successfully created new keypair. Address: 0xFC0374Ae658e46cA4022acA179d3cb6D8e1A4934 Private key: 0xa9bc1b3f5deb1e00251df68bf86e3493b25bc5430665433546f2f9aacc748d1a Batcher: Successfully created new keypair. Address: 0xD6857B5BE9468Be67d64ABaB48459378d5329b96 Private key: 0xe9cd8960fc7984a301d567b819e0c62871eb2c7239c2e66b8f319eaa45c3cbd5 Sequencer: Successfully created new keypair. Address: 0x33348817E4B1192D576C4f157e9a5EC93dc5392D Private key: 0xd98b49e11e4e0be9931017831395e6644a50c36285d08e14d1a479af5ee08675

    Record and securely store these key details. You’ll need to fund Admin, Proposer, and Batcher with Sepolia ETH (0.5 ETH for Admin, 0.2 ETH for Proposer, 0.1 ETH for Batcher).

⚠️

NOTE FOR PRODUCTION
Use secure hardware for key management in production environments. cast wallet is not designed for production deployments.

Network Configuration and Setup

After building the repositories, configure your chain settings in the contracts-bedrock package.

  1. Ensure you are in the contracts-bedrock sub-directory:

    cd ~/optimism/packages/contracts-bedrock
  2. Activate the environment with direnv:

    If you need to install direnv, ensure you also modify the shell configuration.

    direnv allow .

Core Contract Deployment

Deploy essential L1 contracts for the chain’s functionality:

  1. Update /optimism/packages/contracts-bedrock/deploy-config and update file getting_started.json.
cd packages/contracts-bedrock ./scripts/getting-started/config.sh
  1. Add the following at the bottom of the config generated:
"useAltDA": true, "daCommitmentType": "GenericCommitment", "daChallengeWindow": 160, "daResolveWindow": 160, "daBondSize": 1000000, "daResolverRefundPercentage": 0

Example config ( for reference purpose ):

{ "l1StartingBlockTag": "0x2c9f156ae1cc024817b920b41c102b23b5a7526e16220c517078341f9890e8bd", "l1ChainID": 11155111, "l2ChainID": 11155420, "l2BlockTime": 2, "l1BlockTime": 12, "maxSequencerDrift": 600, "sequencerWindowSize": 3600, "channelTimeout": 300, "p2pSequencerAddress": "0x15cb6e5fa6a7134F3f6f5a9130F70c1344162b77", "batchInboxAddress": "0xff00000000000000000000000000000000042069", "batchSenderAddress": "0x5bd31d51C4041108c238473f27BF5f72311b1bcF", "l2OutputOracleSubmissionInterval": 120, "l2OutputOracleStartingBlockNumber": 0, "l2OutputOracleStartingTimestamp": 1725740628, "l2OutputOracleProposer": "0x07B4c44290fD2Fba85d7924Fbf4A6499661bBe53", "l2OutputOracleChallenger": "0x79A953eAc59e40B3c7567a4cfc446c4B4912722f", "finalizationPeriodSeconds": 12, "proxyAdminOwner": "0x79A953eAc59e40B3c7567a4cfc446c4B4912722f", "baseFeeVaultRecipient": "0x79A953eAc59e40B3c7567a4cfc446c4B4912722f", "l1FeeVaultRecipient": "0x79A953eAc59e40B3c7567a4cfc446c4B4912722f", "sequencerFeeVaultRecipient": "0x79A953eAc59e40B3c7567a4cfc446c4B4912722f", "finalSystemOwner": "0x79A953eAc59e40B3c7567a4cfc446c4B4912722f", "superchainConfigGuardian": "0x79A953eAc59e40B3c7567a4cfc446c4B4912722f", "baseFeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000", "l1FeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000", "sequencerFeeVaultMinimumWithdrawalAmount": "0x8ac7230489e80000", "baseFeeVaultWithdrawalNetwork": 0, "l1FeeVaultWithdrawalNetwork": 0, "sequencerFeeVaultWithdrawalNetwork": 0, "gasPriceOracleOverhead": 0, "gasPriceOracleScalar": 1000000, "enableGovernance": true, "governanceTokenSymbol": "OP", "governanceTokenName": "Optimism", "governanceTokenOwner": "0x79A953eAc59e40B3c7567a4cfc446c4B4912722f", "l2GenesisBlockGasLimit": "0x1c9c380", "l2GenesisBlockBaseFeePerGas": "0x3b9aca00", "eip1559Denominator": 50, "eip1559DenominatorCanyon": 250, "eip1559Elasticity": 6, "l2GenesisFjordTimeOffset": "0x0", "l2GenesisRegolithTimeOffset": "0x0", "l2GenesisEcotoneTimeOffset": "0x0", "l2GenesisDeltaTimeOffset": "0x0", "l2GenesisCanyonTimeOffset": "0x0", "systemConfigStartBlock": 0, "requiredProtocolVersion": "0x0000000000000000000000000000000000000000000000000000000000000000", "recommendedProtocolVersion": "0x0000000000000000000000000000000000000000000000000000000000000000", "faultGameAbsolutePrestate": "0x03c7ae758795765c6664a5d39bf63841c71ff191e9189522bad8ebff5d4eca98", "faultGameMaxDepth": 44, "faultGameClockExtension": 0, "faultGameMaxClockDuration": 1200, "faultGameGenesisBlock": 0, "faultGameGenesisOutputRoot": "0x0000000000000000000000000000000000000000000000000000000000000000", "faultGameSplitDepth": 14, "faultGameWithdrawalDelay": 600, "preimageOracleMinProposalSize": 1800000, "preimageOracleChallengePeriod": 300, "useAltDA": true, "daCommitmentType": "GenericCommitment", "daChallengeWindow": 160, "daResolveWindow": 160, "daBondSize": 1000000, "daResolverRefundPercentage": 0 }
  1. Navigate to /optimism/packages/contracts-bedrock/deployments, and create avail-optimism directory:
cd ~/optimism/packages/contracts-bedrock/deployments mkdir avail-optimism
  1. Navigate to /optimism/packages/contracts-bedrock/ and the deploy contracts (this can take up to 15 minutes):
    DEPLOYMENT_OUTFILE=deployments/artifact.json \ DEPLOY_CONFIG_PATH=deploy-config/getting-started.json \ forge script scripts/deploy/Deploy.s.sol:Deploy --broadcast --private-key $GS_ADMIN_PRIVATE_KEY \ --rpc-url $L1_RPC_URL --slow
  2. L2 Allocs
CONTRACT_ADDRESSES_PATH=deployments/artifact.json DEPLOY_CONFIG_PATH=deploy-config/getting-started.json STATE_DUMP_PATH=deploy-config/statedump.json forge script scripts/L2Genesis.s.sol:L2Genesis --sig 'runWithStateDump()' --chain <YOUR_L2_CHAINID>
⚠️

If you see a nondescript error that includes EvmError: Revert and Script failed then you likely need to change the IMPL_SALT environment variable. This variable determines the addresses of various smart contracts that are deployed via CREATE2.

If the same IMPL_SALT is used to deploy the same contracts twice, the second deployment will fail.

You can generate a new IMPL_SALT by running direnv reload anywhere in the Avail Optimism Monorepo.

Setting Up L2 Configuration

After configuring the L1 layer, focus shifts to establishing the L2 infrastructure. This involves generating three key files:

  • genesis.json for the genesis block
  • rollup.json for rollup configurations
  • jwt.txt for secure communication between op-node and op-geth
  1. Navigate to the op-node directory:

    cd ~/optimism/op-node
  2. Run the following command, ensuring you replace <RPC> with your specific L1 RPC URL. This generates the genesis.json and rollup.json files:

    go run cmd/main.go genesis l2 \ --deploy-config ../packages/contracts-bedrock/deploy-config/getting-started.json \ --l1-deployments ../packages/contracts-bedrock/deployments/artifact.json \ --outfile.l2 genesis.json \ --outfile.rollup rollup.json \ --l1-rpc $L1_RPC_URL \ --l2-allocs ../packages/contracts-bedrock/deploy-config/statedump.json

    You’ll find the newly created genesis.json and rollup.json in the op-node package.

  3. Add the following at the end of rollup.json:

"alt_da": { "da_challenge_contract_address": "0x0000000000000000000000000000000000000000", "da_commitment_type": "GenericCommitment", "da_challenge_window": 160, "da_resolve_window": 160 }
  1. Generate a jwt.txt file, which is crucial for the secure interaction between nodes:

    openssl rand -hex 32 > jwt.txt
  2. To get op-geth ready, move the genesis.json and jwt.txt files into its directory:

    cp genesis.json ~/op-geth cp jwt.txt ~/op-geth

These steps ensure the L2 layer is correctly configured and ready for integration with the L1 components, paving the way for a fully functional EVM Rollup on the Avail-OP Stack.

Initialize and Configure Geth

Prepare op-geth for running the chain:

  1. Navigate to op-geth:

    cd ~/op-geth
  2. Create a data directory:

    mkdir datadir
  3. Initialize with the genesis file:

    build/bin/geth init --datadir=datadir genesis.json

Running op-geth

To initiate op-geth, navigate to its directory and execute the following commands:

cd ~/op-geth ./build/bin/geth \ --datadir ./datadir \ --http \ --http.corsdomain="*" \ --http.vhosts="*" \ --http.addr=0.0.0.0 \ --http.port=9545 \ --http.api=web3,debug,eth,txpool,net,engine \ --ws \ --ws.addr=0.0.0.0 \ --ws.port=9546 \ --ws.origins="*" \ --ws.api=debug,eth,txpool,net,engine \ --syncmode=full \ --nodiscover \ --maxpeers=0 \ --networkid=42069 \ --authrpc.vhosts="*" \ --authrpc.addr=0.0.0.0 \ --authrpc.port=9551 \ --authrpc.jwtsecret=./jwt.txt \ --rollup.disabletxpoolgossip=true \ --state.scheme=hash

op-geth is now active, but block creation will begin once op-node is operational.

Why Archive Mode?

Archive mode, requiring more disk space than full mode, is essential for:

  1. op-proposer to access the full state history.
  2. The explorer’s functionality.

Reinitializing op-geth

In cases of database corruption indicated by op-node errors or failure to find L2 heads, follow these steps:

  1. Stop op-geth.
  2. Remove the existing data:
    cd ~/op-geth rm -rf datadir/geth
  3. Reinitialize:
    build/bin/geth init --datadir=datadir genesis.json
  4. Restart op-geth and then op-node.

Running op-node

To launch op-node, which acts as a consensus client, run:

cd ~/optimism/op-node ./bin/op-node \ --l2=http://localhost:9551 \ --l2.jwt-secret=./jwt.txt \ --sequencer.enabled \ --sequencer.l1-confs=5 \ --verifier.l1-confs=4 \ --rollup.config=./rollup.json \ --rpc.addr=0.0.0.0 \ --rpc.port=8547 \ --p2p.disable \ --rpc.enable-admin \ --p2p.sequencer.key=$GS_SEQUENCER_PRIVATE_KEY \ --l1=$L1_RPC_URL \ --l1.rpckind=$L1_RPC_KIND \ --altda.enabled=true \ --altda.da-server=<DA_SERVER_HTTP_URL> \ --altda.da-service=true \ --l1.beacon.ignore=true

Block creation will commence once op-node starts processing L1 information and interfaces with op-geth.

P2P Synchronization

To optimize synchronization and avoid network resource waste:

  • Disable p2p sync (--p2p.disable) by default.
  • Use specific command line parameters for synchronization among multiple nodes.

Running op-batcher

op-batcher is crucial in publishing transactions from the Sequencer to L1. Ensure it has at least 1 Sepolia ETH for operational continuity.

cd ~/optimism/op-batcher ./bin/op-batcher \ --l2-eth-rpc=http://localhost:9545 \ --rollup-rpc=http://localhost:8547 \ --poll-interval=1s \ --sub-safety-margin=6 \ --num-confirmations=1 \ --safe-abort-nonce-too-low-count=3 \ --resubmission-timeout=30s \ --rpc.addr=0.0.0.0 \ --rpc.port=8548 \ --rpc.enable-admin \ --max-channel-duration=1 \ --l1-eth-rpc=$L1_RPC_URL \ --private-key=$GS_BATCHER_PRIVATE_KEY \ --altda.enabled=true \ --altda.da-service=true \ --altda.da-server=<DA_SERVER_HTTP_URL>

Controlling Batcher Costs

Adjust the --max-channel-duration=n setting to balance transaction frequency on L1 and the operational costs of the batcher. Recommended is a minumum of 2 since avail block time is 20s and ethereum’s 12sec.

Running op-proposer

Finally, start op-proposer to propose new state roots:

cd ~/optimism/op-proposer ./bin/op-proposer \ --poll-interval=12s \ --rpc.port=9560 \ --rollup-rpc=http://localhost:8547 \ --l2oo-address=$L2OO_ADDR \ --private-key=$PROPOSER_KEY \ --l1-eth-rpc=$L1_RPC

Acquire Sepolia ETH for Layer 2

To obtain ETH on your Rollup:

  1. Go to contracts-bedrock:

    cd ~/optimism/packages/contracts-bedrock
  2. Find the L1 standard bridge contract address:

    cat deployments/avail-optimism/L1StandardBridgeProxy.json | jq -r .address
  3. Send Sepolia ETH to the bridge contract address.

Conduct Test Transactions

You now have a fully operational Avail-Powered Optimism-based EVM Rollup. Experiment with it as you would with any other test blockchain.

Congratulations on setting up your chain!

Last updated on