Skip to main content

Customize genesis state

Arbitrum chain operators are increasingly seeking to deploy chains with pre-existing state by loading an initial state in a file such as genesis.json. Specifically, chain operators want to predeploy smart contracts (like Gnosis Safe) to an Arbitrum chain so they exist from genesis, before any user interaction or post-launch governance.

Initializing from a genesis state would be helpful in the following scenarios:

  1. Redeploying a new testnet with the pre-existing state if the current testnet is broken.
  2. Deploying additional sibling chains with pre-existing contracts.
  3. Simplifying self-serve backends for RaaSes, such that hundreds of testnets can be deployed with similar contracts.
  4. Reducing lift on third-party infrastructure teams to redeploy contracts for new chains.

Why should I use a custom genesis state?

Using a custom genesis allows you to initialize a new blockchain with a customized genesis state and network configuration through the following options:

  • Predeployed contracts: standard chains start without any smart contracts. This feature allows you to preload contract bytecode in the very first block, so infrastructure is available at launch.
  • Initial account state (allocations): you can pre-configure the ledger—including account balances and contract storage—before the network opens for transactions.
  • Enable advanced features: chain operators can use this feature to launch a chain with advanced customizations, such as minting/burning gas tokens via third-party bridges and compliance-focused transaction filtering.

How to configure

Prerequisites
  • Nitro contracts >= v3.2

    • first version to include full support for custom initialization in genesis.json
  • Nitro node >= v3.9.9 is needed for using custom-genesis.

  • Chain SDK >= xx.xx or

    • Chain SDK only supports the standard genesis.json format, which includes the predeployed contracts.
  • genesis-file-generator tool

    • If you want to customize the genesis.json file or pass accounts/custom chain config, you should use the genesis-file-generator.

    Note: The chain configuration must be exactly the same at the string level, including the order of fields, potential whitespace, or special characters for the serializedChainConfig string

Use the Chain SDK

The script completes the following automated steps:

  • Generates a standard genesis.json file with the pre-deployed contracts.
  • Calculates the blockhash and sendRoot hash and returns them for your use.
  • An option to deploy the rollup. You can either deploy the chain using the genesis.json above or use the output from the previous step to set up the chain separately.

Core configuration ref

The following is required to generate the genesis.json file:

VariableDescription
CHAIN_IDThe unique numeric identifier for your chain.
IS_ANYTRUSTWhether the chain is an AnyTrust (true) or rollup (false).
ARBOS_VERSIONThe version of ArbOS to use for the genesis block.
CHAIN_OWNERThe address that will have admin ownership of the deployed chain.
L1_BASE_FEEThe initial L1 gas price (in wei) used to calibrate the chain initiation.
NITRO_NODE_IMAGEThe Nitro node Docker image used for hashing and node operations.
ENABLE_NATIVE_TOKEN_SUPPLYFlag to launch your chain with native interop tokens as minting/burning gas tokens via third-party bridges via third-party protocols.
ENABLE_TRANSACTION_FILTERINGFlag to launch your chain with protocol-level transaction filtering for regulatory or compliance purposes.
Note: This feature requires ArbOS60 and Nitro node v3.10.0.

Deployment configuration (optional)

This step is only required if you choose to deploy the rollup to the parent chain (Step 3 below).

VariableDescription
DEPLOYER_PRIVATE_KEYPrivate key of the account responsible for the rollup deployment.
BATCH_POSTER_PRIVATE_KEYPrivate key for the sequencer's batch-posting address.
VALIDATOR_PRIVATE_KEYPrivate key for the validator/bonder address
PARENT_CHAIN_RPCRPC endpoint for the parent chain (e.g., Arbitrum Sepolia or Ethereum)

Execution steps

  1. Prepare the environment

    • From the repository root, install dependencies and navigate to the generator directory.
    yarn install && yarn build

    cd examples/generate-genesis-file && cp .env.example .env
  2. Generate gensis

    • Ensure your .env is configured and run the dev script.

      Configuration

      Double-check that your .env values match your intended chain specs before running the script.

  3. Create rollup (optional)

    • After generating the genesis.json file, the Chain SDK provides an option to deploy your rollup. Follow the prompts to continue or exit the process and deploy the rollup later.
  4. Configure and launch your node:

    • Set up your node as usual (directions here), but include the following properties to point to your custom state:
      • --init.genesis-json-file=/path/to/genesis.json: the path to your custom genesis.json file
      • --init.empty=false: (Required) Forces the node to load the provided genesis file instead of initializing a blank state.
  5. Start your chain, with the correct preloaded state.

