Docs
Avail-powered Orbit chains

Deploy Arbitrum Orbit with Avail DA

This guide follows the deployment of an Arbitrum Orbit chain (L3) with Arbitrum Sepolia (L2) as the base chain. You can follow the same steps with any other supported chains with the relevant contract addresses.

Prerequisites

Docker

Avail

Arbitrum Sepolia

Download avail-nitro-node docker image

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

docker pull availj/avail-nitro-node:v2.1.0-upstream-v3.1.1

Deploy Rollup Contracts

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

git clone https://github.com/availproject/nitro-contracts.git
cd nitro-contracts
git checkout v2.1.0-upstream-v2.1.0
yarn install
yarn build

Step-2: Create .env file

Create a copy of .env.sample as .env file and edit the following:

  • Set Rollup Creator Address at ROLLUP_CREATOR_ADDRESS
//for Arbitrum Sepolia
ROLLUP_CREATOR_ADDRESS="0xE917553b67f630C3982236B6A1d7844B1021B909"

For the ROLLUP_CREATOR_ADDRESS on any other supported chain, please fimd it here.

  • Add the private key of a well funded ArbSepolia account in DEVNET_PRIVKEY
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.

config = {
  rollupConfig: {
    confirmPeriodBlocks: ethers.BigNumber.from('150'),
    extraChallengeTimeBlocks: ethers.BigNumber.from('0'),
    stakeToken: ethers.constants.AddressZero,
    baseStake: ethers.utils.parseEther('0.0001'),
    wasmModuleRoot:
      '0x3f3b4da7b5c231e6faf91ff723d235728b05c9074f2ae3cc4b3e54dd5139d34f',
    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 (the config provided above).

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 build:forge:yul
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: Create 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 blocks 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

"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>"
  },

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

After you've filled the relevant params under chain. You'll need to also need to add your Avail relevant details.

      "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>"
    }

Step-3: Create orbitSetupScriptConfig.json in ./config

In orbitSetupScriptConfig.json you need to fill your chain's info as described below:

{
"networkFeeReceiver": "0xd41996ED89bb5BF7dBfB181D8D93E8067446200B",
"infrastructureFeeCollector": "0xd41996ED89bb5BF7dBfB181D8D93E8067446200B",
"staker": "0xDF819f9Fc3c28FEDFb73374C7B60A4f9BCdE6710",
"batchPoster": "0xB0Ad5AE0a78025613F17B7e4644CE5752487B9d6",
"chainOwner": "0xd41996ED89bb5BF7dBfB181D8D93E8067446200B",
"chainId": 99584959107,
"chainName": "My Arbitrum L3 Chain",
"minL2BaseFee": 100000000,
"parentChainId": 421614,
"parent-chain-node-url": "https://sepolia-rollup.arbitrum.io/rpc",
"utils": "0xB11EB62DD2B352886A4530A9106fE427844D515f",
"rollup": "0xd30eCcf27A6f351EfA4fc9D17e7ec20354309aE3",
"inbox": "0x4512e40a1ec8555f9e93E3B6a06af60F13538087",
"nativeToken": "0x0000000000000000000000000000000000000000",
"outbox": "0x2209755fA3470ED1AFFB4407d1e3B1f7dFC13ce9",
"rollupEventInbox": "0x1e58240B2D769de25B4811354819C901317D0894",
"challengeManager": "0xfC5BbC40d24EcD6FcC247EfFDc87E7D074E9B67D",
"adminProxy": "0xf488b25e6736Ed74E8d37EA434892129E4d62E3B",
"sequencerInbox": "0xD15347309854F1290c9a382ea2719AB5462c7719",
"bridge": "0xC83ee8e28B7b258f41aF8ef4279c02f901288029",
"upgradeExecutor": "0x805bB07B88dDA56030eC48644E0C276e2e5E3949",
"validatorUtils": "0xB11EB62DD2B352886A4530A9106fE427844D515f",
"validatorWalletCreator": "0xEb9885B6c0e117D339F47585cC06a2765AaE2E0b",
"deployedAtBlockNumber": 11274529
}
 

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

...
nitro:
  image: availj/avail-nitro-node:v2.1.0-upstream-v3.1.1
  ports:
...

Step-5: Run your chain

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

This will launch the Nitro node with a public RPC reachable at http://localhost:8449/ (opens in a new tab) and a corresponding BlockScout explorer instance, viewable at http://localhost/ (opens in a new tab) - 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.

Appendix A: Logging

Run this command in the root directory of your orbit setup script repo to view your chain's logs:

docker-compose logs -f nitro

Appendix B: Depositing ETH/native token

If you need to deposit more ETH (or native tokens) into your Orbit chain account, run this command on the base directory of the setup script, replacing 0xYourPrivateKey with the private key of the originating account, and <AMOUNT> with the amount to send:

Using Arbitrum Sepolia:

PRIVATE_KEY="0xYourPrivateKey" L2_RPC_URL="https://sepolia-rollup.arbitrum.io/rpc" L3_RPC_URL="http://localhost:8449"
AMOUNT="<AMOUNT>" yarn run deposit

Appendix C: Refunding (For testing environments)

Once you're done with your local Orbit chain and want to refund any remaining balance from the batch poster and validator wallets, you can use the refund script by running:

PRIVATE_KEY="0xYourPrivateKey" L2_RPC_URL="<https://sepolia-rollup.arbitrum.io/rpc>" TARGET_ADDRESS="0xYourTargetAddress" yarn run refund

Make sure to replace "0xYourPrivateKey" with the private key of the wallet you used to deploy the rollup contracts, and "0xYourTargetAddress" with the address where you want to receive the refunded funds.

This will transfer any remaining balance from the batch poster and validator wallets to the specified target address.

