Commit 8f0a9b2d authored by blaine's avatar blaine Committed by GitHub

opcm-redesign: opcm targets a single release (#12851)

* fix: semver locking.

* fix: semver locking.

* feat: opcm impl contracts now type safe.

* feat: fixing test.

* fix: removing unused imports.

* fix: address didn't need to be payable.

* fix: moving all smart contract changes to first pr.

* fix: pr comments addressed.

* fix: removed InputContracts struct.

* fix: ran pre-pr

* fix: deploy implementations renaming version.

* fix: adding solidity changes to this pr.

* fix: adding v160 initializer back in.

* fix: removed branching logic from opcm.

* fix: removed SystemConfigV160.

* opcm-redesign: op-deployer changes

* fix: linting fix.

* fix: semver lock

---------
Co-authored-by: default avatarMatthew Slipper <me@matthewslipper.com>
parent c267d98b
......@@ -35,7 +35,7 @@ type SuperFaultProofConfig struct {
}
type OPCMImplementationsConfig struct {
Release string
L1ContractsRelease string
FaultProof SuperFaultProofConfig
......
......@@ -170,10 +170,9 @@ func DeploySuperchainToL1(l1Host *script.Host, superCfg *SuperchainConfig) (*Sup
ProofMaturityDelaySeconds: superCfg.Implementations.FaultProof.ProofMaturityDelaySeconds,
DisputeGameFinalityDelaySeconds: superCfg.Implementations.FaultProof.DisputeGameFinalityDelaySeconds,
MipsVersion: superCfg.Implementations.FaultProof.MipsVersion,
Release: superCfg.Implementations.Release,
L1ContractsRelease: superCfg.Implementations.L1ContractsRelease,
SuperchainConfigProxy: superDeployment.SuperchainConfigProxy,
ProtocolVersionsProxy: superDeployment.ProtocolVersionsProxy,
OpcmProxyOwner: superDeployment.SuperchainProxyAdmin,
UseInterop: superCfg.Implementations.UseInterop,
StandardVersionsToml: standard.VersionsMainnetData,
})
......@@ -210,7 +209,7 @@ func DeployL2ToL1(l1Host *script.Host, superCfg *SuperchainConfig, superDeployme
BasefeeScalar: cfg.GasPriceOracleBaseFeeScalar,
BlobBaseFeeScalar: cfg.GasPriceOracleBlobBaseFeeScalar,
L2ChainId: new(big.Int).SetUint64(cfg.L2ChainID),
OpcmProxy: superDeployment.OpcmProxy,
Opcm: superDeployment.Opcm,
SaltMixer: cfg.SaltMixer,
GasLimit: cfg.GasLimit,
DisputeGameType: cfg.DisputeGameType,
......
......@@ -9,8 +9,7 @@ type L1Deployment struct {
}
type Implementations struct {
OpcmProxy common.Address `json:"OPCMProxy"`
OpcmImpl common.Address `json:"OPCMImpl"`
Opcm common.Address `json:"OPCM"`
DelayedWETHImpl common.Address `json:"DelayedWETHImpl"`
OptimismPortalImpl common.Address `json:"OptimismPortalImpl"`
PreimageOracleSingleton common.Address `json:"PreimageOracleSingleton"`
......
......@@ -69,7 +69,7 @@ func (r *InteropDevRecipe) Build(addrs devkeys.Addresses) (*WorldConfig, error)
ProtocolVersionsOwner: superchainProtocolVersionsOwner,
Deployer: superchainDeployer,
Implementations: OPCMImplementationsConfig{
Release: "dev",
L1ContractsRelease: "dev",
FaultProof: SuperFaultProofConfig{
WithdrawalDelaySeconds: big.NewInt(604800),
MinProposalSizeBytes: big.NewInt(10000),
......
......@@ -164,10 +164,6 @@ func OPCM(ctx context.Context, cfg OPCMConfig) error {
if err != nil {
return fmt.Errorf("error getting standard versions TOML: %w", err)
}
opcmProxyOwnerAddr, err := standard.ManagerOwnerAddrFor(chainIDU64)
if err != nil {
return fmt.Errorf("error getting superchain proxy admin: %w", err)
}
signer := opcrypto.SignerFnFromBind(opcrypto.PrivateKeySignerFn(cfg.privateKeyECDSA, chainID))
chainDeployer := crypto.PubkeyToAddress(cfg.privateKeyECDSA.PublicKey)
......@@ -199,14 +195,14 @@ func OPCM(ctx context.Context, cfg OPCMConfig) error {
}
host.SetNonce(chainDeployer, nonce)
var release string
var l1ContractsRelease string
if cfg.ArtifactsLocator.IsTag() {
release = cfg.ArtifactsLocator.Tag
l1ContractsRelease = cfg.ArtifactsLocator.Tag
} else {
release = "dev"
l1ContractsRelease = "dev"
}
lgr.Info("deploying OPCM", "release", release)
lgr.Info("deploying OPCM", "l1ContractsRelease", l1ContractsRelease)
// We need to etch the Superchain addresses so that they have nonzero code
// and the checks in the OPCM constructor pass.
......@@ -238,10 +234,9 @@ func OPCM(ctx context.Context, cfg OPCMConfig) error {
ProofMaturityDelaySeconds: new(big.Int).SetUint64(cfg.ProofMaturityDelaySeconds),
DisputeGameFinalityDelaySeconds: new(big.Int).SetUint64(cfg.DisputeGameFinalityDelaySeconds),
MipsVersion: new(big.Int).SetUint64(cfg.MIPSVersion),
Release: release,
L1ContractsRelease: l1ContractsRelease,
SuperchainConfigProxy: superchainConfigAddr,
ProtocolVersionsProxy: protocolVersionsAddr,
OpcmProxyOwner: opcmProxyOwnerAddr,
StandardVersionsToml: standardVersionsTOML,
UseInterop: false,
},
......
......@@ -45,7 +45,7 @@ type OpChainDeployment struct {
}
type ImplementationsDeployment struct {
OpcmProxyAddress common.Address `json:"opcmProxyAddress"`
OpcmAddress common.Address `json:"opcmAddress"`
DelayedWETHImplAddress common.Address `json:"delayedWETHImplAddress"`
OptimismPortalImplAddress common.Address `json:"optimismPortalImplAddress"`
PreimageOracleSingletonAddress common.Address `json:"preimageOracleSingletonAddress"`
......@@ -113,7 +113,7 @@ func L1(globalState *state.State, chainID common.Hash) (*L1Contracts, error) {
// DelayedWETHPermissionlessGameProxyAddress: chainState.DelayedWETHPermissionlessGameProxyAddress,
},
ImplementationsDeployment: ImplementationsDeployment{
OpcmProxyAddress: globalState.ImplementationsDeployment.OpcmProxyAddress,
OpcmAddress: globalState.ImplementationsDeployment.OpcmAddress,
DelayedWETHImplAddress: globalState.ImplementationsDeployment.DelayedWETHImplAddress,
OptimismPortalImplAddress: globalState.ImplementationsDeployment.OptimismPortalImplAddress,
PreimageOracleSingletonAddress: globalState.ImplementationsDeployment.PreimageOracleSingletonAddress,
......
......@@ -207,6 +207,30 @@ func TestApplyExistingOPCM(t *testing.T) {
))
validateOPChainDeployment(t, ethClientCodeGetter(ctx, l1Client), st, intent)
releases := standard.L1VersionsSepolia.Releases["op-contracts/v1.6.0"]
implTests := []struct {
name string
expAddr common.Address
actAddr common.Address
}{
{"OptimismPortal", releases.OptimismPortal.ImplementationAddress, st.ImplementationsDeployment.OptimismPortalImplAddress},
{"SystemConfig,", releases.SystemConfig.ImplementationAddress, st.ImplementationsDeployment.SystemConfigImplAddress},
{"L1CrossDomainMessenger", releases.L1CrossDomainMessenger.ImplementationAddress, st.ImplementationsDeployment.L1CrossDomainMessengerImplAddress},
{"L1ERC721Bridge", releases.L1ERC721Bridge.ImplementationAddress, st.ImplementationsDeployment.L1ERC721BridgeImplAddress},
{"L1StandardBridge", releases.L1StandardBridge.ImplementationAddress, st.ImplementationsDeployment.L1StandardBridgeImplAddress},
{"OptimismMintableERC20Factory", releases.OptimismMintableERC20Factory.ImplementationAddress, st.ImplementationsDeployment.OptimismMintableERC20FactoryImplAddress},
{"DisputeGameFactory", releases.DisputeGameFactory.ImplementationAddress, st.ImplementationsDeployment.DisputeGameFactoryImplAddress},
{"MIPS", releases.MIPS.Address, st.ImplementationsDeployment.MipsSingletonAddress},
{"PreimageOracle", releases.PreimageOracle.Address, st.ImplementationsDeployment.PreimageOracleSingletonAddress},
{"DelayedWETH", releases.DelayedWETH.ImplementationAddress, st.ImplementationsDeployment.DelayedWETHImplAddress},
}
for _, tt := range implTests {
t.Run(tt.name, func(t *testing.T) {
require.Equal(t, tt.expAddr, tt.actAddr)
})
}
}
func TestL2BlockTimeOverride(t *testing.T) {
......@@ -571,7 +595,7 @@ func validateSuperchainDeployment(t *testing.T, st *state.State, cg codeGetter)
{"SuperchainConfigImpl", st.SuperchainDeployment.SuperchainConfigImplAddress},
{"ProtocolVersionsProxy", st.SuperchainDeployment.ProtocolVersionsProxyAddress},
{"ProtocolVersionsImpl", st.SuperchainDeployment.ProtocolVersionsImplAddress},
{"OpcmProxy", st.ImplementationsDeployment.OpcmProxyAddress},
{"Opcm", st.ImplementationsDeployment.OpcmAddress},
{"PreimageOracleSingleton", st.ImplementationsDeployment.PreimageOracleSingletonAddress},
{"MipsSingleton", st.ImplementationsDeployment.MipsSingletonAddress},
}
......
......@@ -48,57 +48,6 @@ func (c *Contract) GenericAddressGetter(ctx context.Context, functionName string
return c.callContractMethod(ctx, functionName, abi.Arguments{})
}
// GetImplementation retrieves the Implementation struct for a given release and contract name.
func (c *Contract) GetOPCMImplementationAddress(ctx context.Context, release, contractName string) (common.Address, error) {
methodName := "implementations"
method := abi.NewMethod(
methodName,
methodName,
abi.Function,
"view",
true,
false,
abi.Arguments{
{Name: "release", Type: mustType("string")},
{Name: "contractName", Type: mustType("string")},
},
abi.Arguments{
{Name: "logic", Type: mustType("address")},
{Name: "initializer", Type: mustType("bytes4")},
},
)
calldata, err := method.Inputs.Pack(release, contractName)
if err != nil {
return common.Address{}, fmt.Errorf("failed to pack inputs: %w", err)
}
msg := ethereum.CallMsg{
To: &c.addr,
Data: append(bytes.Clone(method.ID), calldata...),
}
result, err := c.client.CallContract(ctx, msg, nil)
if err != nil {
return common.Address{}, fmt.Errorf("failed to call contract: %w", err)
}
out, err := method.Outputs.Unpack(result)
if err != nil {
return common.Address{}, fmt.Errorf("failed to unpack result: %w", err)
}
if len(out) != 2 {
return common.Address{}, fmt.Errorf("unexpected output length: %d", len(out))
}
logic, ok := out[0].(common.Address)
if !ok {
return common.Address{}, fmt.Errorf("unexpected type for logic: %T", out[0])
}
return logic, nil
}
func (c *Contract) callContractMethod(ctx context.Context, methodName string, inputs abi.Arguments, args ...interface{}) (common.Address, error) {
method := abi.NewMethod(
methodName,
......
......@@ -18,12 +18,11 @@ type DeployImplementationsInput struct {
DisputeGameFinalityDelaySeconds *big.Int
MipsVersion *big.Int
// Release version to set OPCM implementations for, of the format `op-contracts/vX.Y.Z`.
Release string
L1ContractsRelease string
SuperchainConfigProxy common.Address
ProtocolVersionsProxy common.Address
UseInterop bool // if true, deploy Interop implementations
OpcmProxyOwner common.Address
StandardVersionsToml string // contents of 'standard-versions-mainnet.toml' or 'standard-versions-sepolia.toml' file
}
......@@ -32,8 +31,7 @@ func (input *DeployImplementationsInput) InputSet() bool {
}
type DeployImplementationsOutput struct {
OpcmProxy common.Address
OpcmImpl common.Address
Opcm common.Address
DelayedWETHImpl common.Address
OptimismPortalImpl common.Address
PreimageOracleSingleton common.Address
......
......@@ -26,7 +26,7 @@ type DeployOPChainInputV160 struct {
BasefeeScalar uint32
BlobBaseFeeScalar uint32
L2ChainId *big.Int
OpcmProxy common.Address
Opcm common.Address
SaltMixer string
GasLimit uint64
......@@ -122,8 +122,8 @@ func deployOPChain[T any](host *script.Host, input T) (DeployOPChainOutput, erro
type ReadImplementationAddressesInput struct {
DeployOPChainOutput
OpcmProxy common.Address
Release string
Opcm common.Address
Release string
}
type ReadImplementationAddressesOutput struct {
......
......@@ -31,7 +31,7 @@ func DeployAltDA(env *Env, intent *state.Intent, st *state.State, chainID common
lgr.Info("deploying alt-da contracts")
dao, err = opcm.DeployAltDA(env.L1ScriptHost, opcm.DeployAltDAInput{
Salt: st.Create2Salt,
ProxyAdmin: st.ImplementationsDeployment.OpcmProxyAddress,
ProxyAdmin: chainState.ProxyAdminAddress,
ChallengeContractOwner: chainIntent.Roles.L1ProxyAdminOwner,
ChallengeWindow: new(big.Int).SetUint64(chainIntent.DangerousAltDAConfig.DAChallengeWindow),
ResolveWindow: new(big.Int).SetUint64(chainIntent.DangerousAltDAConfig.DAResolveWindow),
......
......@@ -68,10 +68,9 @@ func DeployImplementations(env *Env, intent *state.Intent, st *state.State) erro
ProofMaturityDelaySeconds: new(big.Int).SetUint64(proofParams.ProofMaturityDelaySeconds),
DisputeGameFinalityDelaySeconds: new(big.Int).SetUint64(proofParams.DisputeGameFinalityDelaySeconds),
MipsVersion: new(big.Int).SetUint64(proofParams.MIPSVersion),
Release: contractsRelease,
L1ContractsRelease: contractsRelease,
SuperchainConfigProxy: st.SuperchainDeployment.SuperchainConfigProxyAddress,
ProtocolVersionsProxy: st.SuperchainDeployment.ProtocolVersionsProxyAddress,
OpcmProxyOwner: st.SuperchainDeployment.ProxyAdminAddress,
StandardVersionsToml: standardVersionsTOML,
UseInterop: intent.UseInterop,
},
......@@ -81,7 +80,7 @@ func DeployImplementations(env *Env, intent *state.Intent, st *state.State) erro
}
st.ImplementationsDeployment = &state.ImplementationsDeployment{
OpcmProxyAddress: dio.OpcmProxy,
OpcmAddress: dio.Opcm,
DelayedWETHImplAddress: dio.DelayedWETHImpl,
OptimismPortalImplAddress: dio.OptimismPortalImpl,
PreimageOracleSingletonAddress: dio.PreimageOracleSingleton,
......
......@@ -45,12 +45,12 @@ func InitLiveStrategy(ctx context.Context, env *Env, intent *state.Intent, st *s
SuperchainConfigProxyAddress: common.Address(*superCfg.Config.SuperchainConfigAddr),
}
opcmProxy, err := standard.ManagerImplementationAddrFor(intent.L1ChainID)
opcmAddress, err := standard.ManagerImplementationAddrFor(intent.L1ChainID)
if err != nil {
return fmt.Errorf("error getting OPCM proxy address: %w", err)
}
st.ImplementationsDeployment = &state.ImplementationsDeployment{
OpcmProxyAddress: opcmProxy,
OpcmAddress: opcmAddress,
}
}
......
......@@ -34,7 +34,7 @@ func DeployOPChain(env *Env, intent *state.Intent, st *state.State, chainID comm
return opcm.DeployOPChainOutput{}, fmt.Errorf("error making deploy OP chain input: %w", err)
}
opcmAddr = input.OpcmProxy
opcmAddr = input.Opcm
return opcm.DeployOPChainV160(env.L1ScriptHost, input)
}
default:
......@@ -44,7 +44,7 @@ func DeployOPChain(env *Env, intent *state.Intent, st *state.State, chainID comm
return opcm.DeployOPChainOutput{}, fmt.Errorf("error making deploy OP chain input: %w", err)
}
opcmAddr = input.OpcmProxy
opcmAddr = input.Opcm
return opcm.DeployOPChainIsthmus(env.L1ScriptHost, input)
}
}
......@@ -67,7 +67,7 @@ func DeployOPChain(env *Env, intent *state.Intent, st *state.State, chainID comm
readInput := opcm.ReadImplementationAddressesInput{
DeployOPChainOutput: dco,
OpcmProxy: opcmAddr,
Opcm: opcmAddr,
Release: release,
}
impls, err := opcm.ReadImplementationAddresses(env.L1ScriptHost, readInput)
......@@ -126,7 +126,7 @@ func makeDCIV160(intent *state.Intent, thisIntent *state.ChainIntent, chainID co
BasefeeScalar: standard.BasefeeScalar,
BlobBaseFeeScalar: standard.BlobBaseFeeScalar,
L2ChainId: chainID.Big(),
OpcmProxy: st.ImplementationsDeployment.OpcmProxyAddress,
Opcm: st.ImplementationsDeployment.OpcmAddress,
SaltMixer: st.Create2Salt.String(), // passing through salt generated at state initialization
GasLimit: standard.GasLimit,
DisputeGameType: proofParams.DisputeGameType,
......
......@@ -134,10 +134,11 @@ func ManagerImplementationAddrFor(chainID uint64) (common.Address, error) {
switch chainID {
case 1:
// Generated using the bootstrap command on 10/18/2024.
return common.HexToAddress("0x18cec91779995ad14c880e4095456b9147160790"), nil
// TODO: @blmalone this needs re-bootstrapped because it's still proxied
return common.HexToAddress(""), nil
case 11155111:
// Generated using the bootstrap command on 10/18/2024.
return common.HexToAddress("0xf564eea7960ea244bfebcbbb17858748606147bf"), nil
// Generated using the bootstrap command on 11/15/2024.
return common.HexToAddress("0xde9eacb994a6eb12997445f8a63a22772c5c4313"), nil
default:
return common.Address{}, fmt.Errorf("unsupported chain ID: %d", chainID)
}
......@@ -172,7 +173,7 @@ func SystemOwnerAddrFor(chainID uint64) (common.Address, error) {
func ArtifactsURLForTag(tag string) (*url.URL, error) {
switch tag {
case "op-contracts/v1.6.0":
return url.Parse(standardArtifactsURL("3a27c6dc0cb61b36feaac26def98c64b4a48ec8f5c5ba6965e8ae3157606043c"))
return url.Parse(standardArtifactsURL("e1f0c4020618c4a98972e7124c39686cab2e31d5d7846f9ce5e0d5eed0f5ff32"))
case "op-contracts/v1.7.0-beta.1+l2-contracts":
return url.Parse(standardArtifactsURL("b0fb1f6f674519d637cff39a22187a5993d7f81a6d7b7be6507a0b50a5e38597"))
default:
......
......@@ -64,7 +64,7 @@ type SuperchainDeployment struct {
}
type ImplementationsDeployment struct {
OpcmProxyAddress common.Address `json:"opcmProxyAddress"`
OpcmAddress common.Address `json:"opcmAddress"`
DelayedWETHImplAddress common.Address `json:"delayedWETHImplAddress"`
OptimismPortalImplAddress common.Address `json:"optimismPortalImplAddress"`
PreimageOracleSingletonAddress common.Address `json:"preimageOracleSingletonAddress"`
......
......@@ -162,7 +162,7 @@ contract Deploy is Deployer {
L1ERC721Bridge: getAddress("L1ERC721BridgeProxy"),
ProtocolVersions: getAddress("ProtocolVersionsProxy"),
SuperchainConfig: getAddress("SuperchainConfigProxy"),
OPContractsManager: getAddress("OPContractsManagerProxy")
OPContractsManager: getAddress("OPContractsManager")
});
}
......@@ -378,13 +378,12 @@ contract Deploy is Deployer {
dii.set(dii.disputeGameFinalityDelaySeconds.selector, cfg.disputeGameFinalityDelaySeconds());
dii.set(dii.mipsVersion.selector, Config.useMultithreadedCannon() ? 2 : 1);
string memory release = "dev";
dii.set(dii.release.selector, release);
dii.set(dii.l1ContractsRelease.selector, release);
dii.set(
dii.standardVersionsToml.selector, string.concat(vm.projectRoot(), "/test/fixtures/standard-versions.toml")
);
dii.set(dii.superchainConfigProxy.selector, mustGetAddress("SuperchainConfigProxy"));
dii.set(dii.protocolVersionsProxy.selector, mustGetAddress("ProtocolVersionsProxy"));
dii.set(dii.opcmProxyOwner.selector, cfg.finalSystemOwner());
if (_isInterop) {
di = DeployImplementations(new DeployImplementationsInterop());
......@@ -409,8 +408,7 @@ contract Deploy is Deployer {
save("DelayedWETH", address(dio.delayedWETHImpl()));
save("PreimageOracle", address(dio.preimageOracleSingleton()));
save("Mips", address(dio.mipsSingleton()));
save("OPContractsManagerProxy", address(dio.opcmProxy()));
save("OPContractsManager", address(dio.opcmImpl()));
save("OPContractsManager", address(dio.opcm()));
Types.ContractSet memory contracts = _impls();
ChainAssertions.checkL1CrossDomainMessenger({ _contracts: contracts, _vm: vm, _isProxy: false });
......@@ -446,7 +444,7 @@ contract Deploy is Deployer {
// Ensure that the requisite contracts are deployed
address superchainConfigProxy = mustGetAddress("SuperchainConfigProxy");
OPContractsManager opcm = OPContractsManager(mustGetAddress("OPContractsManagerProxy"));
OPContractsManager opcm = OPContractsManager(mustGetAddress("OPContractsManager"));
OPContractsManager.DeployInput memory deployInput = getDeployInput();
OPContractsManager.DeployOutput memory deployOutput = opcm.deploy(deployInput);
......
......@@ -8,16 +8,11 @@ import { LibString } from "@solady/utils/LibString.sol";
import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol";
import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol";
import { IProtocolVersions } from "src/L1/interfaces/IProtocolVersions.sol";
import { ISystemConfigV160 } from "src/L1/interfaces/ISystemConfigV160.sol";
import { IL1CrossDomainMessengerV160 } from "src/L1/interfaces/IL1CrossDomainMessengerV160.sol";
import { IL1StandardBridgeV160 } from "src/L1/interfaces/IL1StandardBridgeV160.sol";
import { Constants } from "src/libraries/Constants.sol";
import { Predeploys } from "src/libraries/Predeploys.sol";
import { Bytes } from "src/libraries/Bytes.sol";
import { IProxy } from "src/universal/interfaces/IProxy.sol";
import { IDelayedWETH } from "src/dispute/interfaces/IDelayedWETH.sol";
import { IPreimageOracle } from "src/cannon/interfaces/IPreimageOracle.sol";
import { IMIPS } from "src/cannon/interfaces/IMIPS.sol";
......@@ -51,8 +46,9 @@ contract DeployImplementationsInput is BaseDeployIO {
uint256 internal _disputeGameFinalityDelaySeconds;
uint256 internal _mipsVersion;
// The release version to set OPCM implementations for, of the format `op-contracts/vX.Y.Z`.
string internal _release;
// This is used in opcm to signal which version of the L1 smart contracts is deployed.
// It takes the format of `op-contracts/v*.*.*`.
string internal _l1ContractsRelease;
// Outputs from DeploySuperchain.s.sol.
ISuperchainConfig internal _superchainConfigProxy;
......@@ -60,8 +56,6 @@ contract DeployImplementationsInput is BaseDeployIO {
string internal _standardVersionsToml;
address internal _opcmProxyOwner;
function set(bytes4 _sel, uint256 _value) public {
require(_value != 0, "DeployImplementationsInput: cannot set zero value");
......@@ -85,7 +79,7 @@ contract DeployImplementationsInput is BaseDeployIO {
function set(bytes4 _sel, string memory _value) public {
require(!LibString.eq(_value, ""), "DeployImplementationsInput: cannot set empty string");
if (_sel == this.release.selector) _release = _value;
if (_sel == this.l1ContractsRelease.selector) _l1ContractsRelease = _value;
else if (_sel == this.standardVersionsToml.selector) _standardVersionsToml = _value;
else revert("DeployImplementationsInput: unknown selector");
}
......@@ -94,7 +88,6 @@ contract DeployImplementationsInput is BaseDeployIO {
require(_addr != address(0), "DeployImplementationsInput: cannot set zero address");
if (_sel == this.superchainConfigProxy.selector) _superchainConfigProxy = ISuperchainConfig(_addr);
else if (_sel == this.protocolVersionsProxy.selector) _protocolVersionsProxy = IProtocolVersions(_addr);
else if (_sel == this.opcmProxyOwner.selector) _opcmProxyOwner = _addr;
else revert("DeployImplementationsInput: unknown selector");
}
......@@ -141,9 +134,9 @@ contract DeployImplementationsInput is BaseDeployIO {
return _mipsVersion;
}
function release() public view returns (string memory) {
require(!LibString.eq(_release, ""), "DeployImplementationsInput: not set");
return _release;
function l1ContractsRelease() public view returns (string memory) {
require(!LibString.eq(_l1ContractsRelease, ""), "DeployImplementationsInput: not set");
return _l1ContractsRelease;
}
function standardVersionsToml() public view returns (string memory) {
......@@ -160,16 +153,10 @@ contract DeployImplementationsInput is BaseDeployIO {
require(address(_protocolVersionsProxy) != address(0), "DeployImplementationsInput: not set");
return _protocolVersionsProxy;
}
function opcmProxyOwner() public view returns (address) {
require(address(_opcmProxyOwner) != address(0), "DeployImplementationsInput: not set");
return _opcmProxyOwner;
}
}
contract DeployImplementationsOutput is BaseDeployIO {
OPContractsManager internal _opcmProxy;
OPContractsManager internal _opcmImpl;
OPContractsManager internal _opcm;
IDelayedWETH internal _delayedWETHImpl;
IOptimismPortal2 internal _optimismPortalImpl;
IPreimageOracle internal _preimageOracleSingleton;
......@@ -185,8 +172,7 @@ contract DeployImplementationsOutput is BaseDeployIO {
require(_addr != address(0), "DeployImplementationsOutput: cannot set zero address");
// forgefmt: disable-start
if (_sel == this.opcmProxy.selector) _opcmProxy = OPContractsManager(payable(_addr));
else if (_sel == this.opcmImpl.selector) _opcmImpl = OPContractsManager(payable(_addr));
if (_sel == this.opcm.selector) _opcm = OPContractsManager(_addr);
else if (_sel == this.optimismPortalImpl.selector) _optimismPortalImpl = IOptimismPortal2(payable(_addr));
else if (_sel == this.delayedWETHImpl.selector) _delayedWETHImpl = IDelayedWETH(payable(_addr));
else if (_sel == this.preimageOracleSingleton.selector) _preimageOracleSingleton = IPreimageOracle(_addr);
......@@ -201,12 +187,11 @@ contract DeployImplementationsOutput is BaseDeployIO {
// forgefmt: disable-end
}
function checkOutput(DeployImplementationsInput _dii) public {
function checkOutput(DeployImplementationsInput _dii) public view {
// With 12 addresses, we'd get a stack too deep error if we tried to do this inline as a
// single call to `Solarray.addresses`. So we split it into two calls.
address[] memory addrs1 = Solarray.addresses(
address(this.opcmProxy()),
address(this.opcmImpl()),
address(this.opcm()),
address(this.optimismPortalImpl()),
address(this.delayedWETHImpl()),
address(this.preimageOracleSingleton()),
......@@ -227,15 +212,9 @@ contract DeployImplementationsOutput is BaseDeployIO {
assertValidDeploy(_dii);
}
function opcmProxy() public returns (OPContractsManager) {
DeployUtils.assertValidContractAddress(address(_opcmProxy));
DeployUtils.assertERC1967ImplementationSet(address(_opcmProxy));
return _opcmProxy;
}
function opcmImpl() public view returns (OPContractsManager) {
DeployUtils.assertValidContractAddress(address(_opcmImpl));
return _opcmImpl;
function opcm() public view returns (OPContractsManager) {
DeployUtils.assertValidContractAddress(address(_opcm));
return _opcm;
}
function optimismPortalImpl() public view returns (IOptimismPortal2) {
......@@ -289,40 +268,22 @@ contract DeployImplementationsOutput is BaseDeployIO {
}
// -------- Deployment Assertions --------
function assertValidDeploy(DeployImplementationsInput _dii) public {
function assertValidDeploy(DeployImplementationsInput _dii) public view {
assertValidDelayedWETHImpl(_dii);
assertValidDisputeGameFactoryImpl(_dii);
assertValidL1CrossDomainMessengerImpl(_dii);
assertValidL1ERC721BridgeImpl(_dii);
assertValidL1StandardBridgeImpl(_dii);
assertValidMipsSingleton(_dii);
assertValidOpcmProxy(_dii);
assertValidOpcmImpl(_dii);
assertValidOpcm(_dii);
assertValidOptimismMintableERC20FactoryImpl(_dii);
assertValidOptimismPortalImpl(_dii);
assertValidPreimageOracleSingleton(_dii);
assertValidSystemConfigImpl(_dii);
}
function assertValidOpcmProxy(DeployImplementationsInput _dii) internal {
// First we check the proxy as itself.
IProxy proxy = IProxy(payable(address(opcmProxy())));
vm.prank(address(0));
address admin = proxy.admin();
require(admin == address(_dii.opcmProxyOwner()), "OPCMP-10");
// Then we check the proxy as OPCM.
DeployUtils.assertInitialized({ _contractAddress: address(opcmProxy()), _slot: 0, _offset: 0 });
require(address(opcmProxy().superchainConfig()) == address(_dii.superchainConfigProxy()), "OPCMP-20");
require(address(opcmProxy().protocolVersions()) == address(_dii.protocolVersionsProxy()), "OPCMP-30");
require(LibString.eq(opcmProxy().latestRelease(), _dii.release()), "OPCMP-50"); // Initial release is latest.
}
function assertValidOpcmImpl(DeployImplementationsInput _dii) internal {
IProxy proxy = IProxy(payable(address(opcmProxy())));
vm.prank(address(0));
OPContractsManager impl = OPContractsManager(proxy.implementation());
DeployUtils.assertInitialized({ _contractAddress: address(impl), _slot: 0, _offset: 0 });
function assertValidOpcm(DeployImplementationsInput _dii) internal view {
OPContractsManager impl = OPContractsManager(address(opcm()));
require(address(impl.superchainConfig()) == address(_dii.superchainConfigProxy()), "OPCMI-10");
require(address(impl.protocolVersions()) == address(_dii.protocolVersionsProxy()), "OPCMI-20");
}
......@@ -361,7 +322,6 @@ contract DeployImplementationsOutput is BaseDeployIO {
function assertValidMipsSingleton(DeployImplementationsInput) internal view {
IMIPS mips = mipsSingleton();
require(address(mips.oracle()) == address(preimageOracleSingleton()), "MIPS-10");
}
......@@ -480,102 +440,38 @@ contract DeployImplementations is Script {
// --- OP Contracts Manager ---
function opcmSystemConfigSetter(
DeployImplementationsInput _dii,
DeployImplementationsOutput _dio
)
internal
view
virtual
returns (OPContractsManager.ImplementationSetter memory)
{
// When configuring OPCM during Solidity tests, we are using the latest SystemConfig.sol
// version in this repo, which contains Custom Gas Token (CGT) features. This CGT version
// has a different `initialize` signature than the SystemConfig version that was released
// as part of `op-contracts/v1.6.0`, which is no longer in the repo. When running this
// script's bytecode for a production deploy of OPCM at `op-contracts/v1.6.0`, we need to
// use the ISystemConfigV160 interface instead of ISystemConfig. Therefore the selector used
// is a function of the `release` passed in by the caller.
bytes4 selector = LibString.eq(_dii.release(), "op-contracts/v1.6.0")
? ISystemConfigV160.initialize.selector
: ISystemConfig.initialize.selector;
return OPContractsManager.ImplementationSetter({
name: "SystemConfig",
info: OPContractsManager.Implementation(address(_dio.systemConfigImpl()), selector)
});
}
function l1CrossDomainMessengerConfigSetter(
DeployImplementationsInput _dii,
DeployImplementationsOutput _dio
)
internal
view
virtual
returns (OPContractsManager.ImplementationSetter memory)
{
bytes4 selector = LibString.eq(_dii.release(), "op-contracts/v1.6.0")
? IL1CrossDomainMessengerV160.initialize.selector
: IL1CrossDomainMessenger.initialize.selector;
return OPContractsManager.ImplementationSetter({
name: "L1CrossDomainMessenger",
info: OPContractsManager.Implementation(address(_dio.l1CrossDomainMessengerImpl()), selector)
});
}
function l1StandardBridgeConfigSetter(
DeployImplementationsInput _dii,
DeployImplementationsOutput _dio
)
internal
view
virtual
returns (OPContractsManager.ImplementationSetter memory)
{
bytes4 selector = LibString.eq(_dii.release(), "op-contracts/v1.6.0")
? IL1StandardBridgeV160.initialize.selector
: IL1StandardBridge.initialize.selector;
return OPContractsManager.ImplementationSetter({
name: "L1StandardBridge",
info: OPContractsManager.Implementation(address(_dio.l1StandardBridgeImpl()), selector)
});
}
// Deploy and initialize a proxied OPContractsManager.
function createOPCMContract(
DeployImplementationsInput _dii,
DeployImplementationsOutput _dio,
OPContractsManager.Blueprints memory _blueprints,
string memory _release,
OPContractsManager.ImplementationSetter[] memory _setters
string memory _l1ContractsRelease
)
internal
virtual
returns (OPContractsManager opcmProxy_)
returns (OPContractsManager opcm_)
{
address opcmProxyOwner = _dii.opcmProxyOwner();
ISuperchainConfig superchainConfigProxy = _dii.superchainConfigProxy();
IProtocolVersions protocolVersionsProxy = _dii.protocolVersionsProxy();
OPContractsManager.Implementations memory implementations = OPContractsManager.Implementations({
l1ERC721BridgeImpl: address(_dio.l1ERC721BridgeImpl()),
optimismPortalImpl: address(_dio.optimismPortalImpl()),
systemConfigImpl: address(_dio.systemConfigImpl()),
optimismMintableERC20FactoryImpl: address(_dio.optimismMintableERC20FactoryImpl()),
l1CrossDomainMessengerImpl: address(_dio.l1CrossDomainMessengerImpl()),
l1StandardBridgeImpl: address(_dio.l1StandardBridgeImpl()),
disputeGameFactoryImpl: address(_dio.disputeGameFactoryImpl()),
delayedWETHImpl: address(_dio.delayedWETHImpl()),
mipsImpl: address(_dio.mipsSingleton())
});
vm.broadcast(msg.sender);
IProxy proxy = IProxy(
DeployUtils.create1({
_name: "Proxy",
_args: DeployUtils.encodeConstructor(abi.encodeCall(IProxy.__constructor__, (msg.sender)))
})
opcm_ = new OPContractsManager(
superchainConfigProxy, protocolVersionsProxy, _l1ContractsRelease, _blueprints, implementations
);
deployOPContractsManagerImpl(_dii, _dio);
OPContractsManager opcmImpl = _dio.opcmImpl();
OPContractsManager.InitializerInputs memory initializerInputs =
OPContractsManager.InitializerInputs(_blueprints, _setters, _release, true);
vm.startBroadcast(msg.sender);
proxy.upgradeToAndCall(address(opcmImpl), abi.encodeCall(opcmImpl.initialize, (initializerInputs)));
proxy.changeAdmin(address(opcmProxyOwner)); // transfer ownership of Proxy contract to the ProxyAdmin contract
vm.stopBroadcast();
opcmProxy_ = OPContractsManager(address(proxy));
vm.label(address(opcm_), "OPContractsManager");
_dio.set(_dio.opcm.selector, address(opcm_));
}
function deployOPContractsManager(
......@@ -585,72 +481,42 @@ contract DeployImplementations is Script {
public
virtual
{
string memory release = _dii.release();
// First we deploy the blueprints for the singletons deployed by OPCM.
// forgefmt: disable-start
bytes32 salt = _dii.salt();
OPContractsManager.Blueprints memory blueprints;
vm.startBroadcast(msg.sender);
blueprints.addressManager = deployBytecode(Blueprint.blueprintDeployerBytecode(vm.getCode("AddressManager")), salt);
blueprints.proxy = deployBytecode(Blueprint.blueprintDeployerBytecode(vm.getCode("Proxy")), salt);
blueprints.proxyAdmin = deployBytecode(Blueprint.blueprintDeployerBytecode(vm.getCode("ProxyAdmin")), salt);
blueprints.l1ChugSplashProxy = deployBytecode(Blueprint.blueprintDeployerBytecode(vm.getCode("L1ChugSplashProxy")), salt);
blueprints.resolvedDelegateProxy = deployBytecode(Blueprint.blueprintDeployerBytecode(vm.getCode("ResolvedDelegateProxy")), salt);
blueprints.anchorStateRegistry = deployBytecode(Blueprint.blueprintDeployerBytecode(vm.getCode("AnchorStateRegistry")), salt);
(blueprints.permissionedDisputeGame1, blueprints.permissionedDisputeGame2) = deployBigBytecode(vm.getCode("PermissionedDisputeGame"), salt);
vm.stopBroadcast();
// forgefmt: disable-end
OPContractsManager.ImplementationSetter[] memory setters = new OPContractsManager.ImplementationSetter[](9);
setters[0] = OPContractsManager.ImplementationSetter({
name: "L1ERC721Bridge",
info: OPContractsManager.Implementation(address(_dio.l1ERC721BridgeImpl()), IL1ERC721Bridge.initialize.selector)
});
setters[1] = OPContractsManager.ImplementationSetter({
name: "OptimismPortal",
info: OPContractsManager.Implementation(
address(_dio.optimismPortalImpl()), IOptimismPortal2.initialize.selector
)
});
setters[2] = opcmSystemConfigSetter(_dii, _dio);
setters[3] = OPContractsManager.ImplementationSetter({
name: "OptimismMintableERC20Factory",
info: OPContractsManager.Implementation(
address(_dio.optimismMintableERC20FactoryImpl()), IOptimismMintableERC20Factory.initialize.selector
)
});
setters[4] = l1CrossDomainMessengerConfigSetter(_dii, _dio);
setters[5] = l1StandardBridgeConfigSetter(_dii, _dio);
setters[6] = OPContractsManager.ImplementationSetter({
name: "DisputeGameFactory",
info: OPContractsManager.Implementation(
address(_dio.disputeGameFactoryImpl()), IDisputeGameFactory.initialize.selector
)
});
setters[7] = OPContractsManager.ImplementationSetter({
name: "DelayedWETH",
info: OPContractsManager.Implementation(address(_dio.delayedWETHImpl()), IDelayedWETH.initialize.selector)
});
setters[8] = OPContractsManager.ImplementationSetter({
name: "MIPS",
// MIPS is a singleton for all chains, so it doesn't need to be initialized, so the
// selector is just `bytes4(0)`.
info: OPContractsManager.Implementation(address(_dio.mipsSingleton()), bytes4(0))
});
string memory l1ContractsRelease = _dii.l1ContractsRelease();
string memory stdVerToml = _dii.standardVersionsToml();
string memory contractName = "op_contracts_manager";
OPContractsManager opcm;
// This call contains a broadcast to deploy OPCM which is proxied.
OPContractsManager opcmProxy = createOPCMContract(_dii, _dio, blueprints, release, setters);
address existingImplementation = getReleaseAddress(l1ContractsRelease, contractName, stdVerToml);
if (existingImplementation != address(0)) {
opcm = OPContractsManager(existingImplementation);
} else {
// First we deploy the blueprints for the singletons deployed by OPCM.
// forgefmt: disable-start
bytes32 salt = _dii.salt();
OPContractsManager.Blueprints memory blueprints;
vm.startBroadcast(msg.sender);
blueprints.addressManager = deployBytecode(Blueprint.blueprintDeployerBytecode(vm.getCode("AddressManager")), salt);
blueprints.proxy = deployBytecode(Blueprint.blueprintDeployerBytecode(vm.getCode("Proxy")), salt);
blueprints.proxyAdmin = deployBytecode(Blueprint.blueprintDeployerBytecode(vm.getCode("ProxyAdmin")), salt);
blueprints.l1ChugSplashProxy = deployBytecode(Blueprint.blueprintDeployerBytecode(vm.getCode("L1ChugSplashProxy")), salt);
blueprints.resolvedDelegateProxy = deployBytecode(Blueprint.blueprintDeployerBytecode(vm.getCode("ResolvedDelegateProxy")), salt);
blueprints.anchorStateRegistry = deployBytecode(Blueprint.blueprintDeployerBytecode(vm.getCode("AnchorStateRegistry")), salt);
(blueprints.permissionedDisputeGame1, blueprints.permissionedDisputeGame2) = deployBigBytecode(vm.getCode("PermissionedDisputeGame"), salt);
vm.stopBroadcast();
// forgefmt: disable-end
opcm = createOPCMContract(_dii, _dio, blueprints, l1ContractsRelease);
}
vm.label(address(opcmProxy), "OPContractsManager");
_dio.set(_dio.opcmProxy.selector, address(opcmProxy));
vm.label(address(opcm), "OPContractsManager");
_dio.set(_dio.opcm.selector, address(opcm));
}
// --- Core Contracts ---
function deploySystemConfigImpl(DeployImplementationsInput _dii, DeployImplementationsOutput _dio) public virtual {
string memory release = _dii.release();
string memory release = _dii.l1ContractsRelease();
string memory stdVerToml = _dii.standardVersionsToml();
// Using snake case for contract name to match the TOML file in superchain-registry.
string memory contractName = "system_config";
......@@ -659,7 +525,7 @@ contract DeployImplementations is Script {
address existingImplementation = getReleaseAddress(release, contractName, stdVerToml);
if (existingImplementation != address(0)) {
impl = ISystemConfig(existingImplementation);
} else if (isDevelopRelease(release)) {
} else {
// Deploy a new implementation for development builds.
vm.broadcast(msg.sender);
impl = ISystemConfig(
......@@ -668,8 +534,6 @@ contract DeployImplementations is Script {
_args: DeployUtils.encodeConstructor(abi.encodeCall(ISystemConfig.__constructor__, ()))
})
);
} else {
revert(string.concat("DeployImplementations: failed to deploy release ", release));
}
vm.label(address(impl), "SystemConfigImpl");
......@@ -683,7 +547,7 @@ contract DeployImplementations is Script {
public
virtual
{
string memory release = _dii.release();
string memory release = _dii.l1ContractsRelease();
string memory stdVerToml = _dii.standardVersionsToml();
string memory contractName = "l1_cross_domain_messenger";
IL1CrossDomainMessenger impl;
......@@ -691,7 +555,7 @@ contract DeployImplementations is Script {
address existingImplementation = getReleaseAddress(release, contractName, stdVerToml);
if (existingImplementation != address(0)) {
impl = IL1CrossDomainMessenger(existingImplementation);
} else if (isDevelopRelease(release)) {
} else {
vm.broadcast(msg.sender);
impl = IL1CrossDomainMessenger(
DeployUtils.create1({
......@@ -699,8 +563,6 @@ contract DeployImplementations is Script {
_args: DeployUtils.encodeConstructor(abi.encodeCall(IL1CrossDomainMessenger.__constructor__, ()))
})
);
} else {
revert(string.concat("DeployImplementations: failed to deploy release ", release));
}
vm.label(address(impl), "L1CrossDomainMessengerImpl");
......@@ -714,7 +576,7 @@ contract DeployImplementations is Script {
public
virtual
{
string memory release = _dii.release();
string memory release = _dii.l1ContractsRelease();
string memory stdVerToml = _dii.standardVersionsToml();
string memory contractName = "l1_erc721_bridge";
IL1ERC721Bridge impl;
......@@ -722,7 +584,7 @@ contract DeployImplementations is Script {
address existingImplementation = getReleaseAddress(release, contractName, stdVerToml);
if (existingImplementation != address(0)) {
impl = IL1ERC721Bridge(existingImplementation);
} else if (isDevelopRelease(release)) {
} else {
vm.broadcast(msg.sender);
impl = IL1ERC721Bridge(
DeployUtils.create1({
......@@ -730,8 +592,6 @@ contract DeployImplementations is Script {
_args: DeployUtils.encodeConstructor(abi.encodeCall(IL1ERC721Bridge.__constructor__, ()))
})
);
} else {
revert(string.concat("DeployImplementations: failed to deploy release ", release));
}
vm.label(address(impl), "L1ERC721BridgeImpl");
......@@ -745,7 +605,7 @@ contract DeployImplementations is Script {
public
virtual
{
string memory release = _dii.release();
string memory release = _dii.l1ContractsRelease();
string memory stdVerToml = _dii.standardVersionsToml();
string memory contractName = "l1_standard_bridge";
IL1StandardBridge impl;
......@@ -753,7 +613,7 @@ contract DeployImplementations is Script {
address existingImplementation = getReleaseAddress(release, contractName, stdVerToml);
if (existingImplementation != address(0)) {
impl = IL1StandardBridge(payable(existingImplementation));
} else if (isDevelopRelease(release)) {
} else {
vm.broadcast(msg.sender);
impl = IL1StandardBridge(
DeployUtils.create1({
......@@ -761,8 +621,6 @@ contract DeployImplementations is Script {
_args: DeployUtils.encodeConstructor(abi.encodeCall(IL1StandardBridge.__constructor__, ()))
})
);
} else {
revert(string.concat("DeployImplementations: failed to deploy release ", release));
}
vm.label(address(impl), "L1StandardBridgeImpl");
......@@ -776,7 +634,7 @@ contract DeployImplementations is Script {
public
virtual
{
string memory release = _dii.release();
string memory release = _dii.l1ContractsRelease();
string memory stdVerToml = _dii.standardVersionsToml();
string memory contractName = "optimism_mintable_erc20_factory";
IOptimismMintableERC20Factory impl;
......@@ -784,7 +642,7 @@ contract DeployImplementations is Script {
address existingImplementation = getReleaseAddress(release, contractName, stdVerToml);
if (existingImplementation != address(0)) {
impl = IOptimismMintableERC20Factory(existingImplementation);
} else if (isDevelopRelease(release)) {
} else {
vm.broadcast(msg.sender);
impl = IOptimismMintableERC20Factory(
DeployUtils.create1({
......@@ -792,32 +650,12 @@ contract DeployImplementations is Script {
_args: DeployUtils.encodeConstructor(abi.encodeCall(IOptimismMintableERC20Factory.__constructor__, ()))
})
);
} else {
revert(string.concat("DeployImplementations: failed to deploy release ", release));
}
vm.label(address(impl), "OptimismMintableERC20FactoryImpl");
_dio.set(_dio.optimismMintableERC20FactoryImpl.selector, address(impl));
}
function deployOPContractsManagerImpl(
DeployImplementationsInput _dii,
DeployImplementationsOutput _dio
)
public
virtual
{
ISuperchainConfig superchainConfigProxy = _dii.superchainConfigProxy();
IProtocolVersions protocolVersionsProxy = _dii.protocolVersionsProxy();
vm.broadcast(msg.sender);
// TODO: Eventually we will want to select the correct implementation based on the release.
OPContractsManager impl = new OPContractsManager(superchainConfigProxy, protocolVersionsProxy);
vm.label(address(impl), "OPContractsManagerImpl");
_dio.set(_dio.opcmImpl.selector, address(impl));
}
// --- Fault Proofs Contracts ---
// The fault proofs contracts are configured as follows:
......@@ -862,7 +700,7 @@ contract DeployImplementations is Script {
public
virtual
{
string memory release = _dii.release();
string memory release = _dii.l1ContractsRelease();
string memory stdVerToml = _dii.standardVersionsToml();
string memory contractName = "optimism_portal";
IOptimismPortal2 impl;
......@@ -870,7 +708,7 @@ contract DeployImplementations is Script {
address existingImplementation = getReleaseAddress(release, contractName, stdVerToml);
if (existingImplementation != address(0)) {
impl = IOptimismPortal2(payable(existingImplementation));
} else if (isDevelopRelease(release)) {
} else {
uint256 proofMaturityDelaySeconds = _dii.proofMaturityDelaySeconds();
uint256 disputeGameFinalityDelaySeconds = _dii.disputeGameFinalityDelaySeconds();
vm.broadcast(msg.sender);
......@@ -884,8 +722,6 @@ contract DeployImplementations is Script {
)
})
);
} else {
revert(string.concat("DeployImplementations: failed to deploy release ", release));
}
vm.label(address(impl), "OptimismPortalImpl");
......@@ -893,7 +729,7 @@ contract DeployImplementations is Script {
}
function deployDelayedWETHImpl(DeployImplementationsInput _dii, DeployImplementationsOutput _dio) public virtual {
string memory release = _dii.release();
string memory release = _dii.l1ContractsRelease();
string memory stdVerToml = _dii.standardVersionsToml();
string memory contractName = "delayed_weth";
IDelayedWETH impl;
......@@ -901,7 +737,7 @@ contract DeployImplementations is Script {
address existingImplementation = getReleaseAddress(release, contractName, stdVerToml);
if (existingImplementation != address(0)) {
impl = IDelayedWETH(payable(existingImplementation));
} else if (isDevelopRelease(release)) {
} else {
uint256 withdrawalDelaySeconds = _dii.withdrawalDelaySeconds();
vm.broadcast(msg.sender);
impl = IDelayedWETH(
......@@ -912,8 +748,6 @@ contract DeployImplementations is Script {
)
})
);
} else {
revert(string.concat("DeployImplementations: failed to deploy release ", release));
}
vm.label(address(impl), "DelayedWETHImpl");
......@@ -927,7 +761,7 @@ contract DeployImplementations is Script {
public
virtual
{
string memory release = _dii.release();
string memory release = _dii.l1ContractsRelease();
string memory stdVerToml = _dii.standardVersionsToml();
string memory contractName = "preimage_oracle";
IPreimageOracle singleton;
......@@ -935,7 +769,7 @@ contract DeployImplementations is Script {
address existingImplementation = getReleaseAddress(release, contractName, stdVerToml);
if (existingImplementation != address(0)) {
singleton = IPreimageOracle(payable(existingImplementation));
} else if (isDevelopRelease(release)) {
} else {
uint256 minProposalSizeBytes = _dii.minProposalSizeBytes();
uint256 challengePeriodSeconds = _dii.challengePeriodSeconds();
vm.broadcast(msg.sender);
......@@ -947,8 +781,6 @@ contract DeployImplementations is Script {
)
})
);
} else {
revert(string.concat("DeployImplementations: failed to deploy release ", release));
}
vm.label(address(singleton), "PreimageOracleSingleton");
......@@ -956,7 +788,7 @@ contract DeployImplementations is Script {
}
function deployMipsSingleton(DeployImplementationsInput _dii, DeployImplementationsOutput _dio) public virtual {
string memory release = _dii.release();
string memory release = _dii.l1ContractsRelease();
string memory stdVerToml = _dii.standardVersionsToml();
string memory contractName = "mips";
IMIPS singleton;
......@@ -964,7 +796,7 @@ contract DeployImplementations is Script {
address existingImplementation = getReleaseAddress(release, contractName, stdVerToml);
if (existingImplementation != address(0)) {
singleton = IMIPS(payable(existingImplementation));
} else if (isDevelopRelease(release)) {
} else {
uint256 mipsVersion = _dii.mipsVersion();
IPreimageOracle preimageOracle = IPreimageOracle(address(_dio.preimageOracleSingleton()));
vm.broadcast(msg.sender);
......@@ -974,8 +806,6 @@ contract DeployImplementations is Script {
_args: DeployUtils.encodeConstructor(abi.encodeCall(IMIPS.__constructor__, (preimageOracle)))
})
);
} else {
revert(string.concat("DeployImplementations: failed to deploy release ", release));
}
vm.label(address(singleton), "MIPSSingleton");
......@@ -989,7 +819,7 @@ contract DeployImplementations is Script {
public
virtual
{
string memory release = _dii.release();
string memory release = _dii.l1ContractsRelease();
string memory stdVerToml = _dii.standardVersionsToml();
string memory contractName = "dispute_game_factory";
IDisputeGameFactory impl;
......@@ -997,7 +827,7 @@ contract DeployImplementations is Script {
address existingImplementation = getReleaseAddress(release, contractName, stdVerToml);
if (existingImplementation != address(0)) {
impl = IDisputeGameFactory(payable(existingImplementation));
} else if (isDevelopRelease(release)) {
} else {
vm.broadcast(msg.sender);
impl = IDisputeGameFactory(
DeployUtils.create1({
......@@ -1005,8 +835,6 @@ contract DeployImplementations is Script {
_args: DeployUtils.encodeConstructor(abi.encodeCall(IDisputeGameFactory.__constructor__, ()))
})
);
} else {
revert(string.concat("DeployImplementations: failed to deploy release ", release));
}
vm.label(address(impl), "DisputeGameFactoryImpl");
......@@ -1076,11 +904,6 @@ contract DeployImplementations is Script {
}
}
}
// A release is considered a 'develop' release if it does not start with 'op-contracts'.
function isDevelopRelease(string memory _release) internal pure returns (bool) {
return !LibString.startsWith(_release, "op-contracts");
}
}
// Similar to how DeploySuperchain.s.sol contains a lot of comments to thoroughly document the script
......@@ -1120,36 +943,35 @@ contract DeployImplementationsInterop is DeployImplementations {
DeployImplementationsInput _dii,
DeployImplementationsOutput _dio,
OPContractsManager.Blueprints memory _blueprints,
string memory _release,
OPContractsManager.ImplementationSetter[] memory _setters
string memory _l1ContractsRelease
)
internal
virtual
override
returns (OPContractsManager opcmProxy_)
returns (OPContractsManager opcm_)
{
address opcmProxyOwner = _dii.opcmProxyOwner();
ISuperchainConfig superchainConfigProxy = _dii.superchainConfigProxy();
IProtocolVersions protocolVersionsProxy = _dii.protocolVersionsProxy();
OPContractsManager.Implementations memory implementations = OPContractsManager.Implementations({
l1ERC721BridgeImpl: address(_dio.l1ERC721BridgeImpl()),
optimismPortalImpl: address(_dio.optimismPortalImpl()),
systemConfigImpl: address(_dio.systemConfigImpl()),
optimismMintableERC20FactoryImpl: address(_dio.optimismMintableERC20FactoryImpl()),
l1CrossDomainMessengerImpl: address(_dio.l1CrossDomainMessengerImpl()),
l1StandardBridgeImpl: address(_dio.l1StandardBridgeImpl()),
disputeGameFactoryImpl: address(_dio.disputeGameFactoryImpl()),
delayedWETHImpl: address(_dio.delayedWETHImpl()),
mipsImpl: address(_dio.mipsSingleton())
});
vm.broadcast(msg.sender);
IProxy proxy = IProxy(
DeployUtils.create1({
_name: "Proxy",
_args: DeployUtils.encodeConstructor(abi.encodeCall(IProxy.__constructor__, (msg.sender)))
})
opcm_ = new OPContractsManagerInterop(
superchainConfigProxy, protocolVersionsProxy, _l1ContractsRelease, _blueprints, implementations
);
deployOPContractsManagerImpl(_dii, _dio); // overriding function
OPContractsManager opcmImpl = _dio.opcmImpl();
OPContractsManager.InitializerInputs memory initializerInputs =
OPContractsManager.InitializerInputs(_blueprints, _setters, _release, true);
vm.startBroadcast(msg.sender);
proxy.upgradeToAndCall(address(opcmImpl), abi.encodeCall(opcmImpl.initialize, (initializerInputs)));
proxy.changeAdmin(opcmProxyOwner); // transfer ownership of Proxy contract to the ProxyAdmin contract
vm.stopBroadcast();
opcmProxy_ = OPContractsManagerInterop(address(proxy));
vm.label(address(opcm_), "OPContractsManager");
_dio.set(_dio.opcm.selector, address(opcm_));
}
function deployOptimismPortalImpl(
......@@ -1159,7 +981,7 @@ contract DeployImplementationsInterop is DeployImplementations {
public
override
{
string memory release = _dii.release();
string memory release = _dii.l1ContractsRelease();
string memory stdVerToml = _dii.standardVersionsToml();
string memory contractName = "optimism_portal";
IOptimismPortalInterop impl;
......@@ -1167,7 +989,7 @@ contract DeployImplementationsInterop is DeployImplementations {
address existingImplementation = getReleaseAddress(release, contractName, stdVerToml);
if (existingImplementation != address(0)) {
impl = IOptimismPortalInterop(payable(existingImplementation));
} else if (isDevelopRelease(release)) {
} else {
uint256 proofMaturityDelaySeconds = _dii.proofMaturityDelaySeconds();
uint256 disputeGameFinalityDelaySeconds = _dii.disputeGameFinalityDelaySeconds();
vm.broadcast(msg.sender);
......@@ -1182,8 +1004,6 @@ contract DeployImplementationsInterop is DeployImplementations {
)
})
);
} else {
revert(string.concat("DeployImplementations: failed to deploy release ", release));
}
vm.label(address(impl), "OptimismPortalImpl");
......@@ -1197,7 +1017,7 @@ contract DeployImplementationsInterop is DeployImplementations {
public
override
{
string memory release = _dii.release();
string memory release = _dii.l1ContractsRelease();
string memory stdVerToml = _dii.standardVersionsToml();
string memory contractName = "system_config";
......@@ -1206,7 +1026,7 @@ contract DeployImplementationsInterop is DeployImplementations {
address existingImplementation = getReleaseAddress(release, contractName, stdVerToml);
if (existingImplementation != address(0)) {
impl = ISystemConfigInterop(existingImplementation);
} else if (isDevelopRelease(release)) {
} else {
vm.broadcast(msg.sender);
impl = ISystemConfigInterop(
DeployUtils.create1({
......@@ -1214,46 +1034,9 @@ contract DeployImplementationsInterop is DeployImplementations {
_args: DeployUtils.encodeConstructor(abi.encodeCall(ISystemConfigInterop.__constructor__, ()))
})
);
} else {
revert(string.concat("DeployImplementations: failed to deploy release ", release));
}
vm.label(address(impl), "SystemConfigImpl");
_dio.set(_dio.systemConfigImpl.selector, address(impl));
}
function deployOPContractsManagerImpl(
DeployImplementationsInput _dii,
DeployImplementationsOutput _dio
)
public
override
{
ISuperchainConfig superchainConfigProxy = _dii.superchainConfigProxy();
IProtocolVersions protocolVersionsProxy = _dii.protocolVersionsProxy();
vm.broadcast(msg.sender);
// TODO: Eventually we will want to select the correct implementation based on the release.
OPContractsManager impl = new OPContractsManagerInterop(superchainConfigProxy, protocolVersionsProxy);
vm.label(address(impl), "OPContractsManagerImpl");
_dio.set(_dio.opcmImpl.selector, address(impl));
}
function opcmSystemConfigSetter(
DeployImplementationsInput,
DeployImplementationsOutput _dio
)
internal
view
override
returns (OPContractsManager.ImplementationSetter memory)
{
return OPContractsManager.ImplementationSetter({
name: "SystemConfig",
info: OPContractsManager.Implementation(
address(_dio.systemConfigImpl()), ISystemConfigInterop.initialize.selector
)
});
}
}
......@@ -47,7 +47,7 @@ contract DeployOPChainInput is BaseDeployIO {
uint32 internal _basefeeScalar;
uint32 internal _blobBaseFeeScalar;
uint256 internal _l2ChainId;
OPContractsManager internal _opcmProxy;
OPContractsManager internal _opcm;
string internal _saltMixer;
uint64 internal _gasLimit;
......@@ -68,7 +68,7 @@ contract DeployOPChainInput is BaseDeployIO {
else if (_sel == this.unsafeBlockSigner.selector) _unsafeBlockSigner = _addr;
else if (_sel == this.proposer.selector) _proposer = _addr;
else if (_sel == this.challenger.selector) _challenger = _addr;
else if (_sel == this.opcmProxy.selector) _opcmProxy = OPContractsManager(_addr);
else if (_sel == this.opcm.selector) _opcm = OPContractsManager(_addr);
else revert("DeployOPChainInput: unknown selector");
}
......@@ -174,11 +174,10 @@ contract DeployOPChainInput is BaseDeployIO {
return abi.encode(ScriptConstants.DEFAULT_STARTING_ANCHOR_ROOTS());
}
function opcmProxy() public returns (OPContractsManager) {
require(address(_opcmProxy) != address(0), "DeployOPChainInput: not set");
DeployUtils.assertValidContractAddress(address(_opcmProxy));
DeployUtils.assertERC1967ImplementationSet(address(_opcmProxy));
return _opcmProxy;
function opcm() public view returns (OPContractsManager) {
require(address(_opcm) != address(0), "DeployOPChainInput: not set");
DeployUtils.assertValidContractAddress(address(_opcm));
return _opcm;
}
function saltMixer() public view returns (string memory) {
......@@ -347,7 +346,7 @@ contract DeployOPChain is Script {
// -------- Core Deployment Methods --------
function run(DeployOPChainInput _doi, DeployOPChainOutput _doo) public {
OPContractsManager opcmProxy = _doi.opcmProxy();
OPContractsManager opcm = _doi.opcm();
OPContractsManager.Roles memory roles = OPContractsManager.Roles({
opChainProxyAdminOwner: _doi.opChainProxyAdminOwner(),
......@@ -374,7 +373,7 @@ contract DeployOPChain is Script {
});
vm.broadcast(msg.sender);
OPContractsManager.DeployOutput memory deployOutput = opcmProxy.deploy(deployInput);
OPContractsManager.DeployOutput memory deployOutput = opcm.deploy(deployInput);
vm.label(address(deployOutput.opChainProxyAdmin), "opChainProxyAdmin");
vm.label(address(deployOutput.addressManager), "addressManager");
......@@ -480,9 +479,9 @@ contract DeployOPChain is Script {
"DPG-20"
);
OPContractsManager opcm = _doi.opcmProxy();
(address mips,) = opcm.implementations(opcm.latestRelease(), "MIPS");
require(game.vm() == IBigStepper(mips), "DPG-30");
OPContractsManager opcm = _doi.opcm();
address mipsImpl = opcm.implementations().mipsImpl;
require(game.vm() == IBigStepper(mipsImpl), "DPG-30");
require(address(game.weth()) == address(_doo.delayedWETHPermissionedGameProxy()), "DPG-40");
require(address(game.anchorStateRegistry()) == address(_doo.anchorStateRegistryProxy()), "DPG-50");
......@@ -552,9 +551,7 @@ contract DeployOPChain is Script {
require(outputConfig.maximumBaseFee == rConfig.maximumBaseFee, "SYSCON-130");
require(systemConfig.startBlock() == block.number, "SYSCON-140");
require(
systemConfig.batchInbox() == _doi.opcmProxy().chainIdToBatchInboxAddress(_doi.l2ChainId()), "SYSCON-150"
);
require(systemConfig.batchInbox() == _doi.opcm().chainIdToBatchInboxAddress(_doi.l2ChainId()), "SYSCON-150");
require(systemConfig.l1CrossDomainMessenger() == address(_doo.l1CrossDomainMessengerProxy()), "SYSCON-160");
require(systemConfig.l1ERC721Bridge() == address(_doo.l1ERC721BridgeProxy()), "SYSCON-170");
......@@ -579,7 +576,7 @@ contract DeployOPChain is Script {
require(address(messenger.PORTAL()) == address(_doo.optimismPortalProxy()), "L1xDM-30");
require(address(messenger.portal()) == address(_doo.optimismPortalProxy()), "L1xDM-40");
require(address(messenger.superchainConfig()) == address(_doi.opcmProxy().superchainConfig()), "L1xDM-50");
require(address(messenger.superchainConfig()) == address(_doi.opcm().superchainConfig()), "L1xDM-50");
bytes32 xdmSenderSlot = vm.load(address(messenger), bytes32(uint256(204)));
require(address(uint160(uint256(xdmSenderSlot))) == Constants.DEFAULT_L2_SENDER, "L1xDM-60");
......@@ -595,7 +592,7 @@ contract DeployOPChain is Script {
require(address(bridge.messenger()) == address(messenger), "L1SB-20");
require(address(bridge.OTHER_BRIDGE()) == Predeploys.L2_STANDARD_BRIDGE, "L1SB-30");
require(address(bridge.otherBridge()) == Predeploys.L2_STANDARD_BRIDGE, "L1SB-40");
require(address(bridge.superchainConfig()) == address(_doi.opcmProxy().superchainConfig()), "L1SB-50");
require(address(bridge.superchainConfig()) == address(_doi.opcm().superchainConfig()), "L1SB-50");
}
function assertValidOptimismMintableERC20Factory(DeployOPChainInput, DeployOPChainOutput _doo) internal {
......@@ -617,12 +614,12 @@ contract DeployOPChain is Script {
require(address(bridge.MESSENGER()) == address(_doo.l1CrossDomainMessengerProxy()), "L721B-30");
require(address(bridge.messenger()) == address(_doo.l1CrossDomainMessengerProxy()), "L721B-40");
require(address(bridge.superchainConfig()) == address(_doi.opcmProxy().superchainConfig()), "L721B-50");
require(address(bridge.superchainConfig()) == address(_doi.opcm().superchainConfig()), "L721B-50");
}
function assertValidOptimismPortal(DeployOPChainInput _doi, DeployOPChainOutput _doo) internal {
IOptimismPortal2 portal = _doo.optimismPortalProxy();
ISuperchainConfig superchainConfig = ISuperchainConfig(address(_doi.opcmProxy().superchainConfig()));
ISuperchainConfig superchainConfig = ISuperchainConfig(address(_doi.opcm().superchainConfig()));
require(address(portal.disputeGameFactory()) == address(_doo.disputeGameFactoryProxy()), "PORTAL-10");
require(address(portal.systemConfig()) == address(_doo.systemConfigProxy()), "PORTAL-20");
......
......@@ -12,29 +12,18 @@ import { IAddressManager } from "src/legacy/interfaces/IAddressManager.sol";
import { IStaticL1ChugSplashProxy } from "src/legacy/interfaces/IL1ChugSplashProxy.sol";
contract ReadImplementationAddressesInput is DeployOPChainOutput {
OPContractsManager internal _opcmProxy;
string internal _release;
OPContractsManager internal _opcm;
function set(bytes4 _sel, address _addr) public override {
require(_addr != address(0), "ReadImplementationAddressesInput: cannot set zero address");
if (_sel == this.opcmProxy.selector) _opcmProxy = OPContractsManager(_addr);
if (_sel == this.opcm.selector) _opcm = OPContractsManager(_addr);
else if (_sel == this.addressManager.selector) _addressManager = IAddressManager(_addr);
else super.set(_sel, _addr);
}
function set(bytes4 _sel, string memory _val) public {
if (_sel == this.release.selector) _release = _val;
else revert("ReadImplementationAddressesInput: unknown selector");
}
function opcmProxy() public view returns (OPContractsManager) {
DeployUtils.assertValidContractAddress(address(_opcmProxy));
return _opcmProxy;
}
function release() public view returns (string memory) {
require(bytes(_release).length != 0, "ReadImplementationAddressesInput: release not set");
return _release;
function opcm() public view returns (OPContractsManager) {
DeployUtils.assertValidContractAddress(address(_opcm));
return _opcm;
}
}
......@@ -154,9 +143,12 @@ contract ReadImplementationAddresses is Script {
vm.prank(address(0));
_rio.set(_rio.l1StandardBridge.selector, l1SBImpl);
(address mipsLogic,) = _rii.opcmProxy().implementations(_rii.release(), "MIPS");
address mipsLogic = _rii.opcm().implementations().mipsImpl;
_rio.set(_rio.mipsSingleton.selector, mipsLogic);
address delayedWETH = _rii.opcm().implementations().delayedWETHImpl;
_rio.set(_rio.delayedWETH.selector, delayedWETH);
IAddressManager am = _rii.addressManager();
_rio.set(_rio.l1CrossDomainMessenger.selector, am.getAddress("OVM_L1CrossDomainMessenger"));
......
......@@ -10,6 +10,110 @@
"internalType": "contract IProtocolVersions",
"name": "_protocolVersions",
"type": "address"
},
{
"internalType": "string",
"name": "_l1ContractsRelease",
"type": "string"
},
{
"components": [
{
"internalType": "address",
"name": "addressManager",
"type": "address"
},
{
"internalType": "address",
"name": "proxy",
"type": "address"
},
{
"internalType": "address",
"name": "proxyAdmin",
"type": "address"
},
{
"internalType": "address",
"name": "l1ChugSplashProxy",
"type": "address"
},
{
"internalType": "address",
"name": "resolvedDelegateProxy",
"type": "address"
},
{
"internalType": "address",
"name": "anchorStateRegistry",
"type": "address"
},
{
"internalType": "address",
"name": "permissionedDisputeGame1",
"type": "address"
},
{
"internalType": "address",
"name": "permissionedDisputeGame2",
"type": "address"
}
],
"internalType": "struct OPContractsManager.Blueprints",
"name": "_blueprints",
"type": "tuple"
},
{
"components": [
{
"internalType": "address",
"name": "l1ERC721BridgeImpl",
"type": "address"
},
{
"internalType": "address",
"name": "optimismPortalImpl",
"type": "address"
},
{
"internalType": "address",
"name": "systemConfigImpl",
"type": "address"
},
{
"internalType": "address",
"name": "optimismMintableERC20FactoryImpl",
"type": "address"
},
{
"internalType": "address",
"name": "l1CrossDomainMessengerImpl",
"type": "address"
},
{
"internalType": "address",
"name": "l1StandardBridgeImpl",
"type": "address"
},
{
"internalType": "address",
"name": "disputeGameFactoryImpl",
"type": "address"
},
{
"internalType": "address",
"name": "delayedWETHImpl",
"type": "address"
},
{
"internalType": "address",
"name": "mipsImpl",
"type": "address"
}
],
"internalType": "struct OPContractsManager.Implementations",
"name": "_implementations",
"type": "tuple"
}
],
"stateMutability": "nonpayable",
......@@ -298,138 +402,68 @@
"type": "function"
},
{
"inputs": [
{
"internalType": "string",
"name": "",
"type": "string"
},
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"inputs": [],
"name": "implementations",
"outputs": [
{
"internalType": "address",
"name": "logic",
"type": "address"
},
{
"internalType": "bytes4",
"name": "initializer",
"type": "bytes4"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"components": [
{
"components": [
{
"internalType": "address",
"name": "addressManager",
"type": "address"
},
{
"internalType": "address",
"name": "proxy",
"type": "address"
},
{
"internalType": "address",
"name": "proxyAdmin",
"type": "address"
},
{
"internalType": "address",
"name": "l1ChugSplashProxy",
"type": "address"
},
{
"internalType": "address",
"name": "resolvedDelegateProxy",
"type": "address"
},
{
"internalType": "address",
"name": "anchorStateRegistry",
"type": "address"
},
{
"internalType": "address",
"name": "permissionedDisputeGame1",
"type": "address"
},
{
"internalType": "address",
"name": "permissionedDisputeGame2",
"type": "address"
}
],
"internalType": "struct OPContractsManager.Blueprints",
"name": "blueprints",
"type": "tuple"
"internalType": "address",
"name": "l1ERC721BridgeImpl",
"type": "address"
},
{
"components": [
{
"internalType": "string",
"name": "name",
"type": "string"
},
{
"components": [
{
"internalType": "address",
"name": "logic",
"type": "address"
},
{
"internalType": "bytes4",
"name": "initializer",
"type": "bytes4"
}
],
"internalType": "struct OPContractsManager.Implementation",
"name": "info",
"type": "tuple"
}
],
"internalType": "struct OPContractsManager.ImplementationSetter[]",
"name": "setters",
"type": "tuple[]"
"internalType": "address",
"name": "optimismPortalImpl",
"type": "address"
},
{
"internalType": "string",
"name": "release",
"type": "string"
"internalType": "address",
"name": "systemConfigImpl",
"type": "address"
},
{
"internalType": "address",
"name": "optimismMintableERC20FactoryImpl",
"type": "address"
},
{
"internalType": "address",
"name": "l1CrossDomainMessengerImpl",
"type": "address"
},
{
"internalType": "address",
"name": "l1StandardBridgeImpl",
"type": "address"
},
{
"internalType": "bool",
"name": "isLatest",
"type": "bool"
"internalType": "address",
"name": "disputeGameFactoryImpl",
"type": "address"
},
{
"internalType": "address",
"name": "delayedWETHImpl",
"type": "address"
},
{
"internalType": "address",
"name": "mipsImpl",
"type": "address"
}
],
"internalType": "struct OPContractsManager.InitializerInputs",
"name": "_initializerInputs",
"internalType": "struct OPContractsManager.Implementations",
"name": "",
"type": "tuple"
}
],
"name": "initialize",
"outputs": [],
"stateMutability": "nonpayable",
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "latestRelease",
"name": "l1ContractsRelease",
"outputs": [
{
"internalType": "string",
......@@ -529,19 +563,6 @@
"name": "Deployed",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "uint8",
"name": "version",
"type": "uint8"
}
],
"name": "Initialized",
"type": "event"
},
{
"inputs": [
{
......
......@@ -10,6 +10,110 @@
"internalType": "contract IProtocolVersions",
"name": "_protocolVersions",
"type": "address"
},
{
"internalType": "string",
"name": "_l1ContractsRelease",
"type": "string"
},
{
"components": [
{
"internalType": "address",
"name": "addressManager",
"type": "address"
},
{
"internalType": "address",
"name": "proxy",
"type": "address"
},
{
"internalType": "address",
"name": "proxyAdmin",
"type": "address"
},
{
"internalType": "address",
"name": "l1ChugSplashProxy",
"type": "address"
},
{
"internalType": "address",
"name": "resolvedDelegateProxy",
"type": "address"
},
{
"internalType": "address",
"name": "anchorStateRegistry",
"type": "address"
},
{
"internalType": "address",
"name": "permissionedDisputeGame1",
"type": "address"
},
{
"internalType": "address",
"name": "permissionedDisputeGame2",
"type": "address"
}
],
"internalType": "struct OPContractsManager.Blueprints",
"name": "_blueprints",
"type": "tuple"
},
{
"components": [
{
"internalType": "address",
"name": "l1ERC721BridgeImpl",
"type": "address"
},
{
"internalType": "address",
"name": "optimismPortalImpl",
"type": "address"
},
{
"internalType": "address",
"name": "systemConfigImpl",
"type": "address"
},
{
"internalType": "address",
"name": "optimismMintableERC20FactoryImpl",
"type": "address"
},
{
"internalType": "address",
"name": "l1CrossDomainMessengerImpl",
"type": "address"
},
{
"internalType": "address",
"name": "l1StandardBridgeImpl",
"type": "address"
},
{
"internalType": "address",
"name": "disputeGameFactoryImpl",
"type": "address"
},
{
"internalType": "address",
"name": "delayedWETHImpl",
"type": "address"
},
{
"internalType": "address",
"name": "mipsImpl",
"type": "address"
}
],
"internalType": "struct OPContractsManager.Implementations",
"name": "_implementations",
"type": "tuple"
}
],
"stateMutability": "nonpayable",
......@@ -298,138 +402,68 @@
"type": "function"
},
{
"inputs": [
{
"internalType": "string",
"name": "",
"type": "string"
},
{
"internalType": "string",
"name": "",
"type": "string"
}
],
"inputs": [],
"name": "implementations",
"outputs": [
{
"internalType": "address",
"name": "logic",
"type": "address"
},
{
"internalType": "bytes4",
"name": "initializer",
"type": "bytes4"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"components": [
{
"components": [
{
"internalType": "address",
"name": "addressManager",
"type": "address"
},
{
"internalType": "address",
"name": "proxy",
"type": "address"
},
{
"internalType": "address",
"name": "proxyAdmin",
"type": "address"
},
{
"internalType": "address",
"name": "l1ChugSplashProxy",
"type": "address"
},
{
"internalType": "address",
"name": "resolvedDelegateProxy",
"type": "address"
},
{
"internalType": "address",
"name": "anchorStateRegistry",
"type": "address"
},
{
"internalType": "address",
"name": "permissionedDisputeGame1",
"type": "address"
},
{
"internalType": "address",
"name": "permissionedDisputeGame2",
"type": "address"
}
],
"internalType": "struct OPContractsManager.Blueprints",
"name": "blueprints",
"type": "tuple"
"internalType": "address",
"name": "l1ERC721BridgeImpl",
"type": "address"
},
{
"components": [
{
"internalType": "string",
"name": "name",
"type": "string"
},
{
"components": [
{
"internalType": "address",
"name": "logic",
"type": "address"
},
{
"internalType": "bytes4",
"name": "initializer",
"type": "bytes4"
}
],
"internalType": "struct OPContractsManager.Implementation",
"name": "info",
"type": "tuple"
}
],
"internalType": "struct OPContractsManager.ImplementationSetter[]",
"name": "setters",
"type": "tuple[]"
"internalType": "address",
"name": "optimismPortalImpl",
"type": "address"
},
{
"internalType": "string",
"name": "release",
"type": "string"
"internalType": "address",
"name": "systemConfigImpl",
"type": "address"
},
{
"internalType": "address",
"name": "optimismMintableERC20FactoryImpl",
"type": "address"
},
{
"internalType": "address",
"name": "l1CrossDomainMessengerImpl",
"type": "address"
},
{
"internalType": "address",
"name": "l1StandardBridgeImpl",
"type": "address"
},
{
"internalType": "bool",
"name": "isLatest",
"type": "bool"
"internalType": "address",
"name": "disputeGameFactoryImpl",
"type": "address"
},
{
"internalType": "address",
"name": "delayedWETHImpl",
"type": "address"
},
{
"internalType": "address",
"name": "mipsImpl",
"type": "address"
}
],
"internalType": "struct OPContractsManager.InitializerInputs",
"name": "_initializerInputs",
"internalType": "struct OPContractsManager.Implementations",
"name": "",
"type": "tuple"
}
],
"name": "initialize",
"outputs": [],
"stateMutability": "nonpayable",
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "latestRelease",
"name": "l1ContractsRelease",
"outputs": [
{
"internalType": "string",
......@@ -529,19 +563,6 @@
"name": "Deployed",
"type": "event"
},
{
"anonymous": false,
"inputs": [
{
"indexed": false,
"internalType": "uint8",
"name": "version",
"type": "uint8"
}
],
"name": "Initialized",
"type": "event"
},
{
"inputs": [
{
......
......@@ -20,8 +20,8 @@
"sourceCodeHash": "0x4132ff37d267cb12224b75ea806c0aa7d25407b0d66ce526d7fcda8f7d223882"
},
"src/L1/OPContractsManager.sol": {
"initCodeHash": "0xd58cb3978affc5c1457cdd498ff8420c90aef804d4c3b62cf42ab2691986d6d2",
"sourceCodeHash": "0x7bfa6eff76176649fe600303cd60009a0f6e282cbaec55836b5ea1f8875cbeb5"
"initCodeHash": "0xd038cc35325d023499151264232d75fa4ecc81f04a8c8353e6b50c43af224d6e",
"sourceCodeHash": "0xa13f3ab2b8744015290dbabe5f20fdd44774607e6a7ad3e5e016303fc4aa8c12"
},
"src/L1/OptimismPortal.sol": {
"initCodeHash": "0x152167cfa18635ae4918a6eb3371a599cfa084418c0a652799cdb48bfc0ee0cc",
......
[
{
"bytes": "1",
"label": "_initialized",
"offset": 0,
"slot": "0",
"type": "uint8"
},
{
"bytes": "1",
"label": "_initializing",
"offset": 1,
"slot": "0",
"type": "bool"
},
{
"bytes": "32",
"label": "latestRelease",
"label": "l1ContractsRelease",
"offset": 0,
"slot": "1",
"slot": "0",
"type": "string"
},
{
"bytes": "32",
"label": "implementations",
"offset": 0,
"slot": "2",
"type": "mapping(string => mapping(string => struct OPContractsManager.Implementation))"
},
{
"bytes": "32",
"label": "systemConfigs",
"offset": 0,
"slot": "3",
"slot": "1",
"type": "mapping(uint256 => contract ISystemConfig)"
},
{
"bytes": "256",
"label": "blueprint",
"offset": 0,
"slot": "4",
"slot": "2",
"type": "struct OPContractsManager.Blueprints"
},
{
"bytes": "1600",
"label": "__gap",
"bytes": "288",
"label": "implementation",
"offset": 0,
"slot": "12",
"type": "uint256[50]"
"slot": "10",
"type": "struct OPContractsManager.Implementations"
}
]
\ No newline at end of file
[
{
"bytes": "1",
"label": "_initialized",
"offset": 0,
"slot": "0",
"type": "uint8"
},
{
"bytes": "1",
"label": "_initializing",
"offset": 1,
"slot": "0",
"type": "bool"
},
{
"bytes": "32",
"label": "latestRelease",
"label": "l1ContractsRelease",
"offset": 0,
"slot": "1",
"slot": "0",
"type": "string"
},
{
"bytes": "32",
"label": "implementations",
"offset": 0,
"slot": "2",
"type": "mapping(string => mapping(string => struct OPContractsManager.Implementation))"
},
{
"bytes": "32",
"label": "systemConfigs",
"offset": 0,
"slot": "3",
"slot": "1",
"type": "mapping(uint256 => contract ISystemConfig)"
},
{
"bytes": "256",
"label": "blueprint",
"offset": 0,
"slot": "4",
"slot": "2",
"type": "struct OPContractsManager.Blueprints"
},
{
"bytes": "1600",
"label": "__gap",
"bytes": "288",
"label": "implementation",
"offset": 0,
"slot": "12",
"type": "uint256[50]"
"slot": "10",
"type": "struct OPContractsManager.Implementations"
}
]
\ No newline at end of file
......@@ -4,15 +4,12 @@ pragma solidity 0.8.15;
import { Blueprint } from "src/libraries/Blueprint.sol";
import { Constants } from "src/libraries/Constants.sol";
import { Initializable } from "@openzeppelin/contracts/proxy/utils/Initializable.sol";
import { ISemver } from "src/universal/interfaces/ISemver.sol";
import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol";
import { IBigStepper } from "src/dispute/interfaces/IBigStepper.sol";
import { IDelayedWETH } from "src/dispute/interfaces/IDelayedWETH.sol";
import { IAnchorStateRegistry } from "src/dispute/interfaces/IAnchorStateRegistry.sol";
import { IDisputeGame } from "src/dispute/interfaces/IDisputeGame.sol";
import { ISystemConfigV160 } from "src/L1/interfaces/ISystemConfigV160.sol";
import { IAddressManager } from "src/legacy/interfaces/IAddressManager.sol";
import { IProxyAdmin } from "src/universal/interfaces/IProxyAdmin.sol";
......@@ -28,14 +25,12 @@ import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol";
import { IProtocolVersions } from "src/L1/interfaces/IProtocolVersions.sol";
import { IOptimismPortal2 } from "src/L1/interfaces/IOptimismPortal2.sol";
import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol";
import { ISystemConfigV160 } from "src/L1/interfaces/ISystemConfigV160.sol";
import { IL1CrossDomainMessenger } from "src/L1/interfaces/IL1CrossDomainMessenger.sol";
import { IL1ERC721Bridge } from "src/L1/interfaces/IL1ERC721Bridge.sol";
import { IL1StandardBridge } from "src/L1/interfaces/IL1StandardBridge.sol";
import { IOptimismMintableERC20Factory } from "src/universal/interfaces/IOptimismMintableERC20Factory.sol";
/// @custom:proxied true
contract OPContractsManager is ISemver, Initializable {
contract OPContractsManager is ISemver {
// -------- Structs --------
/// @notice Represents the roles that can be set when deploying a standard OP Stack chain.
......@@ -89,19 +84,6 @@ contract OPContractsManager is ISemver, Initializable {
IDelayedWETH delayedWETHPermissionlessGameProxy;
}
/// @notice The logic address and initializer selector for an implementation contract.
struct Implementation {
address logic; // Address containing the deployed logic contract.
bytes4 initializer; // Function selector for the initializer.
}
/// @notice Used to set the implementation for a contract by mapping a contract
/// name to the implementation data.
struct ImplementationSetter {
string name; // Contract name.
Implementation info; // Implementation to set.
}
/// @notice Addresses of ERC-5202 Blueprint contracts. There are used for deploying full size
/// contracts, to reduce the code size of this factory contract. If it deployed full contracts
/// using the `new Proxy()` syntax, the code size would get large fast, since this contract would
......@@ -118,19 +100,23 @@ contract OPContractsManager is ISemver, Initializable {
address permissionedDisputeGame2;
}
/// @notice Inputs required when initializing the OPContractsManager. To avoid 'StackTooDeep' errors,
/// all necessary inputs (excluding immutables) for initialization are bundled together in this struct.
struct InitializerInputs {
Blueprints blueprints;
ImplementationSetter[] setters;
string release;
bool isLatest;
/// @notice The latest implementation contracts for the OP Stack.
struct Implementations {
address l1ERC721BridgeImpl;
address optimismPortalImpl;
address systemConfigImpl;
address optimismMintableERC20FactoryImpl;
address l1CrossDomainMessengerImpl;
address l1StandardBridgeImpl;
address disputeGameFactoryImpl;
address delayedWETHImpl;
address mipsImpl;
}
// -------- Constants and Variables --------
/// @custom:semver 1.0.0-beta.20
string public constant version = "1.0.0-beta.20";
/// @custom:semver 1.0.0-beta.21
string public constant version = "1.0.0-beta.21";
/// @notice Represents the interface version so consumers know how to decode the DeployOutput struct
/// that's emitted in the `Deployed` event. Whenever that struct changes, a new version should be used.
......@@ -142,24 +128,20 @@ contract OPContractsManager is ISemver, Initializable {
/// @notice Address of the ProtocolVersions contract shared by all chains.
IProtocolVersions public immutable protocolVersions;
/// @notice The latest release of the OP Contracts Manager, as a string of the format `op-contracts/vX.Y.Z`.
string public latestRelease;
/// @notice Maps a release version to a contract name to it's implementation data.
mapping(string => mapping(string => Implementation)) public implementations;
// @notice L1 smart contracts release deployed by this version of OPCM. This is used in opcm to signal which version
// of the L1 smart contracts is deployed. It takes the format of `op-contracts/vX.Y.Z`.
string public l1ContractsRelease;
/// @notice Maps an L2 Chain ID to the SystemConfig for that chain.
mapping(uint256 => ISystemConfig) public systemConfigs;
/// @notice Addresses of the Blueprint contracts.
/// This is internal because if public the autogenerated getter method would return a tuple of
/// addresses, but we want it to return a struct. This is also set via `initialize` because
/// we can't make this an immutable variable as it is a non-value type.
/// addresses, but we want it to return a struct.
Blueprints internal blueprint;
/// @notice Storage gap for future modifications, so we can expand the number of blueprints
/// without affecting other storage variables.
uint256[50] private __gap;
/// @notice Addresses of the latest implementation contracts.
Implementations internal implementation;
// -------- Events --------
......@@ -197,37 +179,26 @@ contract OPContractsManager is ISemver, Initializable {
// -------- Methods --------
/// @notice OPCM is proxied. Therefore the `initialize` function replaces most constructor logic for this contract.
constructor(ISuperchainConfig _superchainConfig, IProtocolVersions _protocolVersions) {
constructor(
ISuperchainConfig _superchainConfig,
IProtocolVersions _protocolVersions,
string memory _l1ContractsRelease,
Blueprints memory _blueprints,
Implementations memory _implementations
) {
assertValidContractAddress(address(_superchainConfig));
assertValidContractAddress(address(_protocolVersions));
superchainConfig = _superchainConfig;
protocolVersions = _protocolVersions;
_disableInitializers();
}
function initialize(InitializerInputs memory _initializerInputs) public initializer {
if (_initializerInputs.isLatest) latestRelease = _initializerInputs.release;
if (keccak256(bytes(latestRelease)) == keccak256("")) revert LatestReleaseNotSet();
l1ContractsRelease = _l1ContractsRelease;
for (uint256 i = 0; i < _initializerInputs.setters.length; i++) {
ImplementationSetter memory setter = _initializerInputs.setters[i];
Implementation storage impl = implementations[_initializerInputs.release][setter.name];
if (impl.logic != address(0)) revert AlreadyReleased();
impl.initializer = setter.info.initializer;
impl.logic = setter.info.logic;
}
blueprint = _initializerInputs.blueprints;
blueprint = _blueprints;
implementation = _implementations;
}
function deploy(DeployInput calldata _input) external returns (DeployOutput memory) {
assertValidInputs(_input);
uint256 l2ChainId = _input.l2ChainId;
// The salt for a non-proxy contract is a function of the chain ID and the salt mixer.
string memory saltMixer = _input.saltMixer;
bytes32 salt = keccak256(abi.encode(l2ChainId, saltMixer));
......@@ -266,7 +237,6 @@ contract OPContractsManager is ISemver, Initializable {
payable(Blueprint.deployFrom(blueprint.l1ChugSplashProxy, salt, abi.encode(output.opChainProxyAdmin)))
);
output.opChainProxyAdmin.setProxyType(address(output.l1StandardBridgeProxy), IProxyAdmin.ProxyType.CHUGSPLASH);
string memory contractName = "OVM_L1CrossDomainMessenger";
output.l1CrossDomainMessengerProxy = IL1CrossDomainMessenger(
Blueprint.deployFrom(blueprint.resolvedDelegateProxy, salt, abi.encode(output.addressManager, contractName))
......@@ -275,10 +245,8 @@ contract OPContractsManager is ISemver, Initializable {
address(output.l1CrossDomainMessengerProxy), IProxyAdmin.ProxyType.RESOLVED
);
output.opChainProxyAdmin.setImplementationName(address(output.l1CrossDomainMessengerProxy), contractName);
// Now that all proxies are deployed, we can transfer ownership of the AddressManager to the ProxyAdmin.
output.addressManager.transferOwnership(address(output.opChainProxyAdmin));
// The AnchorStateRegistry Implementation is not MCP Ready, and therefore requires an implementation per chain.
// It must be deployed after the DisputeGameFactoryProxy so that it can be provided as a constructor argument.
output.anchorStateRegistryImpl = IAnchorStateRegistry(
......@@ -301,54 +269,76 @@ contract OPContractsManager is ISemver, Initializable {
);
// -------- Set and Initialize Proxy Implementations --------
Implementation memory impl;
bytes memory data;
impl = getLatestImplementation("L1ERC721Bridge");
data = encodeL1ERC721BridgeInitializer(impl.initializer, output);
upgradeAndCall(output.opChainProxyAdmin, address(output.l1ERC721BridgeProxy), impl.logic, data);
data = encodeL1ERC721BridgeInitializer(IL1ERC721Bridge.initialize.selector, output);
upgradeAndCall(
output.opChainProxyAdmin, address(output.l1ERC721BridgeProxy), implementation.l1ERC721BridgeImpl, data
);
impl = getLatestImplementation("OptimismPortal");
data = encodeOptimismPortalInitializer(impl.initializer, output);
upgradeAndCall(output.opChainProxyAdmin, address(output.optimismPortalProxy), impl.logic, data);
data = encodeOptimismPortalInitializer(IOptimismPortal2.initialize.selector, output);
upgradeAndCall(
output.opChainProxyAdmin, address(output.optimismPortalProxy), implementation.optimismPortalImpl, data
);
// First we upgrade the implementation so it's version can be retrieved, then we initialize
// it afterwards. See the comments in encodeSystemConfigInitializer to learn more.
impl = getLatestImplementation("SystemConfig");
output.opChainProxyAdmin.upgrade(payable(address(output.systemConfigProxy)), impl.logic);
data = encodeSystemConfigInitializer(impl.initializer, _input, output);
upgradeAndCall(output.opChainProxyAdmin, address(output.systemConfigProxy), impl.logic, data);
output.opChainProxyAdmin.upgrade(payable(address(output.systemConfigProxy)), implementation.systemConfigImpl);
data = encodeSystemConfigInitializer(_input, output);
upgradeAndCall(
output.opChainProxyAdmin, address(output.systemConfigProxy), implementation.systemConfigImpl, data
);
impl = getLatestImplementation("OptimismMintableERC20Factory");
data = encodeOptimismMintableERC20FactoryInitializer(impl.initializer, output);
upgradeAndCall(output.opChainProxyAdmin, address(output.optimismMintableERC20FactoryProxy), impl.logic, data);
data = encodeOptimismMintableERC20FactoryInitializer(IOptimismMintableERC20Factory.initialize.selector, output);
upgradeAndCall(
output.opChainProxyAdmin,
address(output.optimismMintableERC20FactoryProxy),
implementation.optimismMintableERC20FactoryImpl,
data
);
impl = getLatestImplementation("L1CrossDomainMessenger");
data = encodeL1CrossDomainMessengerInitializer(impl.initializer, output);
upgradeAndCall(output.opChainProxyAdmin, address(output.l1CrossDomainMessengerProxy), impl.logic, data);
data = encodeL1CrossDomainMessengerInitializer(IL1CrossDomainMessenger.initialize.selector, output);
upgradeAndCall(
output.opChainProxyAdmin,
address(output.l1CrossDomainMessengerProxy),
implementation.l1CrossDomainMessengerImpl,
data
);
impl = getLatestImplementation("L1StandardBridge");
data = encodeL1StandardBridgeInitializer(impl.initializer, output);
upgradeAndCall(output.opChainProxyAdmin, address(output.l1StandardBridgeProxy), impl.logic, data);
data = encodeL1StandardBridgeInitializer(IL1StandardBridge.initialize.selector, output);
upgradeAndCall(
output.opChainProxyAdmin, address(output.l1StandardBridgeProxy), implementation.l1StandardBridgeImpl, data
);
impl = getLatestImplementation("DelayedWETH");
data = encodeDelayedWETHInitializer(impl.initializer, _input);
data = encodeDelayedWETHInitializer(IDelayedWETH.initialize.selector, _input);
// Eventually we will switch from DelayedWETHPermissionedGameProxy to DelayedWETHPermissionlessGameProxy.
upgradeAndCall(output.opChainProxyAdmin, address(output.delayedWETHPermissionedGameProxy), impl.logic, data);
upgradeAndCall(
output.opChainProxyAdmin,
address(output.delayedWETHPermissionedGameProxy),
implementation.delayedWETHImpl,
data
);
// We set the initial owner to this contract, set game implementations, then transfer ownership.
impl = getLatestImplementation("DisputeGameFactory");
data = encodeDisputeGameFactoryInitializer(impl.initializer, _input);
upgradeAndCall(output.opChainProxyAdmin, address(output.disputeGameFactoryProxy), impl.logic, data);
data = encodeDisputeGameFactoryInitializer(IDisputeGameFactory.initialize.selector, _input);
upgradeAndCall(
output.opChainProxyAdmin,
address(output.disputeGameFactoryProxy),
implementation.disputeGameFactoryImpl,
data
);
output.disputeGameFactoryProxy.setImplementation(
GameTypes.PERMISSIONED_CANNON, IDisputeGame(address(output.permissionedDisputeGame))
);
output.disputeGameFactoryProxy.transferOwnership(address(_input.roles.opChainProxyAdminOwner));
impl.logic = address(output.anchorStateRegistryImpl);
impl.initializer = IAnchorStateRegistry.initialize.selector;
data = encodeAnchorStateRegistryInitializer(impl.initializer, _input);
upgradeAndCall(output.opChainProxyAdmin, address(output.anchorStateRegistryProxy), impl.logic, data);
data = encodeAnchorStateRegistryInitializer(IAnchorStateRegistry.initialize.selector, _input);
upgradeAndCall(
output.opChainProxyAdmin,
address(output.anchorStateRegistryProxy),
address(output.anchorStateRegistryImpl),
data
);
// -------- Finalize Deployment --------
// Transfer ownership of the ProxyAdmin from this contract to the specified owner.
......@@ -402,13 +392,6 @@ contract OPContractsManager is ISemver, Initializable {
return Blueprint.deployFrom(blueprint.proxy, salt, abi.encode(_proxyAdmin));
}
/// @notice Returns the implementation data for a contract name. Makes a copy of the internal
// Implementation struct in storage to prevent accidental mutation of the internal data.
function getLatestImplementation(string memory _name) internal view returns (Implementation memory) {
Implementation storage impl = implementations[latestRelease][_name];
return Implementation({ logic: impl.logic, initializer: impl.initializer });
}
// -------- Initializer Encoding --------
/// @notice Helper method for encoding the L1ERC721Bridge initializer data.
......@@ -445,7 +428,6 @@ contract OPContractsManager is ISemver, Initializable {
/// @notice Helper method for encoding the SystemConfig initializer data.
function encodeSystemConfigInitializer(
bytes4 _selector,
DeployInput memory _input,
DeployOutput memory _output
)
......@@ -454,50 +436,22 @@ contract OPContractsManager is ISemver, Initializable {
virtual
returns (bytes memory)
{
// We inspect the SystemConfig contract and determine it's signature here. This is required
// because this OPCM contract is being developed in a repository that no longer contains the
// SystemConfig contract that was released as part of `op-contracts/v1.6.0`, but in production
// it needs to support that version, in addition to the version currently on develop.
string memory semver = _output.systemConfigProxy.version();
if (keccak256(abi.encode(semver)) == keccak256(abi.encode(string("2.2.0")))) {
// We are using the op-contracts/v1.6.0 SystemConfig contract.
(
IResourceMetering.ResourceConfig memory referenceResourceConfig,
ISystemConfigV160.Addresses memory opChainAddrs
) = defaultSystemConfigV160Params(_selector, _input, _output);
return abi.encodeWithSelector(
_selector,
_input.roles.systemConfigOwner,
_input.basefeeScalar,
_input.blobBasefeeScalar,
bytes32(uint256(uint160(_input.roles.batcher))), // batcherHash
_input.gasLimit,
_input.roles.unsafeBlockSigner,
referenceResourceConfig,
chainIdToBatchInboxAddress(_input.l2ChainId),
opChainAddrs
);
} else {
// We are using the latest SystemConfig contract from the repo.
(
IResourceMetering.ResourceConfig memory referenceResourceConfig,
ISystemConfig.Addresses memory opChainAddrs
) = defaultSystemConfigParams(_selector, _input, _output);
return abi.encodeWithSelector(
_selector,
_input.roles.systemConfigOwner,
_input.basefeeScalar,
_input.blobBasefeeScalar,
bytes32(uint256(uint160(_input.roles.batcher))), // batcherHash
_input.gasLimit,
_input.roles.unsafeBlockSigner,
referenceResourceConfig,
chainIdToBatchInboxAddress(_input.l2ChainId),
opChainAddrs
);
}
bytes4 selector = ISystemConfig.initialize.selector;
(IResourceMetering.ResourceConfig memory referenceResourceConfig, ISystemConfig.Addresses memory opChainAddrs) =
defaultSystemConfigParams(selector, _input, _output);
return abi.encodeWithSelector(
selector,
_input.roles.systemConfigOwner,
_input.basefeeScalar,
_input.blobBasefeeScalar,
bytes32(uint256(uint160(_input.roles.batcher))), // batcherHash
_input.gasLimit,
_input.roles.unsafeBlockSigner,
referenceResourceConfig,
chainIdToBatchInboxAddress(_input.l2ChainId),
opChainAddrs
);
}
/// @notice Helper method for encoding the OptimismMintableERC20Factory initializer data.
......@@ -599,7 +553,7 @@ contract OPContractsManager is ISemver, Initializable {
_input.disputeSplitDepth,
_input.disputeClockExtension,
_input.disputeMaxClockDuration,
IBigStepper(getLatestImplementation("MIPS").logic),
IBigStepper(implementation.mipsImpl),
IDelayedWETH(payable(address(_output.delayedWETHPermissionedGameProxy))),
IAnchorStateRegistry(address(_output.anchorStateRegistryProxy)),
_input.l2ChainId,
......@@ -645,45 +599,6 @@ contract OPContractsManager is ISemver, Initializable {
assertValidContractAddress(opChainAddrs_.optimismMintableERC20Factory);
}
/// @notice Returns default, standard config arguments for the SystemConfig initializer.
/// This is used by subclasses to reduce code duplication.
function defaultSystemConfigV160Params(
bytes4, /* selector */
DeployInput memory, /* _input */
DeployOutput memory _output
)
internal
view
virtual
returns (
IResourceMetering.ResourceConfig memory resourceConfig_,
ISystemConfigV160.Addresses memory opChainAddrs_
)
{
// We use assembly to easily convert from IResourceMetering.ResourceConfig to ResourceMetering.ResourceConfig.
// This is required because we have not yet fully migrated the codebase to be interface-based.
IResourceMetering.ResourceConfig memory resourceConfig = Constants.DEFAULT_RESOURCE_CONFIG();
assembly ("memory-safe") {
resourceConfig_ := resourceConfig
}
opChainAddrs_ = ISystemConfigV160.Addresses({
l1CrossDomainMessenger: address(_output.l1CrossDomainMessengerProxy),
l1ERC721Bridge: address(_output.l1ERC721BridgeProxy),
l1StandardBridge: address(_output.l1StandardBridgeProxy),
disputeGameFactory: address(_output.disputeGameFactoryProxy),
optimismPortal: address(_output.optimismPortalProxy),
optimismMintableERC20Factory: address(_output.optimismMintableERC20FactoryProxy)
});
assertValidContractAddress(opChainAddrs_.l1CrossDomainMessenger);
assertValidContractAddress(opChainAddrs_.l1ERC721Bridge);
assertValidContractAddress(opChainAddrs_.l1StandardBridge);
assertValidContractAddress(opChainAddrs_.disputeGameFactory);
assertValidContractAddress(opChainAddrs_.optimismPortal);
assertValidContractAddress(opChainAddrs_.optimismMintableERC20Factory);
}
/// @notice Makes an external call to the target to initialize the proxy with the specified data.
/// First performs safety checks to ensure the target, implementation, and proxy admin are valid.
function upgradeAndCall(
......@@ -710,4 +625,9 @@ contract OPContractsManager is ISemver, Initializable {
function blueprints() public view returns (Blueprints memory) {
return blueprint;
}
/// @notice Returns the implementation contract addresses.
function implementations() public view returns (Implementations memory) {
return implementation;
}
}
......@@ -6,20 +6,22 @@ import { ISuperchainConfig } from "src/L1/interfaces/ISuperchainConfig.sol";
import { IProtocolVersions } from "src/L1/interfaces/IProtocolVersions.sol";
import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol";
import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol";
import { ISystemConfigInterop } from "src/L1/interfaces/ISystemConfigInterop.sol";
/// @custom:proxied true
contract OPContractsManagerInterop is OPContractsManager {
constructor(
ISuperchainConfig _superchainConfig,
IProtocolVersions _protocolVersions
IProtocolVersions _protocolVersions,
string memory _l1ContractsRelease,
Blueprints memory _blueprints,
Implementations memory _implementations
)
OPContractsManager(_superchainConfig, _protocolVersions)
OPContractsManager(_superchainConfig, _protocolVersions, _l1ContractsRelease, _blueprints, _implementations)
{ }
// The `SystemConfigInterop` contract has an extra `address _dependencyManager` argument
// that we must account for.
function encodeSystemConfigInitializer(
bytes4 _selector,
DeployInput memory _input,
DeployOutput memory _output
)
......@@ -29,8 +31,9 @@ contract OPContractsManagerInterop is OPContractsManager {
override
returns (bytes memory)
{
bytes4 selector = ISystemConfigInterop.initialize.selector;
(IResourceMetering.ResourceConfig memory referenceResourceConfig, ISystemConfig.Addresses memory opChainAddrs) =
defaultSystemConfigParams(_selector, _input, _output);
defaultSystemConfigParams(selector, _input, _output);
// TODO For now we assume that the dependency manager is the same as system config owner.
// This is currently undefined since it's not part of the standard config, so we may need
......@@ -40,7 +43,7 @@ contract OPContractsManagerInterop is OPContractsManager {
address dependencyManager = address(_input.roles.systemConfigOwner);
return abi.encodeWithSelector(
_selector,
selector,
_input.roles.systemConfigOwner,
_input.basefeeScalar,
_input.blobBasefeeScalar,
......
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { IResourceMetering } from "src/L1/interfaces/IResourceMetering.sol";
/// @notice This interface corresponds to the op-contracts/v1.6.0 release of the SystemConfig
/// contract, which has a semver of 2.2.0 as specified in
/// https://github.com/ethereum-optimism/optimism/releases/tag/op-contracts%2Fv1.6.0
interface ISystemConfigV160 {
enum UpdateType {
BATCHER,
FEE_SCALARS,
GAS_LIMIT,
UNSAFE_BLOCK_SIGNER
}
struct Addresses {
address l1CrossDomainMessenger;
address l1ERC721Bridge;
address l1StandardBridge;
address disputeGameFactory;
address optimismPortal;
address optimismMintableERC20Factory;
}
event ConfigUpdate(uint256 indexed version, UpdateType indexed updateType, bytes data);
event Initialized(uint8 version);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
function BATCH_INBOX_SLOT() external view returns (bytes32);
function DISPUTE_GAME_FACTORY_SLOT() external view returns (bytes32);
function L1_CROSS_DOMAIN_MESSENGER_SLOT() external view returns (bytes32);
function L1_ERC_721_BRIDGE_SLOT() external view returns (bytes32);
function L1_STANDARD_BRIDGE_SLOT() external view returns (bytes32);
function OPTIMISM_MINTABLE_ERC20_FACTORY_SLOT() external view returns (bytes32);
function OPTIMISM_PORTAL_SLOT() external view returns (bytes32);
function START_BLOCK_SLOT() external view returns (bytes32);
function UNSAFE_BLOCK_SIGNER_SLOT() external view returns (bytes32);
function VERSION() external view returns (uint256);
function basefeeScalar() external view returns (uint32);
function batchInbox() external view returns (address addr_);
function batcherHash() external view returns (bytes32);
function blobbasefeeScalar() external view returns (uint32);
function disputeGameFactory() external view returns (address addr_);
function gasLimit() external view returns (uint64);
function gasPayingToken() external view returns (address addr_, uint8 decimals_);
function gasPayingTokenName() external view returns (string memory name_);
function gasPayingTokenSymbol() external view returns (string memory symbol_);
function initialize(
address _owner,
uint256 _basefeeScalar,
uint256 _blobbasefeeScalar,
bytes32 _batcherHash,
uint64 _gasLimit,
address _unsafeBlockSigner,
IResourceMetering.ResourceConfig memory _config,
address _batchInbox,
Addresses memory _addresses
)
external;
function isCustomGasToken() external view returns (bool);
function l1CrossDomainMessenger() external view returns (address addr_);
function l1ERC721Bridge() external view returns (address addr_);
function l1StandardBridge() external view returns (address addr_);
function maximumGasLimit() external pure returns (uint64);
function minimumGasLimit() external view returns (uint64);
function optimismMintableERC20Factory() external view returns (address addr_);
function optimismPortal() external view returns (address addr_);
function overhead() external view returns (uint256);
function owner() external view returns (address);
function renounceOwnership() external;
function resourceConfig() external view returns (IResourceMetering.ResourceConfig memory);
function scalar() external view returns (uint256);
function setBatcherHash(bytes32 _batcherHash) external;
function setGasConfig(uint256 _overhead, uint256 _scalar) external;
function setGasConfigEcotone(uint32 _basefeeScalar, uint32 _blobbasefeeScalar) external;
function setGasLimit(uint64 _gasLimit) external;
function setUnsafeBlockSigner(address _unsafeBlockSigner) external;
function startBlock() external view returns (uint256 startBlock_);
function transferOwnership(address newOwner) external; // nosemgrep
function unsafeBlockSigner() external view returns (address addr_);
function version() external pure returns (string memory);
function __constructor__() external;
}
......@@ -14,9 +14,12 @@ import { IProtocolVersions } from "src/L1/interfaces/IProtocolVersions.sol";
contract OPContractsManager_Harness is OPContractsManager {
constructor(
ISuperchainConfig _superchainConfig,
IProtocolVersions _protocolVersions
IProtocolVersions _protocolVersions,
string memory _l1ContractsRelease,
Blueprints memory _blueprints,
Implementations memory _implementations
)
OPContractsManager(_superchainConfig, _protocolVersions)
OPContractsManager(_superchainConfig, _protocolVersions, _l1ContractsRelease, _blueprints, _implementations)
{ }
function chainIdToBatchInboxAddress_exposed(uint256 l2ChainId) public pure returns (address) {
......@@ -49,7 +52,7 @@ contract OPContractsManager_Deploy_Test is DeployOPChain_TestBase {
doi.set(doi.basefeeScalar.selector, basefeeScalar);
doi.set(doi.blobBaseFeeScalar.selector, blobBaseFeeScalar);
doi.set(doi.l2ChainId.selector, l2ChainId);
doi.set(doi.opcmProxy.selector, address(opcm));
doi.set(doi.opcm.selector, address(opcm));
doi.set(doi.gasLimit.selector, gasLimit);
doi.set(doi.disputeGameType.selector, disputeGameType);
......@@ -116,12 +119,17 @@ contract OPContractsManager_InternalMethods_Test is Test {
function setUp() public {
ISuperchainConfig superchainConfigProxy = ISuperchainConfig(makeAddr("superchainConfig"));
IProtocolVersions protocolVersionsProxy = IProtocolVersions(makeAddr("protocolVersions"));
OPContractsManager.Blueprints memory emptyBlueprints;
OPContractsManager.Implementations memory emptyImpls;
vm.etch(address(superchainConfigProxy), hex"01");
vm.etch(address(protocolVersionsProxy), hex"01");
opcmHarness = new OPContractsManager_Harness({
_superchainConfig: superchainConfigProxy,
_protocolVersions: protocolVersionsProxy
_protocolVersions: protocolVersionsProxy,
_l1ContractsRelease: "dev",
_blueprints: emptyBlueprints,
_implementations: emptyImpls
});
}
......
......@@ -61,7 +61,7 @@ contract DeployImplementationsInput_Test is Test {
dii.disputeGameFinalityDelaySeconds();
vm.expectRevert("DeployImplementationsInput: not set");
dii.release();
dii.l1ContractsRelease();
vm.expectRevert("DeployImplementationsInput: not set");
dii.superchainConfigProxy();
......@@ -69,23 +69,9 @@ contract DeployImplementationsInput_Test is Test {
vm.expectRevert("DeployImplementationsInput: not set");
dii.protocolVersionsProxy();
vm.expectRevert("DeployImplementationsInput: not set");
dii.opcmProxyOwner();
vm.expectRevert("DeployImplementationsInput: not set");
dii.standardVersionsToml();
}
function test_opcmProxyOwner_whenNotSet_reverts() public {
vm.expectRevert("DeployImplementationsInput: not set");
dii.opcmProxyOwner();
}
function test_opcmProxyOwner_succeeds() public {
dii.set(dii.opcmProxyOwner.selector, address(msg.sender));
address opcmProxyOwner = dii.opcmProxyOwner();
assertEq(address(msg.sender), address(opcmProxyOwner), "100");
}
}
contract DeployImplementationsOutput_Test is Test {
......@@ -96,17 +82,7 @@ contract DeployImplementationsOutput_Test is Test {
}
function test_set_succeeds() public {
IProxy proxy = IProxy(
DeployUtils.create1({
_name: "Proxy",
_args: DeployUtils.encodeConstructor(abi.encodeCall(IProxy.__constructor__, (address(0))))
})
);
address opcmImpl = address(makeAddr("opcmImpl"));
vm.prank(address(0));
proxy.upgradeTo(opcmImpl);
OPContractsManager opcmProxy = OPContractsManager(address(proxy));
OPContractsManager opcm = OPContractsManager(address(makeAddr("opcm")));
IOptimismPortal2 optimismPortalImpl = IOptimismPortal2(payable(makeAddr("optimismPortalImpl")));
IDelayedWETH delayedWETHImpl = IDelayedWETH(payable(makeAddr("delayedWETHImpl")));
IPreimageOracle preimageOracleSingleton = IPreimageOracle(makeAddr("preimageOracleSingleton"));
......@@ -120,8 +96,7 @@ contract DeployImplementationsOutput_Test is Test {
IOptimismMintableERC20Factory(makeAddr("optimismMintableERC20FactoryImpl"));
IDisputeGameFactory disputeGameFactoryImpl = IDisputeGameFactory(makeAddr("disputeGameFactoryImpl"));
vm.etch(address(opcmProxy), address(opcmProxy).code);
vm.etch(address(opcmImpl), hex"01");
vm.etch(address(opcm), hex"01");
vm.etch(address(optimismPortalImpl), hex"01");
vm.etch(address(delayedWETHImpl), hex"01");
vm.etch(address(preimageOracleSingleton), hex"01");
......@@ -132,7 +107,7 @@ contract DeployImplementationsOutput_Test is Test {
vm.etch(address(l1StandardBridgeImpl), hex"01");
vm.etch(address(optimismMintableERC20FactoryImpl), hex"01");
vm.etch(address(disputeGameFactoryImpl), hex"01");
dio.set(dio.opcmProxy.selector, address(opcmProxy));
dio.set(dio.opcm.selector, address(opcm));
dio.set(dio.optimismPortalImpl.selector, address(optimismPortalImpl));
dio.set(dio.delayedWETHImpl.selector, address(delayedWETHImpl));
dio.set(dio.preimageOracleSingleton.selector, address(preimageOracleSingleton));
......@@ -144,7 +119,7 @@ contract DeployImplementationsOutput_Test is Test {
dio.set(dio.optimismMintableERC20FactoryImpl.selector, address(optimismMintableERC20FactoryImpl));
dio.set(dio.disputeGameFactoryImpl.selector, address(disputeGameFactoryImpl));
assertEq(address(opcmProxy), address(dio.opcmProxy()), "50");
assertEq(address(opcm), address(dio.opcm()), "50");
assertEq(address(optimismPortalImpl), address(dio.optimismPortalImpl()), "100");
assertEq(address(delayedWETHImpl), address(dio.delayedWETHImpl()), "200");
assertEq(address(preimageOracleSingleton), address(dio.preimageOracleSingleton()), "300");
......@@ -273,7 +248,7 @@ contract DeployImplementations_Test is Test {
function test_deployImplementation_succeeds() public {
string memory deployContractsRelease = "dev-release";
dii.set(dii.release.selector, deployContractsRelease);
dii.set(dii.l1ContractsRelease.selector, deployContractsRelease);
deployImplementations.deploySystemConfigImpl(dii, dio);
assertTrue(address(0) != address(dio.systemConfigImpl()));
}
......@@ -282,7 +257,7 @@ contract DeployImplementations_Test is Test {
// All hardcoded addresses below are taken from the superchain-registry config:
// https://github.com/ethereum-optimism/superchain-registry/blob/be65d22f8128cf0c4e5b4e1f677daf86843426bf/validation/standard/standard-versions.toml#L11
string memory testRelease = "op-contracts/v1.6.0";
dii.set(dii.release.selector, testRelease);
dii.set(dii.l1ContractsRelease.selector, testRelease);
deployImplementations.deploySystemConfigImpl(dii, dio);
address srSystemConfigImpl = address(0xF56D96B2535B932656d3c04Ebf51baBff241D886);
......@@ -335,71 +310,6 @@ contract DeployImplementations_Test is Test {
assertEq(srDisputeGameFactoryImpl, address(dio.disputeGameFactoryImpl()));
}
function test_deploy_atNonExistentRelease_reverts() public {
string memory unknownRelease = "op-contracts/v0.0.0";
dii.set(dii.release.selector, unknownRelease);
bytes memory expectedErr =
bytes(string.concat("DeployImplementations: failed to deploy release ", unknownRelease));
vm.expectRevert(expectedErr);
deployImplementations.deploySystemConfigImpl(dii, dio);
vm.expectRevert(expectedErr);
deployImplementations.deployL1CrossDomainMessengerImpl(dii, dio);
vm.expectRevert(expectedErr);
deployImplementations.deployL1ERC721BridgeImpl(dii, dio);
vm.expectRevert(expectedErr);
deployImplementations.deployL1StandardBridgeImpl(dii, dio);
vm.expectRevert(expectedErr);
deployImplementations.deployOptimismMintableERC20FactoryImpl(dii, dio);
// TODO: Uncomment the code below when OPContractsManager is deployed based on release. Superchain-registry
// doesn't contain OPContractsManager yet.
// dii.set(dii.superchainConfigProxy.selector, address(superchainConfigProxy));
// dii.set(dii.protocolVersionsProxy.selector, address(protocolVersionsProxy));
// vm.etch(address(superchainConfigProxy), hex"01");
// vm.etch(address(protocolVersionsProxy), hex"01");
// vm.expectRevert(expectedErr);
// deployImplementations.deployOPContractsManagerImpl(dii, dio);
dii.set(dii.proofMaturityDelaySeconds.selector, 1);
dii.set(dii.disputeGameFinalityDelaySeconds.selector, 2);
vm.expectRevert(expectedErr);
deployImplementations.deployOptimismPortalImpl(dii, dio);
dii.set(dii.withdrawalDelaySeconds.selector, 1);
vm.expectRevert(expectedErr);
deployImplementations.deployDelayedWETHImpl(dii, dio);
dii.set(dii.minProposalSizeBytes.selector, 1);
dii.set(dii.challengePeriodSeconds.selector, 2);
vm.expectRevert(expectedErr);
deployImplementations.deployPreimageOracleSingleton(dii, dio);
address preImageOracleSingleton = makeAddr("preImageOracleSingleton");
vm.etch(address(preImageOracleSingleton), hex"01");
dio.set(dio.preimageOracleSingleton.selector, preImageOracleSingleton);
vm.expectRevert(expectedErr);
deployImplementations.deployMipsSingleton(dii, dio);
vm.expectRevert(expectedErr); // fault proof contracts don't exist at this release
deployImplementations.deployDisputeGameFactoryImpl(dii, dio);
}
function test_deploy_noContractExistsAtRelease_reverts() public {
string memory unknownRelease = "op-contracts/v1.3.0";
dii.set(dii.release.selector, unknownRelease);
bytes memory expectedErr =
bytes(string.concat("DeployImplementations: failed to deploy release ", unknownRelease));
vm.expectRevert(expectedErr); // fault proof contracts don't exist at this release
deployImplementations.deployDisputeGameFactoryImpl(dii, dio);
}
function testFuzz_run_memory_succeeds(bytes32 _seed) public {
withdrawalDelaySeconds = uint256(hash(_seed, 0));
minProposalSizeBytes = uint256(hash(_seed, 1));
......@@ -409,7 +319,7 @@ contract DeployImplementations_Test is Test {
string memory release = string(bytes.concat(hash(_seed, 5)));
protocolVersionsProxy = IProtocolVersions(address(uint160(uint256(hash(_seed, 7)))));
// Must configure the ProxyAdmin contract which is used to upgrade the OPCM's proxy contract.
// Must configure the ProxyAdmin contract.
IProxyAdmin superchainProxyAdmin = IProxyAdmin(
DeployUtils.create1({
_name: "ProxyAdmin",
......@@ -439,10 +349,9 @@ contract DeployImplementations_Test is Test {
dii.set(dii.proofMaturityDelaySeconds.selector, proofMaturityDelaySeconds);
dii.set(dii.disputeGameFinalityDelaySeconds.selector, disputeGameFinalityDelaySeconds);
dii.set(dii.mipsVersion.selector, 1);
dii.set(dii.release.selector, release);
dii.set(dii.l1ContractsRelease.selector, release);
dii.set(dii.superchainConfigProxy.selector, address(superchainConfigProxy));
dii.set(dii.protocolVersionsProxy.selector, address(protocolVersionsProxy));
dii.set(dii.opcmProxyOwner.selector, msg.sender);
deployImplementations.run(dii, dio);
......@@ -453,10 +362,9 @@ contract DeployImplementations_Test is Test {
assertEq(proofMaturityDelaySeconds, dii.proofMaturityDelaySeconds(), "400");
assertEq(disputeGameFinalityDelaySeconds, dii.disputeGameFinalityDelaySeconds(), "500");
assertEq(1, dii.mipsVersion(), "512");
assertEq(release, dii.release(), "525");
assertEq(release, dii.l1ContractsRelease(), "525");
assertEq(address(superchainConfigProxy), address(dii.superchainConfigProxy()), "550");
assertEq(address(protocolVersionsProxy), address(dii.protocolVersionsProxy()), "575");
assertEq(msg.sender, dii.opcmProxyOwner(), "580");
// Architecture assertions.
assertEq(address(dio.mipsSingleton().oracle()), address(dio.preimageOracleSingleton()), "600");
......@@ -475,7 +383,7 @@ contract DeployImplementations_Test is Test {
dii.set(dii.disputeGameFinalityDelaySeconds.selector, disputeGameFinalityDelaySeconds);
dii.set(dii.mipsVersion.selector, 1);
string memory release = "dev-release";
dii.set(dii.release.selector, release);
dii.set(dii.l1ContractsRelease.selector, release);
dii.set(dii.superchainConfigProxy.selector, address(superchainConfigProxy));
dii.set(dii.protocolVersionsProxy.selector, address(protocolVersionsProxy));
......
......@@ -39,10 +39,10 @@ contract DeployOPChainInput_Test is Test {
address unsafeBlockSigner = makeAddr("unsafeBlockSigner");
address proposer = makeAddr("proposer");
address challenger = makeAddr("challenger");
address opcm = makeAddr("opcm");
uint32 basefeeScalar = 100;
uint32 blobBaseFeeScalar = 200;
uint256 l2ChainId = 300;
OPContractsManager opcm = OPContractsManager(makeAddr("opcm"));
string saltMixer = "saltMixer";
function setUp() public {
......@@ -60,9 +60,8 @@ contract DeployOPChainInput_Test is Test {
doi.set(doi.blobBaseFeeScalar.selector, blobBaseFeeScalar);
doi.set(doi.l2ChainId.selector, l2ChainId);
doi.set(doi.allowCustomDisputeParameters.selector, true);
(IProxy opcmProxy) = DeployUtils.buildERC1967ProxyWithImpl("opcmProxy");
doi.set(doi.opcmProxy.selector, address(opcmProxy));
doi.set(doi.opcm.selector, opcm);
vm.etch(opcm, hex"01");
// Compare the default inputs to the getter methods.
assertEq(opChainProxyAdminOwner, doi.opChainProxyAdminOwner(), "200");
......@@ -74,7 +73,7 @@ contract DeployOPChainInput_Test is Test {
assertEq(basefeeScalar, doi.basefeeScalar(), "800");
assertEq(blobBaseFeeScalar, doi.blobBaseFeeScalar(), "900");
assertEq(l2ChainId, doi.l2ChainId(), "1000");
assertEq(address(opcmProxy), address(doi.opcmProxy()), "1100");
assertEq(opcm, address(doi.opcm()), "1100");
assertEq(true, doi.allowCustomDisputeParameters(), "1200");
}
......@@ -396,7 +395,7 @@ contract DeployOPChain_TestBase is Test {
dii.set(dii.proofMaturityDelaySeconds.selector, proofMaturityDelaySeconds);
dii.set(dii.disputeGameFinalityDelaySeconds.selector, disputeGameFinalityDelaySeconds);
dii.set(dii.mipsVersion.selector, 1);
dii.set(dii.release.selector, release);
dii.set(dii.l1ContractsRelease.selector, release);
dii.set(dii.superchainConfigProxy.selector, address(superchainConfigProxy));
dii.set(dii.protocolVersionsProxy.selector, address(protocolVersionsProxy));
// End users of the DeployImplementations contract will need to set the `standardVersionsToml`.
......@@ -404,7 +403,7 @@ contract DeployOPChain_TestBase is Test {
string.concat(vm.projectRoot(), "/test/fixtures/standard-versions.toml");
string memory standardVersionsToml = vm.readFile(standardVersionsTomlPath);
dii.set(dii.standardVersionsToml.selector, standardVersionsToml);
dii.set(dii.opcmProxyOwner.selector, address(1));
deployImplementations.run(dii, dio);
// Deploy DeployOpChain, but defer populating the input values to the test suites inheriting this contract.
......@@ -412,7 +411,7 @@ contract DeployOPChain_TestBase is Test {
(doi, doo) = deployOPChain.etchIOContracts();
// Set the OPContractsManager input for DeployOPChain.
opcm = dio.opcmProxy();
opcm = dio.opcm();
}
// See the function of the same name in the `DeployImplementations_Test` contract of
......@@ -466,7 +465,7 @@ contract DeployOPChain_Test is DeployOPChain_TestBase {
doi.set(doi.basefeeScalar.selector, basefeeScalar);
doi.set(doi.blobBaseFeeScalar.selector, blobBaseFeeScalar);
doi.set(doi.l2ChainId.selector, l2ChainId);
doi.set(doi.opcmProxy.selector, address(opcm)); // Not fuzzed since it must be an actual instance.
doi.set(doi.opcm.selector, address(opcm));
doi.set(doi.saltMixer.selector, saltMixer);
doi.set(doi.gasLimit.selector, gasLimit);
doi.set(doi.disputeGameType.selector, disputeGameType);
......@@ -559,7 +558,7 @@ contract DeployOPChain_Test is DeployOPChain_TestBase {
doi.set(doi.basefeeScalar.selector, basefeeScalar);
doi.set(doi.blobBaseFeeScalar.selector, blobBaseFeeScalar);
doi.set(doi.l2ChainId.selector, l2ChainId);
doi.set(doi.opcmProxy.selector, address(opcm));
doi.set(doi.opcm.selector, address(opcm));
doi.set(doi.saltMixer.selector, saltMixer);
doi.set(doi.gasLimit.selector, gasLimit);
doi.set(doi.disputeGameType.selector, disputeGameType);
......
......@@ -16,6 +16,7 @@ import { IOptimismPortal } from "src/L1/interfaces/IOptimismPortal.sol";
import { IOptimismPortal2 } from "src/L1/interfaces/IOptimismPortal2.sol";
import { IOptimismPortalInterop } from "src/L1/interfaces/IOptimismPortalInterop.sol";
import { ISystemConfig } from "src/L1/interfaces/ISystemConfig.sol";
import { ISystemConfigInterop } from "src/L1/interfaces/ISystemConfigInterop.sol";
import { IDataAvailabilityChallenge } from "src/L1/interfaces/IDataAvailabilityChallenge.sol";
import { IProtocolVersions } from "src/L1/interfaces/IProtocolVersions.sol";
......@@ -479,36 +480,37 @@ contract Specification_Test is CommonTest {
_addSpec({ _name: "SystemConfigInterop", _sel: _getSel("gasLimit()") });
_addSpec({ _name: "SystemConfigInterop", _sel: _getSel("eip1559Denominator()") });
_addSpec({ _name: "SystemConfigInterop", _sel: _getSel("eip1559Elasticity()") });
_addSpec({ _name: "SystemConfigInterop", _sel: ISystemConfigInterop.initialize.selector });
_addSpec({ _name: "SystemConfigInterop", _sel: ISystemConfig.initialize.selector });
_addSpec({ _name: "SystemConfigInterop", _sel: ISystemConfig.minimumGasLimit.selector });
_addSpec({ _name: "SystemConfigInterop", _sel: ISystemConfigInterop.minimumGasLimit.selector });
_addSpec({ _name: "SystemConfigInterop", _sel: _getSel("overhead()") });
_addSpec({ _name: "SystemConfigInterop", _sel: _getSel("owner()") });
_addSpec({ _name: "SystemConfigInterop", _sel: _getSel("renounceOwnership()"), _auth: Role.SYSTEMCONFIGOWNER });
_addSpec({ _name: "SystemConfigInterop", _sel: ISystemConfig.resourceConfig.selector });
_addSpec({ _name: "SystemConfigInterop", _sel: ISystemConfigInterop.resourceConfig.selector });
_addSpec({ _name: "SystemConfigInterop", _sel: _getSel("scalar()") });
_addSpec({
_name: "SystemConfigInterop",
_sel: ISystemConfig.setBatcherHash.selector,
_sel: ISystemConfigInterop.setBatcherHash.selector,
_auth: Role.SYSTEMCONFIGOWNER
});
_addSpec({
_name: "SystemConfigInterop",
_sel: ISystemConfig.setGasConfig.selector,
_sel: ISystemConfigInterop.setGasConfig.selector,
_auth: Role.SYSTEMCONFIGOWNER
});
_addSpec({
_name: "SystemConfigInterop",
_sel: ISystemConfig.setGasLimit.selector,
_sel: ISystemConfigInterop.setGasLimit.selector,
_auth: Role.SYSTEMCONFIGOWNER
});
_addSpec({
_name: "SystemConfigInterop",
_sel: ISystemConfig.setEIP1559Params.selector,
_sel: ISystemConfigInterop.setEIP1559Params.selector,
_auth: Role.SYSTEMCONFIGOWNER
});
_addSpec({
_name: "SystemConfigInterop",
_sel: ISystemConfig.setUnsafeBlockSigner.selector,
_sel: ISystemConfigInterop.setUnsafeBlockSigner.selector,
_auth: Role.SYSTEMCONFIGOWNER
});
_addSpec({
......@@ -516,7 +518,7 @@ contract Specification_Test is CommonTest {
_sel: _getSel("transferOwnership(address)"),
_auth: Role.SYSTEMCONFIGOWNER
});
_addSpec({ _name: "SystemConfigInterop", _sel: ISystemConfig.unsafeBlockSigner.selector });
_addSpec({ _name: "SystemConfigInterop", _sel: ISystemConfigInterop.unsafeBlockSigner.selector });
_addSpec({ _name: "SystemConfigInterop", _sel: _getSel("version()") });
_addSpec({ _name: "SystemConfigInterop", _sel: _getSel("l1CrossDomainMessenger()") });
_addSpec({ _name: "SystemConfigInterop", _sel: _getSel("l1ERC721Bridge()") });
......@@ -552,12 +554,6 @@ contract Specification_Test is CommonTest {
_auth: Role.DEPENDENCYMANAGER
});
_addSpec({ _name: "SystemConfigInterop", _sel: _getSel("dependencyManager()") });
_addSpec({
_name: "SystemConfigInterop",
_sel: _getSel(
"initialize(address,uint32,uint32,bytes32,uint64,address,(uint32,uint8,uint8,uint32,uint32,uint128),address,(address,address,address,address,address,address,address),address)"
)
});
// ProxyAdmin
_addSpec({ _name: "ProxyAdmin", _sel: _getSel("addressManager()") });
......@@ -841,27 +837,25 @@ contract Specification_Test is CommonTest {
_addSpec({ _name: "OPContractsManager", _sel: _getSel("version()") });
_addSpec({ _name: "OPContractsManager", _sel: _getSel("superchainConfig()") });
_addSpec({ _name: "OPContractsManager", _sel: _getSel("protocolVersions()") });
_addSpec({ _name: "OPContractsManager", _sel: _getSel("latestRelease()") });
_addSpec({ _name: "OPContractsManager", _sel: _getSel("implementations(string,string)") });
_addSpec({ _name: "OPContractsManager", _sel: _getSel("l1ContractsRelease()") });
_addSpec({ _name: "OPContractsManager", _sel: _getSel("systemConfigs(uint256)") });
_addSpec({ _name: "OPContractsManager", _sel: _getSel("OUTPUT_VERSION()") });
_addSpec({ _name: "OPContractsManager", _sel: OPContractsManager.initialize.selector });
_addSpec({ _name: "OPContractsManager", _sel: OPContractsManager.deploy.selector });
_addSpec({ _name: "OPContractsManager", _sel: OPContractsManager.blueprints.selector });
_addSpec({ _name: "OPContractsManager", _sel: OPContractsManager.chainIdToBatchInboxAddress.selector });
_addSpec({ _name: "OPContractsManager", _sel: OPContractsManager.implementations.selector });
// OPContractsManagerInterop
_addSpec({ _name: "OPContractsManagerInterop", _sel: _getSel("version()") });
_addSpec({ _name: "OPContractsManagerInterop", _sel: _getSel("superchainConfig()") });
_addSpec({ _name: "OPContractsManagerInterop", _sel: _getSel("protocolVersions()") });
_addSpec({ _name: "OPContractsManagerInterop", _sel: _getSel("latestRelease()") });
_addSpec({ _name: "OPContractsManagerInterop", _sel: _getSel("implementations(string,string)") });
_addSpec({ _name: "OPContractsManagerInterop", _sel: _getSel("l1ContractsRelease()") });
_addSpec({ _name: "OPContractsManagerInterop", _sel: _getSel("systemConfigs(uint256)") });
_addSpec({ _name: "OPContractsManagerInterop", _sel: _getSel("OUTPUT_VERSION()") });
_addSpec({ _name: "OPContractsManagerInterop", _sel: OPContractsManager.initialize.selector });
_addSpec({ _name: "OPContractsManagerInterop", _sel: OPContractsManager.deploy.selector });
_addSpec({ _name: "OPContractsManagerInterop", _sel: OPContractsManager.blueprints.selector });
_addSpec({ _name: "OPContractsManagerInterop", _sel: OPContractsManager.chainIdToBatchInboxAddress.selector });
_addSpec({ _name: "OPContractsManagerInterop", _sel: OPContractsManager.implementations.selector });
// DeputyGuardianModule
_addSpec({
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment