The following are the steps you need to take to add a chain to the registry:
Important
Ensure your chain is listed at ethereum-lists/chains. This is to ensure your chain has a unique chain ID. Our validation suite will check against this repository. This is a mandatory prerequisite before being added to the registry.
If you are deploying a standard chain, it must be deployed with op-deployer
to be considered standard in the Superchain Registry. Check out
the docs for more information on how to use it.
Tip
We recommend that most chains use op-deployer
. op-deployer
can be configured to support L3s, alt-DA and custom gas token chains.
If you do not use op-deployer
, you will need to manually create your config file.
See Adding a custom chain below for more.
Install the following dependencies:
Dependency | Version | Version Check Command |
---|---|---|
git | ^2 |
git --version |
go | ^1.21 |
go version |
just | ^1.28.0 |
just --version |
You will be raising a Pull Request from your fork to the upstream repo.
We recommend only adding one chain at a time, and starting with a fresh branch of this repo for every chain.
From the root of this directory, run the following:
just create-config <shortname> <path to your state file>
Where shortname
is your chain's name (e.g. op
) and the path to the state file points to the state.json
file generated by op-deployer
.
This will put two files in the .staging
directory - <shortname>.toml
and <shortname>.json.zst
Update <shortname>.toml
with your chain's information. Most of the data is automatically populated from your deployer
state file, however you will need to populate the following yourself:
name
: Human-readable name for your chain.superchain
: Which superchain your chain belongs to. Can besepolia
ormainnet
.public_rpc
: Public RPC endpoint for your chain.sequencer_rpc
: Sequencer RPC endpoint for your chain.explorer
: Block explorer for your chain.deployment_tx_hash
: Transaction hash of the transaction OP Deployer generated to deploy your chain. You'll need to look this up on Etherscan for now. It will be automatically populated in the future.
Don't forget to double-check the config for any inaccuracies.
Commit your changes to your fork, then open a pull request. When opening your PR:
- Open it from a non-protected branch in your fork (e.g. avoid the
main
branch). This allows maintainers to push to your branch if needed, which streamlines the review and merge process. - Open one PR per chain you would like to add. This ensures the merge of one chain is not blocked by unexpected issues.
- Once the PR is opened, please check the box to allow edits from maintainers.
Automated checks will run on your PR to validate your chain. A report will also be generated that describes your chain's level of compliance with the standard blockchain charter.
A member of our team will review your PR. When ready, we will generate code from your PR and push to your fork.
Important
Don't run codegen yourself. This will slow down review.
We strongly recommend that you use op-deployer
to deploy your chain.
op-deployer
can be configured to create L3s, alt-DA and custom gas token chains.
(See the op-deployer
docs for more.)
However, if your chain requires further modifications, you may need to use a custom deployment method and
manually create the files needed to add your chain to the Superchain Registry.
After installing the dependencies and forking this repository, as specified above, you will need to manually generate the config file.
Your config file is a toml file that looks something like this. You can copy this config file and put it in
the .staging
directory in your fork.
You must substitute the values in this file with the correct values for your chain.
name = "testchain"
public_rpc = ""
sequencer_rpc = ""
explorer = ""
superchain_level = 0
governed_by_optimism = false
data_availability_type = "eth-da"
chain_id = 900
batch_inbox_addr = "0x0031e396976D1D09fBa39348dC2Bacc5EebA6be6"
block_time = 2
seq_window_size = 3600
max_sequencer_drift = 600
superchain = "sepolia"
base_fee_vault_recipient = "0x0000000000000000000000000000000000000001"
l1_fee_vault_recipient = "0x0000000000000000000000000000000000000001"
sequencer_fee_vault_recipient = "0x0000000000000000000000000000000000000001"
deployment_tx_hash = "0x51f046f80445052387403e04cb845f864f653fed413893b0d283772823b2176d"
deployment_l1_contracts_version = "tag://op-contracts/v1.8.0-rc.4"
deployment_l2_contracts_version = "tag://op-contracts/v1.7.0-beta.1+l2-contracts"
[hardforks]
canyon_time = 0 # Thu 1 Jan 1970 00:00:00 UTC
delta_time = 0 # Thu 1 Jan 1970 00:00:00 UTC
ecotone_time = 0 # Thu 1 Jan 1970 00:00:00 UTC
fjord_time = 0 # Thu 1 Jan 1970 00:00:00 UTC
granite_time = 0 # Thu 1 Jan 1970 00:00:00 UTC
holocene_time = 0 # Thu 1 Jan 1970 00:00:00 UTC
[optimism]
eip1559_elasticity = 6
eip1559_denominator = 50
eip1559_denominator_canyon = 250
[genesis]
l2_time = 1737654216
[genesis.l1]
hash = "0xdb9ff219fc073a5283a2b5242db147fee30977b1f72d3605cd097cc5b96c2755"
number = 7555499
[genesis.l2]
hash = "0x8946b7495ed37a4982c2e7bcdec217527bb2fe969a8180edc83b7be28186bd78"
number = 0
[genesis.system_config]
batcherAddress = "0x0000000000000000000000000000000000000001"
overhead = "0x0000000000000000000000000000000000000000000000000000000000000000"
scalar = "0x010000000000000000000000000000000000000000000000000c5fc500000558"
gasLimit = 60000000
[roles]
SystemConfigOwner = "0x0000000000000000000000000000000000000001"
ProxyAdminOwner = "0x0000000000000000000000000000000000000001"
Guardian = "0x7a50f00e8D05b95F98fE38d8BeE366a7324dCf7E"
Challenger = "0x0000000000000000000000000000000000000001"
Proposer = "0x0000000000000000000000000000000000000001"
UnsafeBlockSigner = "0x0000000000000000000000000000000000000001"
BatchSubmitter = "0x0000000000000000000000000000000000000001"
[addresses]
AddressManager = "0xdF5C2b0875462CAbF80f1f81d0Cd3A69DaCBC41b"
L1CrossDomainMessengerProxy = "0xB49e92AC4Bbb5F46ad6486eaF61F0aAB9b5b9B20"
L1ERC721BridgeProxy = "0x95B4c742a11A8840c83BdD890185B1dA1fe0bb65"
L1StandardBridgeProxy = "0xf78DA2b5b0F5C47908C9CEa878CdacDBeCDB63a7"
OptimismMintableERC20FactoryProxy = "0xF7b2B8873F00b3204CDD4B308A8849efa721c190"
OptimismPortalProxy = "0xA4E6C3f0414ab1565Fba2F3174db5D3Eb66b129a"
SystemConfigProxy = "0xe8B3d297A94323385467Aec8D2bE1DeAa7b3FFE6"
ProxyAdmin = "0x27aBaEf37258ab121f607C5A4DE51Ea4C24B1967"
SuperchainConfig = "0xC2Be75506d5724086DEB7245bd260Cc9753911Be"
AnchorStateRegistryProxy = "0x810b7bED1bcF03A9f3685dF4D251e5c170eb7141"
DelayedWETHProxy = "0x325cBe3180AE163338Fa967cD142C08Dc419Ab6F"
DisputeGameFactoryProxy = "0x9a888E54A1C4996662a7CC206482bC15448a6B70"
PermissionedDisputeGame = "0x1fA6B096aC9D8C6C8f150cDFaC9BC25b0CAFe00a"
You must ensure that every field in this file has been updated for your chain.
The first part of the config contains important metadata about your chain. These fields include:
name
: Human-readable name for your chain.superchain
: Which superchain your chain belongs to. Can besepolia
ormainnet
.public_rpc
: Public RPC endpoint for your chain.sequencer_rpc
: Sequencer RPC endpoint for your chain.explorer
: Block explorer for your chain.superchain_level
: For custom chains, this must be0
.governed_by_optimism
: For custom chains, this must befalse
.data_availability_type
: Which data availability layer your chain uses. Can beeth-da
oralt-da
.chain_id
: Your chain ID. Must match the ID specified in ethereum-lists/chains.deployment_tx_hash
: Transaction hash of the transaction generated to deploy your chain.deployment_l1_contracts_version
: Must match the OP Contracts version tag that was used to deploy your L1 contracts.deployment_l2_contracts_version
: Must match the OP Contracts version tag that was used to deploy your L2 contracts.
The [hardforks]
section includes overrides for hardfork activation times.
You can leave all these values as 0
if your chain has opted in to Superchain-wide hardforks.
The [genesis]
section contains the hashes for the L1 start block of the rollup and the hash of the genesis of the L2. The L2 genesis hash is generated from its genesis file. Note that this is unrelated to the ZST encoding in step 4.
[roles]
and [addresses]
in the config file must also be manually updated to match the roles and addresses specified when you deployed the chain.
(If you deploy your chain using a custom tool, you will need to specify them at some point.
Keep them handy so you can add your chain to the Superchain Registry!)
The Superchain Registry requires ZST-encoded genesis files.
To ZST-encode your genesis file, run
zstd -D superchain-registry/superchain/extra/dictionary <your-genesis.json>
.
Put the generated file in the .staging
directory alongside the config file.