Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update for single step upgrades #486

Merged
merged 3 commits into from
Jan 1, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 68 additions & 44 deletions specs/experimental/op-contracts-manager.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,50 @@ The `deploy` method is used to deploy the full set of L1 contracts required to s
chain that complies with the [standard configuration]. It has the following interface:

```solidity
struct Roles {
address opChainProxyAdminOwner;
address systemConfigOwner;
address batcher;
address unsafeBlockSigner;
address proposer;
address challenger;
}

struct DeployInput {
Roles roles;
uint32 basefeeScalar;
uint32 blobBasefeeScalar;
uint256 l2ChainId;
bytes startingAnchorRoots;
string saltMixer;
uint64 gasLimit;
uint32 disputeGameType;
bytes32 disputeAbsolutePrestate;
uint256 disputeMaxGameDepth;
uint256 disputeSplitDepth;
uint64 disputeClockExtension;
uint64 disputeMaxClockDuration;
}

struct DeployOutput {
IProxyAdmin opChainProxyAdmin;
IAddressManager addressManager;
IL1ERC721Bridge l1ERC721BridgeProxy;
ISystemConfig systemConfigProxy;
IOptimismMintableERC20Factory optimismMintableERC20FactoryProxy;
IL1StandardBridge l1StandardBridgeProxy;
IL1CrossDomainMessenger l1CrossDomainMessengerProxy;
// Fault proof contracts below.
IOptimismPortal2 optimismPortalProxy;
IDisputeGameFactory disputeGameFactoryProxy;
IAnchorStateRegistry anchorStateRegistryProxy;
IAnchorStateRegistry anchorStateRegistryImpl;
IFaultDisputeGame faultDisputeGame;
IPermissionedDisputeGame permissionedDisputeGame;
IDelayedWETH delayedWETHPermissionedGameProxy;
IDelayedWETH delayedWETHPermissionlessGameProxy;
}

/// @notice Deploys a new OP Chain
/// @param _input DeployInput containing chain specific config information.
/// @return DeployOutput containing the new addresses.
Expand Down Expand Up @@ -155,6 +199,9 @@ This provides the following benefits:

## Upgrading

This section is written specifically for the Isthmus upgrade path, which is the first upgrade which will
be performed by the OP Contracts Manager.

### Interface

#### `upgrade`
Expand All @@ -165,38 +212,18 @@ all chains that it controls.
It has the following interface:

```solidity
struct Roles {
address opChainProxyAdminOwner;
address systemConfigOwner;
address batcher;
address unsafeBlockSigner;
address proposer;
address challenger;
}

struct DeployInput {
Roles roles;
uint32 basefeeScalar;
uint32 blobBasefeeScalar;
uint256 l2ChainId;
bytes startingAnchorRoots;
string saltMixer;
uint64 gasLimit;
uint32 disputeGameType;
bytes32 disputeAbsolutePrestate;
uint256 disputeMaxGameDepth;
uint256 disputeSplitDepth;
uint64 disputeClockExtension;
uint64 disputeMaxClockDuration;
struct IsthmusConfig {
uint32 public operatorFeeScalar;
uint64 public operatorFeeConstant;
}

function upgrade(ISystemConfig[] _systemConfigs, IProxyAdmin[] _proxyAdmins, NewChainConfig[] _newConfigs) public;
function upgrade(ISystemConfig[] _systemConfigs, IProxyAdmin[] _proxyAdmins, IsthmusConfig[] _isthmusConfigs) public;
```

For each chain successfully upgraded, the following event is emitted:

```solidity
event Upgraded(uint256 indexed l2ChainId, SystemConfig indexed systemConfig, address indexed upgrader);
event Upgraded(uint256 indexed l2ChainId, ISystemConfig indexed systemConfig, address indexed upgrader);
```

This method reverts if the upgrade is not successful for any of the chains.
Expand All @@ -207,32 +234,29 @@ The high level logic of the upgrade method is as follows:

1. The Upgrade Controller Safe will `DELEGATECALL` to the `OPCM.upgrade()` method.
2. For each `_systemConfig`, the list of addresses in the chain is retrieved.
3. For each address, a two step upgrade is used where:
1. the first upgrade is to an `InitializerResetter` which resets the `initialized` value.
1. the implementation is updated to the final address and `upgrade()` is called on that address.

This approach requires that all contracts have an `upgrade()` function which sets the `initialized`
value to `true`. The `upgrade` function body should be empty unless it is used to set a new state
variable added to that contract since the last upgrade.

#### `IsthmusConfig` struct
3. For each address:
1. If it is receiving new state variables (only the SystemConfig for Isthmus), a call is made to:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think its great to leak the implementation details like only sys config for isthmus into the spec. How I would propose structuring this is having a section "Network Upgrades" and then having a subheading for each network upgrade and define the specifics for that upgrade in there

`ProxyAdmin.upgradeAndCall()` with data corresponding to the new value being set.
2. Otherwise, `ProxyAdmin.upgrade()` is called on that address.

This struct is used to pass the new chain configuration to the `upgrade` method, and so it will
vary for each release of the OP Contracts Manager, based on what (if any) new parameters are added.
This approach requires that any contracts which are receiving new state variables
have an upgrade function which:

In practice, this struct is likely to be have a unique name for each release of the OP Contracts
Manager.
1. Writes the new state variables
2. MUST only be callable once

By way of example, if an upgrade is adding a new variable `address foo` to the `SystemConfig` contract, for
an upgrade named `Example`, the struct could have the following definition:
Thus for Isthmus, the System config will receive the following new function.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We would replace this function in the next release and put upgradeKarst(KarstConfig _config)?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hypothetically if there was another change


```solidity
struct IsthmusConfig {
uint32 public operatorFeeScalar;
uint64 public operatorFeeConstant;
}
function upgradeIsthmus(IsthmusConfig _isthmusConfig) external;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the definition of this config?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

```solidity
struct IsthmusConfig {
uint32 public operatorFeeScalar;
uint64 public operatorFeeConstant;
}
function upgrade(ISystemConfig[] _systemConfigs, IProxyAdmin[] _proxyAdmins, IsthmusConfig[] _isthmusConfigs) public;

```

#### `IsthmusConfig` struct

This struct is used to pass the new chain configuration to the `upgrade` method. It's name and
field will vary for each release of the OP Contracts Manager, based on what (if any) new parameters
are being added.

#### Requirements on the OP Chain contracts

In general, all contracts used in an OP Chain SHOULD be proxied with a single shared implementation.
Expand Down