Appendix D: Troubleshooting

You may see error getting latest batch count in your node's output logs (from Appendix A). This is usually safe to ignore. It's usually displayed when your Orbit chain's base contract deployment isn't yet finalized on the L1 chain. This finalization can take 15-20 minutes, but don't worry - the deployment doesn't need to be L1-finalized in order for your chain to function properly.

Learn more about customizing and using your Orbit chain from the Arbitrum Orbit Docs (opens in a new tab).

Reference

Currently chains supporting Arbitrum orbit chain deployment with AvailDA:-

Soon will add more chains

Smart contract addresses

The following information may be useful to those building on Arbitrum. We list the addresses of the smart contracts related to the protocol

Arbitrum Sepolia (opens in a new tab)Base Sepolia (opens in a new tab)
RollupCreator0xE917553b67f630C3982236B6A1d7844B1021B9090x66667c90de1E169e705F248614c72076aA1a2240
Bridge0x4A9722A440506469CcA933969f790923Ac59A0A50x6a7a97E34E6D75724BB58C0d8EFF8cEB27b23A56
AvailDABridge0x5EE5FAd194260bF039b32DEe0bC3D809989A3d000x36cE36dc5BE3E89F6B25315d8346503B307546A6
SequencerInbox0xA04d516D245D1E11Eb7cF8D38Ec1540A25c2DCB50x7C44660caB5b6d330cd38a9468F3F84F2f175E9C
Inbox0x790d2BCD12Fa25db147fc033515CBCEc89d89E200x48dCee9af45842A905FDE5ff5a502EFd06862E49
RollupEventInbox0x62F82278559e8aBdCe222D1A4c2D45dFD6D8C26E0x1cd6c66A1C6b260147909bbd3211Fb9f4424A480
Outbox0xdd414356a4D573865D78D0C5E05d62686c14E3760xdB991f2943CD1A3c17FDb5b78434F4b7331bFb37
ERC20Bridge0x6582b333408D8eF71a951a77E61a263857cd570C0x3d238cf78f740E94753254f9B6339ACaa66c1574
ERC20SequencerInbox0xA878d9432DaCCb14A94EAcB8f6158954e538874a0xE6Cb93cA92f1C65D5709059456ad232721A87c02
ERC20Inbox0x7484e03fF084Fd9C1Bc30de40D7A2ed4acb22AFC0xa5E5c409f39e929087DFbb182C29FE8350Ad1bC8
ERC20RollupEventInbox0xE26d16aAb33950C7bEEcf0F46C161bAc0495dB000x09Cb2789481759613886b5747c5fE49FAb7c4650
ERC20Outbox0xC313E4F98C525b555A972a564A01bdB76D69BA100xa183436DAb3ea069010912e0beBB4c734A4aD90c
BridgeCreator0xe188683D96b82a3A1314424E5e9c438461667EdE0xE6DeCD823d1480069348931833F97C3810ea7Ea5
OneStepProver00x6404d3539B6d37ebc9AC50d7f528Ee8168ece5cC0x6032313a93F78b9Db91885E6d83e40626f371052
OneStepProverMemory0x71FF43aeb6E788B855410447Bbc1F71916Bb98Ec0x5AFee8C856386Ac18E56CdA14470637e13C1D47b
OneStepProverMath0xcCe345C15E7a9AA7784601e28811671cf41bF7110x91EF8ffce4AbB1b256662A6a6C4C7051534aD575
OneStepProverHostlo0x65DCCc4bA7836B743D2370A5fbea8Ef3263789d90x49Fb114B5c708eF2a5aa6Ba413da55E5F07389C4
OneStepProofEntry0x7452e148a7faffac053f442080DE8f305d0C86420xd0A9C68313233C568AD19B55FECac9148245Fb76
ChallengeManager0x1c8285a7BFc8E5F4960aB105ca0E595Ce80858b20x71BF09F4787187b3c62dA0a89c893Ca5687ffef0
RollupAdminLogic0x0922ce6b911B420EBC5851943Adfba40587B68520x488088F12D354b2bEe8c5d5C27Dd266f0b70c5eb
RollupUserLogic0x256E8dD36893f00E6C0c1B1099561b8322692B910x3A12b3eB213CAb423324400D49Ec7d61c903ac20
UpgradeExecutor0x0c78cDc973de62ae83D99cEe87D8bD45d5Cd20840x2F6DdA8EA7b41186c1C00980fF1b96df23E4D442
ValidatorUtils0x0911837C1cdC5b5C6ACDBc887Be223A05c3c6FDD0xCa56EB65F0C84e2BeCCd6A42Ff2ADAC5e362705e
ValidatorWalletCreator0x367Ad15A9aDFF8C2D1D51892F2d717bF2B86a3aD0xD3E785B544bf85f124fa0f3aC557127882Ed2f09
DeployHelper0xD58aa678074840c5A74c29d85A493723c4f48e8c0xaD98D017aA12d0a7A265d4BFAfd289CE9968943f
VectorX0xA712dfec48AF3a78419A8FF90fE8f97Ae74680F00x13cBE46E168460a101c07efb6Ab7B9ec637F02aA
Avail Bridge0x420953898afC97147675F793a90d3793b974698b0xBC3071f9dE256B3b9C6304731F28C98f102425De
Avail Bridge Proxy0xa3e9e20875b7A7461C4829663497F7c2baB9E13b0x9378F9E35ff46a131406FEb7a226F7da4395DB48

Previous Releases

v2.1.0-upstream-v3.1.0

v2.0.0-upstream-v2.3.1

v1.0.0

⚠️

The previous release of v1 is not recommended for install any more, but we will continue supporting it until a migration path from v1 to current release is provided.