All phases of Avail's unification drop have now ended, šŸ‘‰šŸ‘‰ check out this page šŸ‘ˆšŸ‘ˆ for more information.

Docs
Avail-powered Orbit chains

Deploy Arbitrum Orbit with Avail DA

Prerequisites

  1. You need to have docker (opens in a new tab) and docker-compose (opens in a new tab) installed on your machine.
  2. An Avail account with some AVAIL tokens in it. You can refer to our docs here to get started.
  3. At least 1 ETH over Arbsepolia Testnet. You can follow Step 1 (opens in a new tab) on Arbitrum Orbit Doc for acquiring testnet $ETH
  4. This guide will use Arbitrum's ArbSepolia (opens in a new tab) and Avail's Turing testnets.

Download avail nitro node docker image

Step-1: Download the avail-nitro-node (opens in a new tab) image from docker hub

docker pull availrishabh/avail-nitro-node-dev:v2.3.1

Deploy Rollup Contracts

Step-1: Download the nitro-contract (opens in a new tab) with Avail DA

git clone https://github.com/availproject/nitro-contracts.git
cd nitro-contracts
git checkout avail-develop-v2.3.1
yarn install
yarn build

Step-2: Create .env file

Create a copy of .env.sample as .env file and Set Rollup Creator Address at ROLLUP_CREATOR_ADDRESS and Private key of well funded ArbSepolia accout in DEVNET_PRIVKEY

ROLLUP_CREATOR_ADDRESS="0xADCBE5c221566FA6e6Ebf5BA08759c83177DfCDA"
DEVNET_PRIVKEY="<--Private-key-->"

Step-3: Create .script/config.ts file

Create a copy of scripts/config.ts.example as scripts/config.ts and set this config file with required configurations where wasmModuleRoot must be this based on your cpu arch

// for amd64
wasmModuleRoot:'0xba5ff5ddc46b5c63fa02168819b8e236fa18b4b551f20eba378e3543477298bf'
// for arm64
wasmModuleRoot:'0x1cc4dd8f036f93e37b6c9fa4edfbefaf19cf893558e9358ad41ccb3804684092'
config = {
  rollupConfig: {
  confirmPeriodBlocks: ethers.BigNumber.from('45818'),
  extraChallengeTimeBlocks: ethers.BigNumber.from('200'),
  stakeToken: ethers.constants.AddressZero,
  baseStake: ethers.utils.parseEther('0.0001'),
  wasmModuleRoot:
    '0x1cc4dd8f036f93e37b6c9fa4edfbefaf19cf893558e9358ad41ccb3804684092',
  owner: '0x1234123412341234123412341234123412341234',
  loserStakeEscrow: ethers.constants.AddressZero,
  chainId: ethers.BigNumber.from('20121999'),
  chainConfig:
    '{"chainId":20121999,"homesteadBlock":0,"daoForkBlock":null,"daoForkSupport":true,"eip150Block":0,"eip150Hash":"0x0000000000000000000000000000000000000000000000000000000000000000","eip155Block":0,"eip158Block":0,"byzantiumBlock":0,"constantinopleBlock":0,"petersburgBlock":0,"istanbulBlock":0,"muirGlacierBlock":0,"berlinBlock":0,"londonBlock":0,"clique":{"period":0,"epoch":0},"arbitrum":{"EnableArbOS":true,"AllowDebugPrecompiles":false,"DataAvailabilityCommittee":false,"InitialArbOSVersion":10,"InitialChainOwner":"0xd41996ED89bb5BF7dBfB181D8D93E8067446200B","GenesisBlockNum":0}}',
  genesisBlockNum: ethers.BigNumber.from('0'),
  sequencerInboxMaxTimeVariation: {
    delayBlocks: ethers.BigNumber.from('5760'),
    futureBlocks: ethers.BigNumber.from('12'),
    delaySeconds: ethers.BigNumber.from('86400'),
    futureSeconds: ethers.BigNumber.from('3600'),
  },
},
},
validators: [
  '0x1234123412341234123412341234123412341234',
],
batchPosters: ['0x1234123412341234123412341234123412341234',],
batchPosterManager: '0x1234123412341234123412341234123412341234'
 

