> ## Documentation Index
> Fetch the complete documentation index at: https://docs.optimism.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Upgrade 20

> Prepare Fault Proof services and contract integrations for the Upgrade 20 move to Super Root Dispute Games.

Upgrade 20 is an L1 smart contract upgrade for OP Stack chains.
It moves Fault Proofs from Output Root Dispute Games to Super Root Dispute Games and includes `SystemConfig` and OP Contracts Manager (OPCM) maintenance changes.

## Why Upgrade 20

Output Root Dispute Games commit to one chain's state at an L2 block number.
Interop requires a dispute game format that can commit to the state of multiple chains at the same timestamp.
Super Root Dispute Games provide that format.

Upgrade 20 moves each chain to Super Root Dispute Games before shared cross-chain dispute infrastructure is enabled.
Each game created after this upgrade still contains one chain's Output Root.
The upgrade does not enable Interop, call `OPCM.migrate()`, or move a chain to a shared Dispute Game setup.

Super Root Dispute Games use a timestamp as the `l2SequenceNumber` and validate an incorrect proposal timestamp through the Fault Proof state transition.
This removes the separate L2 block number challenge used by Output Root Dispute Games.
The `OptimismPortal` continues to support both formats, so games and withdrawal proofs created before the upgrade remain valid.

## What's included

### Super Root Dispute Games

Upgrade 20 adds the following Super Root Dispute Game types:

* `SUPER_PERMISSIONED` (game type `5`) for chains that use permissioned Fault Proofs.
* `SUPER_CANNON_KONA` (game type `9`) for chains that use permissionless Fault Proofs.

A permissioned chain remains permissioned.
A permissionless chain runs both Super Root Dispute Game types and uses `SUPER_CANNON_KONA` as its respected game type.
Existing Dispute Games continue to resolve through their original game types.

The upgrade keeps each chain's existing `AnchorStateRegistry` and `DisputeGameFactory`.
It uses an `OPCM.upgrade()` transaction rather than migrating the chain to a shared Dispute Game setup.

### SystemConfig Interface Cleanup

Upgrade 19 recomputed the onchain `SystemConfig` batch inbox address for chains deployed before OPCM.
The change did not affect derivation because OP Stack clients read the batch inbox address from the chain's rollup configuration, but it left the redundant onchain value out of sync.

Upgrade 20 removes `batchInbox()` and clears its legacy storage slot.
It also removes the deprecated `setGasConfig(uint256,uint256)` function, which could leave `scalar()` out of sync with the fee scalar values that OPCM preserves during an upgrade.
The updated `SystemConfig` has contract version `4.0.0`.

The deprecated `overhead()` getter remains available for compatibility with existing integrations.
Because `setGasConfig(uint256,uint256)` was its only writer, the stored value is no longer writable and does not change during the upgrade.
To preserve the two-word `FEE_SCALARS` event payload without requiring a hardfork, calls to `setGasConfigEcotone(uint32,uint32)` encode zero in the first word instead of the stored `overhead()` value.

## Breaking Changes

### Chain Operators

Chain operators must coordinate the L1 contract cutover with the services that propose, challenge, and monitor Fault Proofs.

* Switch `op-proposer` to the new Super Root RPC and game type at the contract cutover.
* Configure `op-challenger` and `op-dispute-mon` to support Super Root Dispute Games while retaining the configuration needed to finish games already in progress.
* For permissionless Fault Proofs, stage the reviewed `kona-client` Interop variant prestate before the cutover.
* Update operational tooling that calls the removed `SystemConfig` functions.

