How to run a local dev node
A local Arbitrum Nitro dev node can help you deploy and test smart contracts in a fully controlled environment. This how-to walks you through the process of deploying and running a full development environment on your local machine that includes a Nitro dev node, a dev-mode geth L1, and multiple instances with different roles.
If you want your local development environment to support Stylus, check out this guide.
Step 1. Install prerequisites
You'll need docker and docker compose to run your node. Follow the instructions in their site to install them.
Step 2. Clone the nitro-testnode repo
You'll need the release branch.
git clone -b release --recurse-submodules https://github.com/OffchainLabs/nitro-testnode.git && cd nitro-testnode
Step 3. Run your node
./test-node.bash --init
Step 4. Successive runs
To relaunch the node after the first installation, run the following command.
./test-node.bash
Note that running with the --init flag will clear all chain data and redeploy!
Token bridge
An L1-L2 token bridge can be deployed by using the parameter --tokenbridge. The list of contracts can be found by running docker compose run --entrypoint sh tokenbridge -c "cat network.json".
Running an L3 chain
An L3 chain can be deployed on top of the L2 chain, by using the parameter --l3node. Its deployment configuration can be found by running docker exec nitro-testnode-sequencer-1 cat /config/l3deployment.json.
When deploying an L3 chain, the following parameters are also available:
--l3-fee-token: Uses a custom gas token for the L3 (symbol $APP), deployed on L2 at address0x9b7c0fcc305ca36412f87fd6bd08c194909a7d4e--l3-token-bridge: Deploys an L2-L3 token bridge
Additional arguments
You can find a list of additional arguments to use with test-node.bash by using --help.
./test-node.bash --help
Helper scripts
The repository includes a set of helper scripts for basic actions like funding accounts or bridging funds. You can see a list of the available scripts by running:
./test-node.bash script --help
If you want to see information of a particular script, you can add the name of the script to the help command.
./test-node.bash script send-l1 --help
Here's an example of how to run the script that funds an address on L2. Replace 0x11223344556677889900 with the address you want to fund.
./test-node.bash script send-l2 --to address_0x11223344556677889900 --ethamount 5
Blockscout
Nitro comes with a local Blockscout block explorer. To access it, add the param --blockscout when running your node.
./test-node.bash --blockscout
The block explorer will be available at http://localhost:4000
Default endpoints and addresses
Node RPC endpoints are available at:
| Node | Chain id | RPC endpoint |
|---|---|---|
| L1 geth devnet | 1337 | http://localhost:8545 |
| L2 nitro devnet | 412346 | http://localhost:8547 and ws://localhost:8548 |
| L3 nitro (if enabled) | 333333 | http://localhost:3347 |
The following accounts will be prefunded with Ether:
L2 Nitro devnet:
0x683642c22feDE752415D4793832Ab75EFdF6223cwith private key0xe887f7d17d07cc7b8004053fb8826f6657084e88904bb61590e498ca04704cf2Both networks (L1 and L2):
0x3f1Eae7D46d88F08fc2F8ed27FCb2AB183EB2d0Ewith private key0xb6b15c8cb491557369f3c7d2c287b053eb229daa9c22138887752191c9520659
You can fund other addresses by using the scripts send-l1 and send-l2 as explained here.
How to get the core contracts
For addresses of the deployed core protocol contracts, run
docker exec nitro-testnode-sequencer-1 cat /config/deployment.json
For the outbox address, run (replace "PUT_THE_ROLLUP_ADDRESS_HERE" with rollup address):
curl 'http://localhost:8545/' -H 'Content-Type: application/json' -d '{"jsonrpc":"2.0","id":0,"method":"eth_call","params":[{"to":"PUT_THE_ROLLUP_ADDRESS_HERE","data":"0xce11e6ab"},"latest"]}'
Some default addresses can be found here:
"l2Network": {
"chainID": 412346,
"confirmPeriodBlocks": 20,
"ethBridge": {
"bridge": "0x2b360a9881f21c3d7aa0ea6ca0de2a3341d4ef3c",
"inbox": "0xff4a24b22f94979e9ba5f3eb35838aa814bad6f1",
"outbox": "0x49940929c7cA9b50Ff57a01d3a92817A414E6B9B",
"rollup": "0x65a59d67da8e710ef9a01eca37f83f84aedec416",
"sequencerInbox": "0xe7362d0787b51d8c72d504803e5b1d6dcda89540"
},
"explorerUrl": "",
"isArbitrum": true,
"isCustom": true,
"name": "ArbLocal",
"partnerChainID": 1337,
"retryableLifetimeSeconds": 604800,
"nitroGenesisBlock": 0,
"depositTimeout": 900000,
"tokenBridge": {
"l1CustomGateway": "0x3DF948c956e14175f43670407d5796b95Bb219D8",
"l1ERC20Gateway": "0x4A2bA922052bA54e29c5417bC979Daaf7D5Fe4f4",
"l1GatewayRouter": "0x525c2aBA45F66987217323E8a05EA400C65D06DC",
"l1MultiCall": "0xDB2D15a3EB70C347E0D2C2c7861cAFb946baAb48",
"l1ProxyAdmin": "0xe1080224B632A93951A7CFA33EeEa9Fd81558b5e",
"l1Weth": "0x408Da76E87511429485C32E4Ad647DD14823Fdc4",
"l1WethGateway": "0xF5FfD11A55AFD39377411Ab9856474D2a7Cb697e",
"l2CustomGateway": "0x525c2aBA45F66987217323E8a05EA400C65D06DC",
"l2ERC20Gateway": "0xe1080224B632A93951A7CFA33EeEa9Fd81558b5e",
"l2GatewayRouter": "0x1294b86822ff4976BfE136cB06CF43eC7FCF2574",
"l2Multicall": "0xDB2D15a3EB70C347E0D2C2c7861cAFb946baAb48",
"l2ProxyAdmin": "0xda52b25ddB0e3B9CC393b0690Ac62245Ac772527",
"l2Weth": "0x408Da76E87511429485C32E4Ad647DD14823Fdc4",
"l2WethGateway": "0x4A2bA922052bA54e29c5417bC979Daaf7D5Fe4f4"
}
}