Running a Scroll L2geth Node

This guide will walk you through setting up your own Scroll node using Docker with snapshot.

Key Differences from Scroll Sepolia

  • Required binary version: scroll-v5.8.38 or higher.
  • Use --scroll instead of --scroll-sepolia.
  • Mainnet requires a fully synced Ethereum Mainnet RPC for the --l1.endpoint flag.
  • Bootnode setup differs (5 default + 2 optional dedicated ones).

Prerequisites

Staying Up-to-Date

Keep an eye on https://github.com/scroll-tech/go-ethereum/releases for new node releases.

We recommend using the latest release at https://github.com/scroll-tech/go-ethereum/releases.

Naming Conventions

The preferred network name is Scroll or scroll. If you operate a user-facing service (e.g. public RPC endpoint), please consider using this name.

Hardware Requirements

Recommended

  • Machine comparable to AWS t3.2xlarge instance.
  • 4TB gp3 SSD storage.

Docker

This section assumes you are familiar with Docker and have Docker and Docker Compose installed and running.

L1 RPC Node

You will need access to a fully-synced Ethereum Mainnet RPC endpoint before running l2geth. You can maintain your own node or choose to use a 3rd-party provider that supports the standard Ethereum RPC APIs. The remainder of the article assumes that you have access to an L1 node’s HTTP RPC API at L2GETH_L1_ENDPOINT. Example: L2GETH_L1_ENDPOINT="https://my-node.com:8545"


Build and Run Using Docker with Snapshot

Download L2geth

Download the latest l2geth :

docker pull scrolltech/l2geth:latest

Download the Snapshot

SNAPSHOT_URL = https://scroll-geth-snapshot.s3.us-west-2.amazonaws.com/mpt/latest.tar

  1. Create a new folder for the snapshot
mkdir l2geth
  1. Go to the created folder
push l2geth
  1. Download the snapshot
wget $SNAPSHOT_URL
  1. unarchive the snapshot
tar -xf latest.tar

Run L2geth

  1. Go to the snapshot folder
cd l2geth
  1. In the l2geth folder, setup the docker-compose.yaml config Insert your config in the yaml file and save it, recommended config would be :
services:
l2geth:
image: scrolltech/l2geth:latest
container_name: l2geth-docker
stop_signal: SIGINT
stop_grace_period: 60s
restart: "unless-stopped"
environment:
- CHAIN_ID=534352
- RUST_LOG="info"
volumes:
- 'l2geth/data:/volume/l2geth/data'
ports:
- 8545:8545
- 8546:8546
- 6060:6060
- 30303:30303
- 30303:30303/udp
command:
--scroll
--scroll-mpt
--snapshot=false
--metrics
--pprof.addr 0.0.0.0
--pprof.port 6060
--datadir /volume/l2geth/data
--gcmode archive
--http
--http.addr 0.0.0.0
--http.port 8545
--http.api eth,net,web3,debug,scroll
--cache.noprefetch
--l1.endpoint "${Your l1 endpoint}"
--da.blob.blobscan "${Your blobscan endpoint}"
--da.blob.beaconnode "${Your beaconnode endpoint}"
--cache.snapshot=0
logging:
driver: "json-file"
options:
max-size: "100m"
max-file: "1"
  1. Run the docker
docker compose up -d
  1. In a separate shell, you can now attach to l2geth.
$ docker exec -it l2geth-docker geth attach "/volume/l2geth-datadir/geth.ipc"
> admin.peers.length
5
> eth.blockNumber
10000

Interacting with the L2geth Container

  • Check logs: docker logs --tail 10 -f l2geth-docker
  • Stop the container: docker stop l2geth-docker
  • Fetch metrics: curl http://localhost:6060/debug/metrics/prometheus

Configuration Reference

  • SCROLL_L2_CHAIN_ID_L2= 534352
  • SCROLL_L2_NETWORK_ID_L2= 534352
  • SCROLL_L2_GENESIS_HASH= 0xbbc05efd412b7cd47a2ed0e5ddfcf87af251e414ea4c801d78b6784513180a80

Bootnode list:

