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:
| Software | Version |
|---|---|
| Git | OS default |
| Go | 1.21 |
| Node | ^20 |
| Pnpm | 8.5.6 |
| Make | OS default |
| jq | OS default |
| direnv | Latest |
| 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 direnvUse 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 ).
- Navigate to
git clone https://github.com/availproject/avail-alt-da-server.git
cd avail-alt-da-server
-
Build Avail DA Server:
make da-server -
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.exampleto.env. Fill the values inside. -
Run the following commands:
docker-compose build docker-compose up
Build the Adapter Source
-
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 -
Install modules:
pnpm install -
Compile the necessary packages:
make op-node op-batcher op-proposer pnpm build
Build the Optimism Geth Source
-
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 -
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:
-
In the Optimism repo, navigate to the contracts-bedrock package:
cd ~/optimism/packages/contracts-bedrock -
Generate accounts:
echo "Admin:" cast wallet new echo "Proposer:" cast wallet new echo "Batcher:" cast wallet new echo "Sequencer:" cast wallet newYou 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: 0xd98b49e11e4e0be9931017831395e6644a50c36285d08e14d1a479af5ee08675Record and securely store these key details. You’ll need to fund
Admin,Proposer, andBatcherwith Sepolia ETH (0.5 ETH forAdmin, 0.2 ETH forProposer, 0.1 ETH forBatcher).
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.
-
Ensure you are in the
contracts-bedrocksub-directory:cd ~/optimism/packages/contracts-bedrock -
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:
- Update
/optimism/packages/contracts-bedrock/deploy-configand update filegetting_started.json.
cd packages/contracts-bedrock
./scripts/getting-started/config.sh- Add the following at the bottom of the config generated:
"useAltDA": true,
"daCommitmentType": "GenericCommitment",
"daChallengeWindow": 160,
"daResolveWindow": 160,
"daBondSize": 1000000,
"daResolverRefundPercentage": 0Example 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
}
- Navigate to
/optimism/packages/contracts-bedrock/deployments, and createavail-optimismdirectory:
cd ~/optimism/packages/contracts-bedrock/deployments
mkdir avail-optimism- 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 - 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_SALTby runningdirenv reloadanywhere 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.jsonfor the genesis blockrollup.jsonfor rollup configurationsjwt.txtfor secure communication betweenop-nodeandop-geth
-
Navigate to the
op-nodedirectory:cd ~/optimism/op-node -
Run the following command, ensuring you replace
<RPC>with your specific L1 RPC URL. This generates thegenesis.jsonandrollup.jsonfiles: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.jsonYou’ll find the newly created
genesis.jsonandrollup.jsonin theop-nodepackage. -
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
}-
Generate a
jwt.txtfile, which is crucial for the secure interaction between nodes:openssl rand -hex 32 > jwt.txt -
To get
op-gethready, move thegenesis.jsonandjwt.txtfiles 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:
-
Navigate to
op-geth:cd ~/op-geth -
Create a data directory:
mkdir datadir -
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=hashop-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:
op-proposerto access the full state history.- 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:
- Stop
op-geth. - Remove the existing data:
cd ~/op-geth rm -rf datadir/geth - Reinitialize:
build/bin/geth init --datadir=datadir genesis.json - Restart
op-gethand thenop-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=trueBlock 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_RPCAcquire Sepolia ETH for Layer 2
To obtain ETH on your Rollup:
-
Go to
contracts-bedrock:cd ~/optimism/packages/contracts-bedrock -
Find the L1 standard bridge contract address:
cat deployments/avail-optimism/L1StandardBridgeProxy.json | jq -r .address -
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!