ethereum-optimism / ethereum-optimism/optimism
Shared interop contracts depend on a single chain's SystemConfig
- Dominant language
- Go
- Stars
- 6.5k
- Forks
- 4k
- Avg merge
- 2d 15h
- Merged PRs (30d)
- 145
Description
**Claude:**
## Problem
`OPCM.migrate` produces four shared contracts for an interop set: a freshly deployed `ETHLockbox`, `DisputeGameFactory` and `AnchorStateRegistry`, plus chain 0's existing `DelayedWETH` (`OPContractsManagerMigrator.sol:154-191`). Three of the four store a pointer to **chain 0's `SystemConfig`** — a per-chain contract.
Full dependency list:
| Shared contract | Field | Call | Used for |
|---|---|---|---|
| `ETHLockbox` | `systemConfig` | `paused()` | gates `unlockETH()` — every chain's withdrawal payouts |
| | | `superchainConfig()` | `_authorizePortal` equality check |
| `AnchorStateRegistry` | `systemConfig` | `paused()` | `isGameProper` — game validity across the whole set |
| | | `guardian()` | `setRespectedGameType`, `updateRetirementTimestamp`, `blacklistDisputeGame` |
| | | `superchainConfig()` | external view only, no internal callers |
| `DelayedWETH` | `systemConfig` | `paused()` | gates `withdraw()` — bond payouts |
| | | `superchainConfig()` via `config()` | external view only, no internal callers |
`DisputeGameFactory` holds no `SystemConfig` reference. Dispute games hold none directly — they pick it up transitively through `anchorStateRegistry().paused()`.
## Why it matters
1. **Chain 0 becomes the governance root of the set.** Pause state and guardian for all shared contracts resolve through one member's `SystemConfig`. Migrate validates ProxyAdmin owner and SuperchainConfig equality once (`OPContractsManagerMigrator.sol:359-388`); nothing keeps chain 0 aligned afterwards.
2. **`SystemConfig.paused()` is not a pure passthrough.** It derives the pause identifier from `optimismPortal().ethLockbox()` and the `ETH_LOCKBOX` feature bit (`SystemConfig.sol:604-612`), so the shared contracts' pause state is routed through chain 0's portal and feature bitmap.
3. **It makes per-chain upgrades non-idempotent.** The validator asserts `_asr.systemConfig() == _sysCfg`, `_weth.systemConfig() == _sysCfg` and `_lockbox.systemConfig() == _sysCfg` (`StandardValidatorUtils.sol:393`, `:358`, `OPContractsManagerStandardValidator.sol:447`) — a predicate that can only hold for one member at a time. `OPContractsManagerV2._upgradeChain` re-initialises all three shared contracts with `_cts.systemConfig` (`:887-890`, `:939-943`, `:947-954`), so upgrading chain N silently repoints the set's governance reference to chain N. This is a direct obstacle to the "all chains always upgrade the shared components" resolution in ethereum-optimism/optimism#21731, which relies on those re-initialisations being idempotent.
## Proposed fix
Point each shared contract at something whose scope matches its own. `ETHLockbox` already *is* the pause identity of a shared set:
- `ETHLockbox` holds the `SuperchainConfig` directly, `paused()` keys on `address(this)`, and it gains a `guardian()` passthrough.
- `AnchorStateRegistry` and `DelayedWETH` hold a minimal `paused()` / `guardian()` / `superchainConfig()` interface, satisfied by `ETHLockbox` (shared scope) and by today's `SystemConfig` (per-chain scope, for chains with no lockbox).
The field is a plain 20-byte address slot in all three contracts (`snapshots/storageLayout/`), so the change is storage-layout-neutral. It also collapses the current 4-hop `paused()` cycle (lockbox → systemConfig → portal → its own address → superchainConfig) down to one call on the `unlockETH` path.
Once every chain has an `ETHLockbox`, the polymorphism can be dropped, `SystemConfig.paused()` collapses to `ethLockbox.paused()`, and the identifier branch plus `setFeature`'s pause-identity special case (`SystemConfig.sol:566-589`) can be deleted.
## Out of scope
The shared proxies are also administered by chain 0's `ProxyAdmin`, and `DisputeGameFactory.owner` is snapshotted from `chain0.proxyAdmin.owner()`. Tracked in ethereum-optimism/optimism#21731.
Contributor guide
Assessment
This issue has not been assessed yet.