enode://c6ac91f43df3d63916ac1ae411cdd5ba249d55d48a7bec7f8cd5bb351a31aba437e5a69e8a1de74d73fdfeba8af1cfe9caf9846ecd3abf60d1ffdf4925b55b23@54.186.123.248:30303
enode://fdcc807b5d1353f3a1e98b90208ce6ef1b7d446136e51eaa8ad657b55518a2f8b37655e42375d61622e6ea18f3faf9d070c9bbdf012cf5484bcbad33b7a15fb1@44.227.91.206:30303
enode://6beb5a3efbb39be73d17630b6da48e94c0ce7ec665172111463cb470197b20c12faa1fa6f835b81c28571277d1017e65c4e426cc92a46141cf69118ecf28ac03@44.237.194.52:30303
enode://7cf893d444eb8e129dca0f6485b3df579911606e7c728be4fa55fcc5f155a37c3ce07d217ccec5447798bde465ac2bdba2cb8763d107e9f3257e787579e9f27e@52.35.203.107:30303
enode://c7b2d94e95da343db6e667a01cef90376a592f2d277fbcbf6e9c9186734ed8003d01389571bd10cdbab7a6e5adfa6f0c7b55644d0db24e0b9deb4ec80f842075@54.70.236.187:30303
enode://a28f9c5a8f6ed2a5063210a1253ddba9b8b48434e4700198ec8c6e687753dc0eba6dcef4fbbe8a6aeef2079884c2d85ca0bffcab8ec826111576a2cffe7a3266@44.230.97.163:30303
enode://0bb5919853cb7cfc302d3c7ac266890cc8f3c67cce7e8fa8d45c3714237fbed395a7b964de131617cf10903774a8ef59d89c002136c2dedad9ef8bd8eddc3ef7@52.36.234.198:30303

Genesis json file can be found here

Troubleshooting

  • The node (APIs, geth console, etc) will not be responsive until all the L1 messages have been synced.
  • However, the derivation pipeline is already started during the initial sync phase, which can be seen through L1 sync progress [...] logs.
  • For Scroll Sepolia it might take a little longer (10-20mins) for the first L1 sync progress [...] logs to appear as the L1 blocks are more sparse at the beginning.

You should see something like this shortly after starting:

INFO [09-18|13:41:34.039] Starting L1 message sync service latestProcessedBlock=20,633,529
WARN [09-18|13:41:34.551] Running initial sync of L1 messages before starting l2geth, this might take a while...
INFO [09-18|13:41:45.249] Syncing L1 messages processed=20,634,929 confirmed=20,777,179 collected=71 progress(%)=99.315
INFO [09-18|13:41:55.300] Syncing L1 messages processed=20,637,029 confirmed=20,777,179 collected=145 progress(%)=99.325
INFO [09-18|13:42:05.400] Syncing L1 messages processed=20,638,329 confirmed=20,777,179 collected=220 progress(%)=99.332
INFO [09-18|13:42:15.610] Syncing L1 messages processed=20,640,129 confirmed=20,777,179 collected=303 progress(%)=99.340
INFO [09-18|13:42:24.324] L1 sync progress "blockchain height"=1000 "block hash"=a28c48..769cee root=174edb..9d9fbd
INFO [09-18|13:42:25.555] Syncing L1 messages processed=20,641,529 confirmed=20,777,179 collected=402 progress(%)=99.347

Common Errors

If you run l2geth in Docker and get this error on MacOS, you need to add the /volume directory to the list of shared paths in Docker Desktop settings.

  1. Click the Docker icon in the macOS menu bar, then click Settings.
  2. Go to the Resources tab.
  3. Click on File Sharing.
  4. Click the ”+” (plus) button to add a new shared folder.
  5. Navigate to the root directory, select the volume folder, and click Open.
  6. Click Apply & Restart for the changes to take effect.

The genesis config format changed starting at version scroll-v3.1.3. You can fix this error in two ways:

  • Run l2geth with the --scroll flag. This will automatically import the up-to-date genesis config.
  • Alternatively, you can download the latest genesis.json , and run l2geth --datadir "./l2geth-datadir" init "./genesis.json" before running the node. This command will import the updated genesis config. Note: Your local database will remain intact.

If DockerHub does not have the container version required by your system, you can pass --platform linux/amd64 to each Docker command. For better performance, we recommend that you build the image for your platform or Build and Run From Source .

Please make sure your l1 endpoint is working as expected

Please add working —da.blob.blobscan and —da.blob.beaconnode endpoints

The issue could be caused by :

  1. Disk issue (busy or out of space) Please increase disk space or check why it is busy
  2. You recently shut down or restart your machine, mpt-trie has a graceful shutdown issue Add flag --cache.snapshot=0 and --snapshot=false to disable snapshot

What's Next

Stay up-to-date on the latest Scroll Developer news
Roadmap updates, virtual and live events, ecosystem opportunities and more
Thank you for subscribing!

Resources

Follow Us