The [OP Stack component changes](#prepare-op-stack-components), [`SystemConfig` integration changes](#update-systemconfig-integrations), and [prestate workflow](#locate-or-build-the-absolute-prestate) are described below.

### Node Operators

Upgrade 20 has no L2 hardfork, and it does not require an `op-node` or `op-reth` configuration change.
If the node also provides a Super Root RPC to Fault Proof services, keep that endpoint reachable during and after the cutover.

### App Developers and Infrastructure Integrators

Ordinary L2 contracts and transactions are not affected.
Update an integration if it does any of the following:

* Calls `SystemConfig.batchInbox()` or `SystemConfig.setGasConfig(uint256,uint256)`.
* Decodes the first word of a `FEE_SCALARS` `ConfigUpdate` event as the current `overhead()` value.
* Reads Dispute Game root claims directly and assumes the claim is an Output Root.
* Uses an OP Stack SDK to check, prove, or finalize L2-to-L1 withdrawals.

For Super Root Dispute Games, direct Dispute Game integrations must recognize game types `5` and `9` and use `rootClaimByChainId(uint256)` to obtain the chain's Output Root.
The `overhead()` getter remains available for compatibility but is deprecated.
Applications that use `viem/op-stack` for withdrawal proving must upgrade to `viem` `2.51.0` or later and follow the [withdrawal tooling changes](#update-withdrawal-tooling).
Bridge operators and developers of withdrawal tooling that read Dispute Game contracts directly must follow the same guidance.
Tooling that delegates the withdrawal flow to an SDK must use a version that supports Super Root Dispute Games.

### Users

No action is required.
Withdrawal proofs submitted before Upgrade 20 remain valid.
Users do not need to re-prove them.
Existing Output Root Dispute Games continue to resolve, and the `OptimismPortal` supports withdrawal proofs from both Output Root and Super Root Dispute Games.

## Prepare OP Stack components

Use the following configuration changes when staging the Upgrade 20 component releases:

| Component                              | Required change                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `op-challenger`                        | Add `--superroot-rpc` (`OP_CHALLENGER_SUPERROOT_RPC`) and keep the existing game types so the challenger can finish games already in progress. On a permissionless chain, append `super-cannon-kona` to `--game-types` (`OP_CHALLENGER_GAME_TYPES`) and configure the reviewed Kona Interop prestate. On a permissioned chain, do not add `super-permissioned`; the simplified game does not require a trace type, and `op-challenger` handles its lifecycle automatically. |
| `op-dispute-mon`                       | Add `--superroot-rpc` (`OP_DISPUTE_MON_SUPERROOT_RPC`). Keep `--rollup-rpc` while Output Root Dispute Games remain in progress.                                                                                                                                                                                                                                                                                                                                             |
| `op-proposer`                          | Switch at the contract upgrade cutover. Replace `--rollup-rpc` with `--superroot-rpcs` (`OP_PROPOSER_SUPERROOT_RPCS`) and set `OP_PROPOSER_GAME_TYPE=5` for a permissioned chain or `OP_PROPOSER_GAME_TYPE=9` for a permissionless chain.                                                                                                                                                                                                                                   |
| `op-node`, `op-reth`, and `op-batcher` | No configuration change is required. Upgrade 20 has no hardfork activation.                                                                                                                                                                                                                                                                                                                                                                                                 |

The Super Root RPC must return a root for the chain or dependency set that the Dispute Game covers.
For a single-chain upgrade, use the chain's `op-node` RPC endpoint or the chain-specific endpoint exposed by an `op-supernode`.

## Update `SystemConfig` integrations

<Warning>
  Calls to `SystemConfig.batchInbox()` and `SystemConfig.setGasConfig(uint256,uint256)` revert after Upgrade 20.
</Warning>

If your tooling reads or writes `SystemConfig` directly:

* Read the batch inbox address from the chain's rollup configuration or its entry in the [Superchain Registry](https://github.com/ethereum-optimism/superchain-registry).
* Replace `setGasConfig(uint256,uint256)` calls with [`setGasConfigEcotone(uint32,uint32)`](/chain-operators/reference/fee-parameters) for the base fee and blob base fee scalars.
* If you decode `FEE_SCALARS` `ConfigUpdate` events, treat the first word as zero rather than the current value returned by `overhead()`.

## Update withdrawal tooling

Super Root Dispute Games anchor withdrawals by L2 timestamp instead of L2 block number, and their root claim contains a Super Root instead of the chain's Output Root.
Application tooling that discovers a Dispute Game or builds a withdrawal proof must support both changes.

| Tooling                                          | Required change                                                                                                                                                                                                                       |
| ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [`viem/op-stack`](https://viem.sh/op-stack)      | Use `viem` `2.51.0` or later. For prove-readiness calls, pass the initiating withdrawal block timestamp as `l2Timestamp`. Pass the `game` returned by `waitToProve` to `buildProveWithdrawal`; do not pass the legacy `output` value. |
| `ethers`, wagmi, and other general EVM libraries | No library update is required for ordinary contract reads, writes, or L2 transactions. Update only custom withdrawal or Dispute Game code that makes the Output Root assumptions described above.                                     |

After the Upgrade 20 cutover, a `viem` withdrawal prove flow must read the timestamp of the L2 block that contains the initiating transaction:

```js theme={null}
const receipt = await publicClientL2.getTransactionReceipt({
  hash: withdrawalHash
});
const withdrawalBlock = await publicClientL2.getBlock({
  blockNumber: receipt.blockNumber
});

const { game, withdrawal } = await publicClientL1.waitToProve({
  receipt,
  l2Timestamp: withdrawalBlock.timestamp,
  targetChain: publicClientL2.chain
});

const proveArgs = await publicClientL2.buildProveWithdrawal({
  game,
  withdrawal
});
```

Pass the same `l2Timestamp` when calling `getTimeToProve` or `getWithdrawalStatus` for a Super Root withdrawal.
`waitToFinalize` and the finalization transaction do not require the timestamp.
See the [`viem` Super Root withdrawal support release](https://github.com/wevm/viem/releases/tag/viem%402.51.0) for the upstream compatibility change.

## Locate or build the absolute prestate

Permissionless chains need the Upgrade 20 `kona-client` Interop variant absolute prestate for `SUPER_CANNON_KONA`. Use the `kona-client-int` artifact even when Interop is not scheduled for the chain.

<Tabs>
  <Tab title="Standard chain configuration">
    Use the `cannon64-kona-interop` hash published for the Upgrade 20 release in [`standard-prestates.toml`](https://github.com/ethereum-optimism/superchain-registry/blob/main/validation/standard/standard-prestates.toml).

    Check out the Kona release tag associated with the published Upgrade 20 prestate hash, reproduce both Kona prestates, and read the interop hash:

    ```bash theme={null}
    just reproducible-prestate-kona
    jq -r .pre rust/kona/prestate-artifacts-cannon-interop/prestate-proof.json
    ```

    Confirm the output matches the published hash.
    Host the generated hash-named `.bin.gz` file on the prestate server used by `op-challenger`.
  </Tab>

  <Tab title="Custom chain configuration">
    First, stage the chain data described in [Generating a custom kona-client absolute prestate](/chain-operators/tutorials/kona-custom-prestate).
    Check out the Kona release tag associated with the reviewed Upgrade 20 prestate and build the interop variant with the same custom configuration:

    ```bash theme={null}
    cd rust
    KONA_CUSTOM_CONFIGS_DIR=/absolute/path/to/custom-configs \
      just build-kona-reproducible-prestate-variant \
      kona-client-int prestate-artifacts-cannon-interop
    jq -r .pre kona/prestate-artifacts-cannon-interop/prestate-proof.json
    ```

    Rebuild from a clean checkout with the same inputs and confirm the hash is identical.
    Host the generated hash-named `.bin.gz` file at a URL reachable by every challenger that participates on the chain.
    A custom prestate hash is specific to its embedded chain configuration and does not appear in `standard-prestates.toml`.
  </Tab>
</Tabs>

## Upgrade timing

Upgrade 20 is applied as an L1 contract upgrade and has no L2 hardfork activation timestamp.
Pending governance approval, we expect the upgrade to be executed in September.

The [Output Root to Super Root upgrade runbook](/chain-operators/tutorials/upgrade-chain-to-super-roots) describes the onchain upgrade and cutover checks.

## Verify readiness

Before the cutover:

* Confirm `op-proposer`, `op-challenger`, and `op-dispute-mon` start with the staged Super Root configuration and can reach the configured Super Root RPC.
* On a permissionless chain, reproduce the `kona-client` Interop variant prestate and confirm its hash matches the reviewed Upgrade 20 value.
* Run integration tests that cover every direct `SystemConfig` call and every withdrawal or Dispute Game code path listed in this notice.

If you have questions or need support, contact your Optimism point of contact.