Use the genesis-file-generator tool

Environment variables reference (.env)

These parameters define the identify of your chain

VariableDescriptionDefault
CHAIN_IDThe unique numeric identifier for your new chain.31337
IS_ANYTRUSTWhether the chain is an AnyTrust (true) or a rollup (false).false
ARBOS_VERSIONThe version of ArbOS to use for the genesis block.51
CHAIN_OWNERThe address that will have admin ownership of the deployed chain.--
L1_BASE_FEEThe initial L1 gas price (in wei) used to calibrate the chain creation.1000000000 (1 gwei)
NITRO_NODE_IMAGEThe Nitro node Docker image used for hashing and node operations.--
CUSTOM_ALLOC_ACCOUNT_FILE(optional) Path to a JSON file containing your own account balances, contract bytecode, and storage slots. The file should be in the the standard Geth alloc format." " (empty)
ENABLE_NATIVE_TOKEN_SUPPLY(optional) Set to true if you want to launch your chain with native interop tokens as minting/burning gas tokens via third-party bridges via third-party protocols.false
LOAD_DEFAULT_PREDEPLOYS(optional) Set to false if you don't want the default predeploys.true
ENABLE_TRANSACTION_FILTERING(optional) Set to true if you want to launch your chain with protocol-level transaction filtering for regulatory or compliance purposes.
Note: This feature requires ArbOS60 and Nitro node v3.10.0.
false

Execution process

  1. Prepare the genesis state

    • Set up the .env file with the required parameters.
    • Run the genesis-file-generator Docker image to generate a genesis.json file with the required pre-deployed contracts and additional configurations.
    mkdir -p genesis

    docker run --rm \
    --env-file .env \
    -v "$(pwd)/genesis":/app/genesis \
    offchainlabs/genesis-file-generator:v0.0.2-4c37f62
  2. Generate the required hashes:

    • After the genesis.json file is created, run the Nitro container to compute the genesis blockhash with the genesis-generator endpoint:
    source .env

    docker run --rm \
    -v "$(pwd)/genesis":/data/genesisDir \
    --entrypoint genesis-generator \
    "$NITRO_NODE_IMAGE" \
    --genesis-json-file /data/genesisDir/genesis.json \
    • This bind-mounts the current directory into the container so it can read the genesis.json file generated in the previous step, and outputs the genesis blockhash and sendRoot hash. The blockhash and sendRoot hash will be logged as:
    genesis-hash-calculator | BlockHash: 0xd636d2cae7a75bf41f471639f1cbf98fe2a24216147792510e664a65496f27ed, SendRoot: 0x0000000000000000000000000000000000000000000000000000000000000000, Batch: 1, PosInBatch: 0
  3. Deploy the rollup:

    • Use the blockhash, sendRoot, Batch, and PosInBatch in the Chain SDK. The SDK will use these to generate the assertion_hash needed to register your rollup's core smart contracts on the parent chain.
    const genesisAssertionState = {
    globalState: {
    bytes32Vals: [genesisBlockHash as `0x${string}`, sendRootHash as `0x${string}`] as [
    `0x${string}`,
    `0x${string}`,
    ],
    // Set inbox position to 1
    u64Vals: [1n, 0n] as [bigint, bigint],
    },
    machineStatus: 1, // FINISHED
    endHistoryRoot: toHex(0, { size: 32 }),
    };
  4. Configure and launch your node:

    • Set up your node as usual (directions here), but include the following properties to point to your custom state:
      • --init.genesis-json-file=/path/to/genesis.json: the path to your custom genesis.json file
      • --init.empty=false: (Required) Forces the node to load the provided genesis file instead of initializing a blank state.
  5. Start your chain, with the correct preloaded state.

Pre-deployed contracts registry

The following contracts are included by default in the standard genesis.json file:

