Skip to main content

How to run a local dev node with Stylus support

ALPHA RELEASE, PUBLIC PREVIEW DOCS

Stylus is currently tagged as an alpha release. The code has not been audited, and should not be used in production scenarios. This documentation is currently in public preview.

To provide feedback, click the Request an update button at the top of this document, join the Arbitrum Discord, or reach out to our team directly by completing this form.

This how-to guides you through the process of setting up a local Arbitrum Nitro dev node, with Stylus support, to help you deploy and test smart contracts written in Solidity or any of the languages supported by Stylus in a fully controlled environment. By following these steps, you'll deploy and run a full development environment on your local machine that includes a Nitro dev node (L2), a dev-mode geth parent chain (L1), and multiple instances with different roles.

1. Install prerequisites

You'll need docker and docker compose to run your node. Follow the instructions in their site to install them.

2. Clone the nitro-testnode repo

You'll need the stylus branch.

git clone -b stylus --recurse-submodules https://github.com/OffchainLabs/nitro-testnode.git && cd nitro-testnode

3. Run your node

./test-node.bash --init

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!

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

The L1 Geth devnet will be running at http://localhost:8545 and the L2 Nitro devnet at http://localhost:8547 and ws://localhost:8548.

The following accounts will be prefunded with Ether:

  • L2 Nitro devnet: 0x683642c22feDE752415D4793832Ab75EFdF6223c with private key 0xe887f7d17d07cc7b8004053fb8826f6657084e88904bb61590e498ca04704cf2

  • Both networks (L1 and L2): 0x3f1Eae7D46d88F08fc2F8ed27FCb2AB183EB2d0E with private key 0xb6b15c8cb491557369f3c7d2c287b053eb229daa9c22138887752191c9520659

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