How to Setup and Run An Arbitrum Local Nitro Dev Node

To interact with or build applications on any of the Arbitrum chains, you need access to the Arbitrum node. In this tutorial, we will learn how to setup and run the Local Nitro Dev node in a local — dev
mode, verify if the node is running, and chain ownership in — dev
mode. The — dev
mode is ideal for developers who want to quickly test contracts using a single node, as it offers a simpler and faster setup compared to more complex environments.
Note: Need more advanced functionality — such as cross-layer messaging, working with both L1 and L2 chains, or testing interactions between different layers? The nitro-testnode is the preferred option. The testnode setup allows developers to simulate a full L1-L2 environment, which is critical for those scenarios.
Prerequisite:
Docker: Required to run the Nitro dev node in a container.
Install Docker by following the official installation guide for your operating system.
Cast: A command-line tool from Foundry for interacting with Ethereum smart contracts.
You can install it via Foundry by following the installation instructions.
jq: A lightweight JSON parsing tool used to extract contract addresses from the script output.
Install
jq
by following the official installation guide for your operating system.
Getting Started
Step 1: Open the terminal and clone the nitro-devnode repository.
```
git clone https://github.com/OffchainLabs/nitro-devnode.git
cd nitro-devnode
```
Step 2: Run the dev node script
```
./run-dev-node.sh
```
The Nitro dev node script will:
Start the Nitro dev node in the background using Docker.
Deploys the Stylus Cache Manager contract
Registers it as a WASM cache manager using the default development account
You should see the following response in your terminal:
```
Deploying Cache Manager contract…
INFO [01–27|11:05:11.586] Submitted contract creation hash=0xc1131b070db52dfe664e10f3b02261c7476424050dc0095e04f8447ae93c81d6 from=0x3f1Eae7D46d88F08fc2F8ed27FCb2AB183EB2d0E nonce=1 contract=0x11B57FE348584f042E436c6Bf7c3c3deF171de49 value=0
Cache Manager contract deployed at address: 0x11B57FE348584f042E436c6Bf7c3c3deF171de49
Registering Cache Manager contract as a WASM cache manager…
INFO [01–27|11:05:11.812] Submitted transaction hash=0x5084e9fd6fe32ca14b701cab39293be2d9dbd108084cd68390cbc0609e39c089 from=0x3f1Eae7D46d88F08fc2F8ed27FCb2AB183EB2d0E nonce=2 recipient=0x0000000000000000000000000000000000000070 value=0
Cache Manager deployed and registered successfully. Nitro node is running…
```
Troubleshooting:
If you get the error: docker: command not found
:
Ensure that Docker is installed and running. To check that Docker is running, run the following command docker --version
in your terminal:
- You should get the following result:
Docker version 27.5.1, build 9f9e405801
Verify if Nitro Dev Node is running using cURL:
To check if the node is running and everything is working correctly, we will send a cURL request to getBlockNumber
.
```
owanate@Owanates-MacBook-Pro ~ % curl http://localhost:8547/ \
-X POST \
-H "Content-Type: application/json" \
- data '{"method":"eth_getBlockByNumber","params":["latest",false],"id":1,"jsonrpc":"2.0"}'
{"jsonrpc":"2.0","id":1,"result":{"baseFeePerGas":"0x5f5e100","difficulty":"0x1","extraData":"0x0000000000000000000000000000000000000000000000000000000000000000","gasLimit":"0x4000000000000","gasUsed":"0x1283f8","hash":"0x96aeee29e65c4cd10cb70a6a77d124b8f4dc2324db1da0fa27405012381ca72d","l1BlockNumber":"0x0","logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000200000000000000000000000000000000000000040000001000000000000800000000000000000000000000200000000000000000000000000000000000000000000000000000000001000000010000000000000000000000000000000000000000000000100000000000000000100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000400000","miner":"0xa4b000000000000000000073657175656e636572","mixHash":"0x0000000000000000000000000000000000000000000000200000000000000000","nonce":"0x0000000000000001","number":"0x3","parentHash":"0x62e37805104f865ed432cec1b6d24047d68c3a4bf5b9be0e78915d8a5d06c1f6","receiptsRoot":"0x9177110ca2751f280da8937ab6609d98511c3eee87f8a11967aa8249dd40fb27","sendCount":"0x0","sendRoot":"0x0000000000000000000000000000000000000000000000000000000000000000","sha3Uncles":"0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347","size":"0x34c","stateRoot":"0xa24e9238125f9532a7d224bf8a379a2f8874938a20f6b115711791dfa6aaac53","timestamp":"0x67976867","totalDifficulty":"0x4","transactions":["0xd28bba94166f4b3b310e69d408f43b4aeb993413813beea4ec68f953d42483c1","0x5084e9fd6fe32ca14b701cab39293be2d9dbd108084cd68390cbc0609e39c089"],"transactionsRoot":"0x861c123b9fcf2d25ab085349569096a2e6f4b2286c2e032cae5f259af546eb31","uncles":[]}}
```
Key Info
Development account (used by default):
In --dev
mode, the script uses a pre-funded development account by default. This account is pre-funded with ETH in all networks and is used to deploy contracts, interact with the chain, and assume chain ownership.
Address: 0x3f1Eae7D46d88F08fc2F8ed27FCb2AB183EB2d0E
Private key: 0xb6b15c8cb491557369f3c7d2c287b053eb229daa9c22138887752191c9520659
You don’t need to set up a private key manually unless you prefer using your key.
Chain ownership in dev mode:
Chain ownership is important because it allows the owner to perform certain critical functions within the Arbitrum environment, such as:
Adding or removing other chain owners
Setting the L1 and L2 base fees directly
Adjusting the gas pricing inertia and backlog tolerance
Modifying the computational speed limit and transaction gas limits
Managing network and infrastructure fee accounts
In nitro—dev mode, the default chain owner is set to:0x0000000000000000000000000000000000000000
However, you can use the ArbDebug precompile to set the chain owner. This precompile includes the becomeChainOwner()
function, which can be called to assume ownership of the chain.
The script automatically sets the chain owner to the pre-funded dev account before registering the Cache Manager
contract. Here’s how the becomeChainOwner()
the function is called within the script:
```
cast send 0x00000000000000000000000000000000000000FF "becomeChainOwner()" - private-key 0xb6b15c8cb491557369f3c7d2c287b053eb229daa9c22138887752191c9520659 - rpc-url http://127.0.0.1:8547
```
This step ensures that the dev account has ownership of the chain, which is necessary to register the Cache Manager as a WASM cache manager.
Congratulations, We have successfully set up and run the Nitro dev mode, verified that a node is running using cURL, and how to do chain ownership in dev mode. Now your environment is ready for testing and interacting with your contracts.
Subscribe to my newsletter
Read articles from Owanate Amachree directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Owanate Amachree
Owanate Amachree
I’m a lead technical writer with over four years of experience helping global blockchain companies drive product adoption. Through high-quality product documentation, guides, and articles, I have empowered over 7,000 developers, users, and enterprise businesses to engage effectively with blockchain technologies. Currently serving as a Lead Technical Writer at RootstockLabs, I have authored and published over 50 guides and tutorials, significantly improving developer onboarding and user experience.