CategoryContract NameAddressNote
FactoriesSafe Singleton Factory v1.0.430x914d7Fec6aaC8cd542e72Bca78B30650d45643d7Deterministic Proxy (Safe Key)
Create2Deployer0x13b0D85CcB8bf860b6b79AF3029fCA081AE9beF2CREATE (Deployer: 0x5542..., Nonce 0)
CreateX v1.0.00xba5Ed099633D3B313e4D5F7bdc1305d3c28ba5EdPre-signed Transaction
Arachnid Proxy0x4e59b44847b379578588920cA78FbF26c0B4956CDeterministic Proxy (Arachnid)
Safe v1.3.0GnosisSafe (Canonical)0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552Via Arachnid CREATE2 Proxy
GnosisSafe (EIP-155)0x69f4D1788e39c87893C980c06EdF4b7f686e2938Via Safe Singleton Factory
GnosisSafeL2 (Canonical)0x3e5c63644e683549055b9be8653de26e0b4cd36eVia Arachnid CREATE2 Proxy
GnosisSafeL2 (EIP-155)0xfb1bffC9d739B8D520DaF37dF666da4C687191EAVia Safe Singleton Factory
SafeProxyFactory (Canonical)0xa6B71E26C5e0845f74c812102Ca7114b6a896AB2Via Arachnid CREATE2 Proxy
SafeProxyFactory (EIP-155)0xC22834581EbC8527d974F8a1c97E1bEA4EF910BCVia Safe Singleton Factory
MultiSend v1.3.00x998739BFdAAdde7C933B942a68053933098f9EDaVia Safe Singleton Factory
MultiSendCallOnly v1.3.00xA1dabEF33b3B82c7814B6D82A79e50F4AC44102BVia Safe Singleton Factory
Safe v1.4.1Safe0x41675C099F32341bf84BFc5382aF534df5C7461aVia Safe Singleton Factory
SafeL20x29fcB43b46531BcA003ddC8FCB67FFE91900C762Via Safe Singleton Factory
SafeProxyFactory0x4e1DCf7AD4e460CfD30791CCC4F9c8a4f820ec67Via Safe Singleton Factory
MultiSend v1.4.10x38869bf66a61cF6bDB996A6aE40D5853Fd43B526Via Safe Singleton Factory
MultiSendCallOnly v1.4.10x9641d764fc13c8B624c04430C7356C1C7C8102e2Via Safe Singleton Factory
ERC-4337 CoreEntryPoint v0.6.00x5FF137D4b0FDCD49DcA30c7CF57E578a026d2789Standard v0.6
SenderCreator v0.6.00x7fc98430eAEdbb6070B35B39D798725049088348Created during EP v0.6.0 deploy
EntryPoint v0.7.00x0000000071727De22E5E9d8BAf0edAc6f37da032Standard v0.7
SenderCreator v0.7.00xEFC2c1444eBCC4Db75e7613d20C6a62fF67A167CCreated during EP v0.7.0 deploy
EntryPoint v0.8.00x4337084d9e255ff0702461cf8895ce9e3b5ff108Standard v0.8
SenderCreator v0.8.00x449ED7C3e6Fee6a97311d4b55475DF59C44AdD33Created during EP v0.8.0 deploy
Account ModulesSafe Module Setup v0.3.00x2dd68b007B46fBe91B9A7c3EDa5A7a1063cB5b47ERC-4337 Initializer
Safe 4337 Module v0.3.00x75cf11467937ce3F2f357CE24ffc3DBF8fD5c226Associated with Entrypoint v0.7.0
Kernel v3.30xd6CEDDe84be40893d153Be9d467CD6aD37875b28Associated with Entrypoint v0.7.0
KernelFactory v3.30x2577507b78c2008Ff367261CB6285d44ba5eF2E9Associated with Entrypoint v0.7.0
MetaFactory v3.00xd703aaE79538628d27099B8c4f621bE4CCd142d5ZeroDev FactoryStaker
ECDSAValidator v3.10x845ADb2C711129d4f3966735eD98a9F09fC4cE57Compiled from commit 8f7fd99
InfrastructureMulticall30xcA11bde05977b3631167028862bE2a173976CA11Pre-signed Transaction
Permit20x000000000022D473030F116dDEE9F6B43aC78BA3Uniswap Permit2
EAS v1.4.00xF4C9CCaf46A866e2c12C5Bd95A39694718044444Ethereum Attestation Service
EAS SchemaRegistry0x822B0B93BE3f3B8Da35a2E90e877C01215be8506EAS Registry