Upgrading a Chain From Output Roots to Super Roots
This runbook walks you through upgrading a single OP Stack chain from output-root dispute games (PERMISSIONED_CANNON, CANNON or CANNON_KONA) to super-root dispute games (SUPER_PERMISSIONED or SUPER_CANNON_KONA). It runs as a single opcm.upgrade call against the chain’s existing per-chain AnchorStateRegistry and DisputeGameFactory. The chain’s permission model is preserved: a permissioned chain stays permissioned with SUPER_PERMISSIONED only; a permissionless chain runs both super game types with SUPER_CANNON_KONA as the respected one. Differences between the two are called out inline.
By the end you will have a chain proposing super-root claims via op-proposer using a single-chain super-root RPC endpoint and monitoring them with op-dispute-mon. On permissionless chains, op-challenger defends SUPER_CANNON_KONA claims. On permissioned chains, op-dispute-mon detects invalid SUPER_PERMISSIONED claims, op-challenger updates the AnchorStateRegistry as games finalize. Every pre-migration dispute game already in flight continues to resolve, and proven withdrawals are not invalidated.
This is
opcm.upgrade, not opcm.migrate — the chain keeps its own per-chain AnchorStateRegistry and DisputeGameFactory.Before You Begin
You should be familiar with runningsuperchain-ops upgrade tasks, signing through the standard signing workflow, and operating op-proposer, op-challenger, and op-dispute-mon. See Upgrade using superchain-ops for the signing workflow.
Required tooling
The versions below are the ones the optimism repo’smise.toml pins; older versions of cast in particular may not parse the function-selector syntax used in this runbook.
You also need a checkout of the optimism monorepo to run
op-fetcher (used in the next step).
Gather the Required Inputs
Collect everything below before you start. Chain identity. The chain’s per-chain addresses live in thesuperchain-registry repository under superchain/configs/<network>/<chain-name>.toml. Open that file and read chain_id, addresses.SystemConfigProxy, and addresses.L1StandardBridgeProxy.
Chain addresses and roles. Use op-fetcher to derive the rest of the on-chain configuration in a single call. It runs an embedded forge script against $L1_RPC and resolves every per-chain proxy, role, and the current fault-proof status from SystemConfig and L1StandardBridge:
chain.json:
Chain type. The upgrade preserves the chain’s existing permission model.
chain.json reports the current respected game type at .faultProofs.respectedGameType:
1(PERMISSIONED_CANNON) — chain is permissioned. The new respected game type is5(SUPER_PERMISSIONED).0(CANNON) or8(CANNON_KONA) — chain is permissionless. The new respected game type is9(SUPER_CANNON_KONA).
SUPER_PERMISSIONED (game type 5) is bondless and must use an initBond of 0. SUPER_CANNON_KONA (game type 9) uses 0.08 ether (80000000000000000 wei), the standard value used on existing chains.
Release artifacts and infrastructure.
Verify the Preconditions
Before you change any configuration:-
Confirm the template injects
overrides.cfg.startingAnchorRoot. Opensuperchain-ops/src/template/OPCMUpgradeV800.soland check_buildExtraInstructions. As of writing it only injectsoverrides.cfg.startingRespectedGameTypeandPermittedProxyDeployment. Without anoverrides.cfg.startingAnchorRootoverride, OPCM falls back to the existing on-chainstartingAnchorRoot, which on a pre-upgrade chain is an output-root-shaped value with a block-numberl2SequenceNumber— not a valid super-root anchor. The template must be extended to read a starting super-root anchor from TOML and add it as a third extra instruction. Fix the template before continuing. -
Confirm the RPC endpoint returns a single-chain super root. Either the chain’s op-node RPC endpoint or an op-supernode
/<chainID>/endpoint can be used. Do not use a multi-chain op-supernode root endpoint; it computes roots across its full dependency set. -
Verify the single-chain RPC endpoint is healthy. For an op-node or namespaced op-supernode endpoint, confirm it reports a recent finalized L2 head and can produce the corresponding super root:
If an op-node returns a SafeDB error, configure
--safedb.path, let the node populate records through derivation, and retry.optimism_syncStatuscan succeed while SafeDB is disabled, butsuperroot_atTimestampcannot serve a non-genesis timestamp without SafeDB. -
Verify the prestate server serves the new hash.
Stage the Off-Chain Configuration
Apply these changes before you submit the on-chain upgrade. After the changes ship, the components keep operating against existing pre-migration games and pick up super-root games automatically once the upgrade lands.Update op-challenger
Update the runningop-challenger for the chain. Keep --rollup-rpc and the existing --game-types so existing games continue to be defended. Add the super-root trace type only on permissionless chains, where SUPER_CANNON_KONA is enabled.
On a permissionless chain, confirm the startup log lists
super-cannon-kona as registered and shows no connection errors against the single-chain super-root RPC endpoint. On a permissioned chain, confirm the existing trace types remain registered; do not configure a SUPER_PERMISSIONED trace type. op-challenger is still required on permissioned chains to update the AnchorStateRegistry as SUPER_PERMISSIONED games finalize.
Update op-dispute-mon
Update the runningop-dispute-mon for the chain.
Keep
--rollup-rpc. op-dispute-mon discovers games from the existing DisputeGameFactory and does not need a game-type filter change. After the restart, confirm the existing-games metrics keep populating.
Leave op-proposer Unchanged for Now
Skipop-proposer until cutover. Its configuration changes in Switch op-proposer to Super Roots.
Generate the Starting Anchor Super Root
The upgrade must re-initialise<ASR> with a super-root-shaped starting anchor. The existing on-chain startingAnchorRoot is in output-root form (its l2SequenceNumber is an L2 block number), so the template must inject a fresh super-root value via overrides.cfg.startingAnchorRoot in extraInstructions. Confirm in the precondition above that the template has been extended to read this from TOML and pass it through.
Compute the value using superroot_atTimestamp. Pick the current finalized timestamp (or any recent finalized timestamp), then ask the single-chain RPC endpoint for the super root at that timestamp.
super_root(abytes32hash from.data.super_root) — passed asProposal.rootinoverrides.cfg.startingAnchorRoot.timestamp(the uint64 you passed in) — passed asProposal.l2SequenceNumber. This field is the timestamp itself, not a block number or sequence index.
Build the superchain-ops Task
Author a new task directory undersuperchain-ops/src/tasks/<network>/<NNN-name>/ using the OPCMUpgradeV800 template. The schema below assumes the template has been extended (per the precondition above) to also read a starting super-root anchor and inject it as overrides.cfg.startingAnchorRoot.
Configure config.toml
SuperchainConfig, validator, etc.) automatically — no further TOML required.
Capture expectedValidationErrors
Run the task in simulation mode against an L1 fork from inside the task directory:expectedValidationErrors in TOML, the simulation reverts with a message of the form Unexpected errors: <actual>; expected: <expectedValidationErrors>. Read the actual codes from that revert message. The default expectation is no errors — expectedValidationErrors = "" and a clean simulation.
Any non-empty error string must be reviewed code by code, not copy-pasted. For each code:
- Resolve it if it points at a fixable input — a wrong address, a wrong prestate, a template release mismatch, a missing override, or a registry entry that needs updating.
- Add it to
expectedValidationErrorsonly after justifying it with an inline comment in the TOML explaining why it is structurally expected for this chain.
Execute the Upgrade
- Stop
op-proposerfor the chain. Existing games continue to resolve; only new proposals halt. - Leave
op-challengerandop-dispute-monrunning. Both were configured earlier and pick up super-root games automatically. - Sign and broadcast the task using your team’s standard
superchain-opssigning workflow. - Wait for the L1 transaction to confirm.
<ASR>is re-initialised with the supplied anchor and respected game type. The retirement timestamp is not bumped, so existing in-flight games stay valid.- The super dispute game implementation or implementations are installed on
<DGF>. - Implementation pointers for the game types passed with
enabled = falseare cleared, blocking creation of new games of those types.
Verify the Upgrade On-Chain
Run the checks below before you cutop-proposer over.
Common Checks
Permissionless Chain Checks
Permissioned Chain Checks
Switch op-proposer to Super Roots
Startop-proposer with the new configuration.
Other flags such as
--proposal-interval and --poll-interval stay the same.
After start-up, verify:
-
The logs show the proposer polling the configured single-chain super-root RPC endpoint and contain no references to
--rollup-rpc. -
Within one
--proposal-interval, the proposer submits a new game. Inspect it: -
Recompute the super root for the proposed timestamp and confirm it matches the proposal:
This confirms
op-proposeris correctly configured and passing valid super roots.
Verify After the Upgrade
Run these checks once the proposer is stable.-
Pre-migration game still resolves. Pick a still-in-flight pre-migration game (use
op-dispute-mondashboards orgameAtIndexto find one) and watch its status until it resolves: -
op-challengertracesSUPER_CANNON_KONAwhen enabled. On a permissionless chain, verify the startup log listssuper-cannon-konaand ongoing logs contain no scheduler or game-poll errors as type-9 games appear. On a permissioned chain,op-challengercontinues to update theAnchorStateRegistrywhenSUPER_PERMISSIONEDgames finalize but does not need to post claims. -
op-dispute-monreports super-root games. Confirmop_dispute_mon_gamesreports the enabled super game types andop_dispute_mon_failed_gamesremains zero. On a permissioned chain, alert onop_dispute_mon_games_agreement{status="disagree_defender_wins"}andUnexpected game resultlogs forSUPER_PERMISSIONED. -
No new pre-migration games can be created. Optionally call
DisputeGameFactory.createwith one of the disabled game types and confirm it reverts. -
Anchor advances on first super-game finalisation. The first anchor update typically lands ~7 days after the first super-root game is created (game duration plus
DISPUTE_GAME_FINALITY_DELAY_SECONDS). Do not block the rollout on this — schedule a follow-up to re-rungetAnchorRoot()after that window and confirm it returns the new game’s claim instead of the starting root. Track viaop-dispute-monrather than waiting in-line.