The below table provides a brief description of each of these configuration parameters. We recommend sticking to the defaults; to learn more about customizing your Orbit chain's deployment configuration, visitĀ How (and when) to customize your Orbit chain's deployment config (opens in a new tab):

ParameterDescription
Chain ID(chainID)A unique integer identifier that represents your chain's network. YourĀ Chain IDĀ can be submitted to chain indexes likeĀ http://chainlist.org/ (opens in a new tab). For devnets, this is randomly generated for each deployment - don't worry about it for now.
Challenge period (confirmPeriodBlocks)The amount of time that your Orbit chain's nodes have to dispute the current state of the chain before it's confirmed (and ultimately finalized) on the underlying L2 chain (e.g. Arbitrum Sepolia). Note that this refers to the number of blocks on the underlying L1 chain (e.g. Ethereum's Sepolia chain).
Stake token(stakeToken)The token that your chain's validators must stake in order to participate in your chain. This is hardcoded to $ETH for now, but future versions of Orbit chains will let you specify an arbitrary ERC-20 token contract here.
Base stake(baseStacke)The amount of your configuredĀ Stake tokenĀ that your chain's validators must stake in order to participate in your chain. Should be greater than 0.
Owner(owner)The administrative Ethereum address that will deploy, own, and update your chain's base contracts. This will default to your connected wallet's address. This needs to be a standard Ethereum wallet account - an EOA, not a contract address. Note that you'll have to specify this wallet's private key within a local JSON file later.
Gas tokenThe address of the ERC-20 token on the parent chain that is intended to be used as the native gas token on the Orbit chain. This token must already be deployed natively on the parent chain and is bridged to the Orbit chain during chain deployment. This feature is only supported on AnyTrust chains currently, and more information around token restrictions can be foundĀ https://docs.arbitrum.io/launch-orbit-chain/how-tos/customize-deployment-configuration (opens in a new tab).
ValidatorsYour chain's validators are responsible for validating the integrity of transactions and posting assertions of the current state of your Orbit chain to its base chain. Add the address in the list which you want to be added to an allow-list in your chainā€™s base contract
Batch PosterYour batch poster address is responsible for posting batches of transactions from your Orbit chain to its base contracts on its base chain. Added the address which you want to act as batch-poster for your orbit chain

When we say "base contracts" and "base chain", we're referring to your Orbit chain's L2 contracts and the L2 chain that they're deployed to, respectively. We'll use these terms throughout the rest of this guide.

Step-4: Deploy your chain's base contracts to Arbitrum Sepolia!

yarn run deploy-eth-rollup --network arbSepolia

You will get to see your chainā€™s base contracts addresses, which will be need in next step to fill in nodeConfig.json


nitro-stack

Before proceeding, let's briefly review what just happened:

  • You submitted a deployment transaction to an Orbit "factory" smart contract on the Arbitrum testnet, the public L2 chain that your local Orbit chain will settle transactions to.
  • This Orbit smart contract then initialized your Orbit chain's base contracts with the values that you specified in the previous step, and deployed these base contracts to the Arbitrum testnet.

Your Orbit chain's base contracts are responsible for facilitating the exchange of information between your chain's node(s) and its base chain's nodes. This includes the batch posting of transactions from your Orbit chain to its base chain, the staking of tokens by your Orbit chain's validators the challenge mechanism, bridging mechanisms, and more.

Spin up the chain using orbit-setup-script

Step-1: Download orbit-setup-script (opens in a new tab)

git clone https://github.com/OffchainLabs/orbit-setup-script.git
cd orbit-setup-script

Step-2: Add the nodeConfig.json in ./config

This is theĀ nodeConfig.jsonĀ file, encapsulating your chain's node configuration. It is crucial as it contains the private keys for your validator and batch poster, essential for signing transactions for RBlocks and batch postings to your chain's base contracts on the L2 chain.

{
  "chain": {
    "info-json": "[{\"chain-id\":<Insert your chain-id>,\"parent-chain-id\":421614,\"parent-chain-is-arbitrum\":true,\"chain-name\":\"<Insert chain name>\",\"chain-config\":{\"homesteadBlock\":0,\"daoForkBlock\":null,\"daoForkSupport\":true,\"eip150Block\":0,\"eip150Hash\":\"0x0000000000000000000000000000000000000000000000000000000000000000\",\"eip155Block\":0,\"eip158Block\":0,\"byzantiumBlock\":0,\"constantinopleBlock\":0,\"petersburgBlock\":0,\"istanbulBlock\":0,\"muirGlacierBlock\":0,\"berlinBlock\":0,\"londonBlock\":0,\"clique\":{\"period\":0,\"epoch\":0},\"arbitrum\":{\"EnableArbOS\":true,\"AllowDebugPrecompiles\":false,\"DataAvailabilityCommittee\":false,\"InitialArbOSVersion\":11,\"GenesisBlockNum\":0,\"MaxCodeSize\":24576,\"MaxInitCodeSize\":49152,\"InitialChainOwner\":\"<Insert chain owner address>\"},\"chainId\":<Insert chain id>},\"rollup\":{\"bridge\":\"<Bridge proxy address>\",\"inbox\":\"<Inbox address>\",\"sequencer-inbox\":\"<Sequencer inbox address>\",\"rollup\":\"<Rollup proxy address>\",\"validator-utils\":\"<Validator until address>\",\"validator-wallet-creator\":\"<Validator wallet creator address>\",\"deployed-at\":<Insert deployed-at block number>}}]",
    "name": "<Insert chain name>"
  },
  "parent-chain": {
    "connection": {
      "url": "https://sepolia-rollup.arbitrum.io/rpc"
    }
  },
  "http": {
    "addr": "0.0.0.0",
    "port": 8449,
    "vhosts": [
      "*"
    ],
    "corsdomain": [
      "*"
    ],
    "api": [
      "eth",
      "net",
      "web3",
      "arb",
      "debug"
    ]
  },
  "node": {
    "sequencer": true,
    "delayed-sequencer": {
      "enable": true,
      "use-merge-finality": false,
      "finalize-distance": 1
    },
    "batch-poster": {
      "max-size": 90000,
      "enable": true,
      "parent-chain-wallet": {
        "private-key": "<Insert your private key here>"
      }
    },
    "staker": {
      "enable": true,
      "strategy": "MakeNodes",
      "parent-chain-wallet": {
        "private-key": "<Insert your private key here>"
      }
    },
    "dangerous": {
      "no-sequencer-coordinator": true
    },
    "avail": {
      "enable": true,
      "seed": "<Enter your seed phrase here>",
      "avail-api-url": "wss://turing-rpc.avail.so/ws",
      "app-id": "<Enter your avail app id>",
      "timeout":"100s",
      "vectorx": "0xA712dfec48AF3a78419A8FF90fE8f97Ae74680F0",
      "arbSepolia-rpc": "<Enter an arbSepolia wss url here>"
    }
  },
  "execution": {
    "forwarding-target": "",
    "sequencer": {
      "enable": true,
      "max-tx-data-size": 85000,
      "max-block-speed": "250ms"
    },
    "caching": {
      "archive": true
    }
  }
}
 

Make sure to update these params based on your chain's configuration and base contract addresses

List of params to be configured

  • chain.chain-id
  • chain.chain-name
  • chain.InitialChainOwner
  • chain.chainId
  • chain.rollup
  • chain.name
  • node.batch-poster.parent-chain-wallet.private-key
  • node.staker.parent-chain-wallet.private-key
  • node.avail.seed
  • node.avail.app-id
  • node.avail.arbSepolia-rpc

Step-3: Update docker-compose file of orbit-setup-script

...
nitro:
  image: avail-nitro-node-dev:v2.3.1
  ports:
...

Step-4: Run your chain

cd orbit-setup-script
docker-compose up -d

A Nitro node and BlockScout explorer instance will be started. Visit http://localhost:4000/ (opens in a new tab) to access your BlockScout explorer instance - this will allow you to view your chain's transactions and blocks, which can be useful for debugging.

Hurray!

Congratulations, Your local Orbit chain with Avail DA is now running.