github.com/ethereum-optimism/optimism@v1.7.2/packages/contracts-bedrock/scripts/Deploy.s.sol (about)

     1  // SPDX-License-Identifier: MIT
     2  pragma solidity ^0.8.0;
     3  
     4  import { VmSafe } from "forge-std/Vm.sol";
     5  import { Script } from "forge-std/Script.sol";
     6  
     7  import { console2 as console } from "forge-std/console2.sol";
     8  import { stdJson } from "forge-std/StdJson.sol";
     9  
    10  import { Safe } from "safe-contracts/Safe.sol";
    11  import { SafeProxyFactory } from "safe-contracts/proxies/SafeProxyFactory.sol";
    12  import { Enum as SafeOps } from "safe-contracts/common/Enum.sol";
    13  
    14  import { Deployer } from "scripts/Deployer.sol";
    15  
    16  import { ProxyAdmin } from "src/universal/ProxyAdmin.sol";
    17  import { AddressManager } from "src/legacy/AddressManager.sol";
    18  import { Proxy } from "src/universal/Proxy.sol";
    19  import { L1StandardBridge } from "src/L1/L1StandardBridge.sol";
    20  import { StandardBridge } from "src/universal/StandardBridge.sol";
    21  import { OptimismPortal } from "src/L1/OptimismPortal.sol";
    22  import { OptimismPortal2 } from "src/L1/OptimismPortal2.sol";
    23  import { L1ChugSplashProxy } from "src/legacy/L1ChugSplashProxy.sol";
    24  import { ResolvedDelegateProxy } from "src/legacy/ResolvedDelegateProxy.sol";
    25  import { L1CrossDomainMessenger } from "src/L1/L1CrossDomainMessenger.sol";
    26  import { L2OutputOracle } from "src/L1/L2OutputOracle.sol";
    27  import { OptimismMintableERC20Factory } from "src/universal/OptimismMintableERC20Factory.sol";
    28  import { SuperchainConfig } from "src/L1/SuperchainConfig.sol";
    29  import { SystemConfig } from "src/L1/SystemConfig.sol";
    30  import { ResourceMetering } from "src/L1/ResourceMetering.sol";
    31  import { DataAvailabilityChallenge } from "src/L1/DataAvailabilityChallenge.sol";
    32  import { Constants } from "src/libraries/Constants.sol";
    33  import { DisputeGameFactory } from "src/dispute/DisputeGameFactory.sol";
    34  import { FaultDisputeGame } from "src/dispute/FaultDisputeGame.sol";
    35  import { PermissionedDisputeGame } from "src/dispute/PermissionedDisputeGame.sol";
    36  import { DelayedWETH } from "src/dispute/weth/DelayedWETH.sol";
    37  import { AnchorStateRegistry } from "src/dispute/AnchorStateRegistry.sol";
    38  import { PreimageOracle } from "src/cannon/PreimageOracle.sol";
    39  import { MIPS } from "src/cannon/MIPS.sol";
    40  import { L1ERC721Bridge } from "src/L1/L1ERC721Bridge.sol";
    41  import { ProtocolVersions, ProtocolVersion } from "src/L1/ProtocolVersions.sol";
    42  import { StorageSetter } from "src/universal/StorageSetter.sol";
    43  import { Predeploys } from "src/libraries/Predeploys.sol";
    44  import { Chains } from "scripts/Chains.sol";
    45  import { Config } from "scripts/Config.sol";
    46  
    47  import { IBigStepper } from "src/dispute/interfaces/IBigStepper.sol";
    48  import { IPreimageOracle } from "src/cannon/interfaces/IPreimageOracle.sol";
    49  import { AlphabetVM } from "test/mocks/AlphabetVM.sol";
    50  import "src/libraries/DisputeTypes.sol";
    51  import { ChainAssertions } from "scripts/ChainAssertions.sol";
    52  import { Types } from "scripts/Types.sol";
    53  import { LibStateDiff } from "scripts/libraries/LibStateDiff.sol";
    54  import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol";
    55  import { ForgeArtifacts } from "scripts/ForgeArtifacts.sol";
    56  
    57  /// @title Deploy
    58  /// @notice Script used to deploy a bedrock system. The entire system is deployed within the `run` function.
    59  ///         To add a new contract to the system, add a public function that deploys that individual contract.
    60  ///         Then add a call to that function inside of `run`. Be sure to call the `save` function after each
    61  ///         deployment so that hardhat-deploy style artifacts can be generated using a call to `sync()`.
    62  ///         The `CONTRACT_ADDRESSES_PATH` environment variable can be set to a path that contains a JSON file full of
    63  ///         contract name to address pairs. That enables this script to be much more flexible in the way it is used.
    64  ///         This contract must not have constructor logic because it is set into state using `etch`.
    65  contract Deploy is Deployer {
    66      using stdJson for string;
    67  
    68      /// @notice FaultDisputeGameParams is a struct that contains the parameters necessary to call
    69      ///         the function _setFaultGameImplementation. This struct exists because the EVM needs
    70      ///         to finally adopt PUSHN and get rid of stack too deep once and for all.
    71      ///         Someday we will look back and laugh about stack too deep, today is not that day.
    72      struct FaultDisputeGameParams {
    73          AnchorStateRegistry anchorStateRegistry;
    74          DelayedWETH weth;
    75          GameType gameType;
    76          Claim absolutePrestate;
    77          IBigStepper faultVm;
    78          uint256 maxGameDepth;
    79      }
    80  
    81      ////////////////////////////////////////////////////////////////
    82      //                        Modifiers                           //
    83      ////////////////////////////////////////////////////////////////
    84  
    85      /// @notice Modifier that wraps a function in broadcasting.
    86      modifier broadcast() {
    87          vm.startBroadcast(msg.sender);
    88          _;
    89          vm.stopBroadcast();
    90      }
    91  
    92      /// @notice Modifier that will only allow a function to be called on devnet.
    93      modifier onlyDevnet() {
    94          uint256 chainid = block.chainid;
    95          if (chainid == Chains.LocalDevnet || chainid == Chains.GethDevnet) {
    96              _;
    97          }
    98      }
    99  
   100      /// @notice Modifier that will only allow a function to be called on a public
   101      ///         testnet or devnet.
   102      modifier onlyTestnetOrDevnet() {
   103          uint256 chainid = block.chainid;
   104          if (
   105              chainid == Chains.Goerli || chainid == Chains.Sepolia || chainid == Chains.LocalDevnet
   106                  || chainid == Chains.GethDevnet
   107          ) {
   108              _;
   109          }
   110      }
   111  
   112      /// @notice Modifier that wraps a function with statediff recording.
   113      ///         The returned AccountAccess[] array is then written to
   114      ///         the `snapshots/state-diff/<name>.json` output file.
   115      modifier stateDiff() {
   116          vm.startStateDiffRecording();
   117          _;
   118          VmSafe.AccountAccess[] memory accesses = vm.stopAndReturnStateDiff();
   119          console.log("Writing %d state diff account accesses to snapshots/state-diff/%s.json", accesses.length, name());
   120          string memory json = LibStateDiff.encodeAccountAccesses(accesses);
   121          string memory statediffPath = string.concat(vm.projectRoot(), "/snapshots/state-diff/", name(), ".json");
   122          vm.writeJson({ json: json, path: statediffPath });
   123      }
   124  
   125      ////////////////////////////////////////////////////////////////
   126      //                        Accessors                           //
   127      ////////////////////////////////////////////////////////////////
   128  
   129      /// @inheritdoc Deployer
   130      function name() public pure override returns (string memory name_) {
   131          name_ = "Deploy";
   132      }
   133  
   134      /// @notice The create2 salt used for deployment of the contract implementations.
   135      ///         Using this helps to reduce config across networks as the implementation
   136      ///         addresses will be the same across networks when deployed with create2.
   137      function _implSalt() internal view returns (bytes32) {
   138          return keccak256(bytes(Config.implSalt()));
   139      }
   140  
   141      /// @notice Returns the proxy addresses. If a proxy is not found, it will have address(0).
   142      function _proxies() internal view returns (Types.ContractSet memory proxies_) {
   143          proxies_ = Types.ContractSet({
   144              L1CrossDomainMessenger: mustGetAddress("L1CrossDomainMessengerProxy"),
   145              L1StandardBridge: mustGetAddress("L1StandardBridgeProxy"),
   146              L2OutputOracle: mustGetAddress("L2OutputOracleProxy"),
   147              DisputeGameFactory: mustGetAddress("DisputeGameFactoryProxy"),
   148              DelayedWETH: mustGetAddress("DelayedWETHProxy"),
   149              AnchorStateRegistry: mustGetAddress("AnchorStateRegistryProxy"),
   150              OptimismMintableERC20Factory: mustGetAddress("OptimismMintableERC20FactoryProxy"),
   151              OptimismPortal: mustGetAddress("OptimismPortalProxy"),
   152              OptimismPortal2: mustGetAddress("OptimismPortalProxy"),
   153              SystemConfig: mustGetAddress("SystemConfigProxy"),
   154              L1ERC721Bridge: mustGetAddress("L1ERC721BridgeProxy"),
   155              ProtocolVersions: mustGetAddress("ProtocolVersionsProxy"),
   156              SuperchainConfig: mustGetAddress("SuperchainConfigProxy")
   157          });
   158      }
   159  
   160      /// @notice Returns the proxy addresses, not reverting if any are unset.
   161      function _proxiesUnstrict() internal view returns (Types.ContractSet memory proxies_) {
   162          proxies_ = Types.ContractSet({
   163              L1CrossDomainMessenger: getAddress("L1CrossDomainMessengerProxy"),
   164              L1StandardBridge: getAddress("L1StandardBridgeProxy"),
   165              L2OutputOracle: getAddress("L2OutputOracleProxy"),
   166              DisputeGameFactory: getAddress("DisputeGameFactoryProxy"),
   167              DelayedWETH: getAddress("DelayedWETHProxy"),
   168              AnchorStateRegistry: getAddress("AnchorStateRegistryProxy"),
   169              OptimismMintableERC20Factory: getAddress("OptimismMintableERC20FactoryProxy"),
   170              OptimismPortal: getAddress("OptimismPortalProxy"),
   171              OptimismPortal2: getAddress("OptimismPortalProxy"),
   172              SystemConfig: getAddress("SystemConfigProxy"),
   173              L1ERC721Bridge: getAddress("L1ERC721BridgeProxy"),
   174              ProtocolVersions: getAddress("ProtocolVersionsProxy"),
   175              SuperchainConfig: getAddress("SuperchainConfigProxy")
   176          });
   177      }
   178  
   179      ////////////////////////////////////////////////////////////////
   180      //            State Changing Helper Functions                 //
   181      ////////////////////////////////////////////////////////////////
   182  
   183      /// @notice Gets the address of the SafeProxyFactory and Safe singleton for use in deploying a new GnosisSafe.
   184      function _getSafeFactory() internal returns (SafeProxyFactory safeProxyFactory_, Safe safeSingleton_) {
   185          // These are the standard create2 deployed contracts. First we'll check if they are deployed,
   186          // if not we'll deploy new ones, though not at these addresses.
   187          address safeProxyFactory = 0xa6B71E26C5e0845f74c812102Ca7114b6a896AB2;
   188          address safeSingleton = 0xd9Db270c1B5E3Bd161E8c8503c55cEABeE709552;
   189  
   190          safeProxyFactory.code.length == 0
   191              ? safeProxyFactory_ = new SafeProxyFactory()
   192              : safeProxyFactory_ = SafeProxyFactory(safeProxyFactory);
   193  
   194          safeSingleton.code.length == 0 ? safeSingleton_ = new Safe() : safeSingleton_ = Safe(payable(safeSingleton));
   195  
   196          save("SafeProxyFactory", address(safeProxyFactory_));
   197          save("SafeSingleton", address(safeSingleton_));
   198      }
   199  
   200      /// @notice Make a call from the Safe contract to an arbitrary address with arbitrary data
   201      function _callViaSafe(address _target, bytes memory _data) internal {
   202          Safe safe = Safe(mustGetAddress("SystemOwnerSafe"));
   203  
   204          // This is the signature format used the caller is also the signer.
   205          bytes memory signature = abi.encodePacked(uint256(uint160(msg.sender)), bytes32(0), uint8(1));
   206  
   207          safe.execTransaction({
   208              to: _target,
   209              value: 0,
   210              data: _data,
   211              operation: SafeOps.Operation.Call,
   212              safeTxGas: 0,
   213              baseGas: 0,
   214              gasPrice: 0,
   215              gasToken: address(0),
   216              refundReceiver: payable(address(0)),
   217              signatures: signature
   218          });
   219      }
   220  
   221      /// @notice Call from the Safe contract to the Proxy Admin's upgrade and call method
   222      function _upgradeAndCallViaSafe(address _proxy, address _implementation, bytes memory _innerCallData) internal {
   223          address proxyAdmin = mustGetAddress("ProxyAdmin");
   224  
   225          bytes memory data =
   226              abi.encodeCall(ProxyAdmin.upgradeAndCall, (payable(_proxy), _implementation, _innerCallData));
   227  
   228          _callViaSafe({ _target: proxyAdmin, _data: data });
   229      }
   230  
   231      /// @notice Transfer ownership of the ProxyAdmin contract to the final system owner
   232      function transferProxyAdminOwnership() public broadcast {
   233          ProxyAdmin proxyAdmin = ProxyAdmin(mustGetAddress("ProxyAdmin"));
   234          address owner = proxyAdmin.owner();
   235          address safe = mustGetAddress("SystemOwnerSafe");
   236          if (owner != safe) {
   237              proxyAdmin.transferOwnership(safe);
   238              console.log("ProxyAdmin ownership transferred to Safe at: %s", safe);
   239          }
   240      }
   241  
   242      /// @notice Transfer ownership of a Proxy to the ProxyAdmin contract
   243      ///         This is expected to be used in conjusting with deployERC1967ProxyWithOwner after setup actions
   244      ///         have been performed on the proxy.
   245      /// @param _name The name of the proxy to transfer ownership of.
   246      function transferProxyToProxyAdmin(string memory _name) public broadcast {
   247          Proxy proxy = Proxy(mustGetAddress(_name));
   248          address proxyAdmin = mustGetAddress("ProxyAdmin");
   249          proxy.changeAdmin(proxyAdmin);
   250          console.log("Proxy %s ownership transferred to ProxyAdmin at: %s", _name, proxyAdmin);
   251      }
   252  
   253      ////////////////////////////////////////////////////////////////
   254      //                    SetUp and Run                           //
   255      ////////////////////////////////////////////////////////////////
   256  
   257      /// @notice Deploy all of the L1 contracts necessary for a full Superchain with a single Op Chain.
   258      function run() public {
   259          console.log("Deploying a fresh OP Stack including SuperchainConfig");
   260          _run();
   261      }
   262  
   263      function runWithStateDump() public {
   264          _run();
   265  
   266          vm.dumpState(Config.stateDumpPath(name()));
   267      }
   268  
   269      /// @notice Deploy all L1 contracts and write the state diff to a file.
   270      function runWithStateDiff() public stateDiff {
   271          _run();
   272      }
   273  
   274      /// @notice Internal function containing the deploy logic.
   275      function _run() internal {
   276          deploySafe();
   277          setupSuperchain();
   278          if (cfg.usePlasma()) {
   279              setupOpPlasma();
   280          }
   281          setupOpChain();
   282      }
   283  
   284      ////////////////////////////////////////////////////////////////
   285      //           High Level Deployment Functions                  //
   286      ////////////////////////////////////////////////////////////////
   287  
   288      /// @notice Deploy a full system with a new SuperchainConfig
   289      ///         The Superchain system has 2 singleton contracts which lie outside of an OP Chain:
   290      ///         1. The SuperchainConfig contract
   291      ///         2. The ProtocolVersions contract
   292      function setupSuperchain() public {
   293          console.log("Setting up Superchain");
   294  
   295          // Deploy a new ProxyAdmin and AddressManager
   296          // This proxy will be used on the SuperchainConfig and ProtocolVersions contracts, as well as the contracts
   297          // in the OP Chain system.
   298          deployAddressManager();
   299          deployProxyAdmin();
   300          transferProxyAdminOwnership();
   301  
   302          // Deploy the SuperchainConfigProxy
   303          deployERC1967Proxy("SuperchainConfigProxy");
   304          deploySuperchainConfig();
   305          initializeSuperchainConfig();
   306  
   307          // Deploy the ProtocolVersionsProxy
   308          deployERC1967Proxy("ProtocolVersionsProxy");
   309          deployProtocolVersions();
   310          initializeProtocolVersions();
   311      }
   312  
   313      /// @notice Deploy a new OP Chain, with an existing SuperchainConfig provided
   314      function setupOpChain() public {
   315          console.log("Deploying OP Chain");
   316  
   317          // Ensure that the requisite contracts are deployed
   318          mustGetAddress("SuperchainConfigProxy");
   319          mustGetAddress("SystemOwnerSafe");
   320          mustGetAddress("AddressManager");
   321          mustGetAddress("ProxyAdmin");
   322  
   323          deployProxies();
   324          deployImplementations();
   325          initializeImplementations();
   326  
   327          setAlphabetFaultGameImplementation({ _allowUpgrade: false });
   328          setCannonFaultGameImplementation({ _allowUpgrade: false });
   329          setPermissionedCannonFaultGameImplementation({ _allowUpgrade: false });
   330  
   331          transferDisputeGameFactoryOwnership();
   332          transferDelayedWETHOwnership();
   333      }
   334  
   335      /// @notice Deploy all of the proxies
   336      function deployProxies() public {
   337          console.log("Deploying proxies");
   338  
   339          deployERC1967Proxy("OptimismPortalProxy");
   340          deployERC1967Proxy("SystemConfigProxy");
   341          deployL1StandardBridgeProxy();
   342          deployL1CrossDomainMessengerProxy();
   343          deployERC1967Proxy("OptimismMintableERC20FactoryProxy");
   344          deployERC1967Proxy("L1ERC721BridgeProxy");
   345  
   346          // Both the DisputeGameFactory and L2OutputOracle proxies are deployed regardles of whether FPAC is enabled
   347          // to prevent a nastier refactor to the deploy scripts. In the future, the L2OutputOracle will be removed. If
   348          // fault proofs are not enabled, the DisputeGameFactory proxy will be unused.
   349          deployERC1967Proxy("DisputeGameFactoryProxy");
   350          deployERC1967Proxy("L2OutputOracleProxy");
   351          deployERC1967Proxy("DelayedWETHProxy");
   352          deployERC1967Proxy("AnchorStateRegistryProxy");
   353  
   354          transferAddressManagerOwnership(); // to the ProxyAdmin
   355      }
   356  
   357      /// @notice Deploy all of the implementations
   358      function deployImplementations() public {
   359          console.log("Deploying implementations");
   360          deployL1CrossDomainMessenger();
   361          deployOptimismMintableERC20Factory();
   362          deploySystemConfig();
   363          deployL1StandardBridge();
   364          deployL1ERC721Bridge();
   365          deployOptimismPortal();
   366          deployL2OutputOracle();
   367  
   368          // Fault proofs
   369          deployOptimismPortal2();
   370          deployDisputeGameFactory();
   371          deployDelayedWETH();
   372          deployPreimageOracle();
   373          deployMips();
   374          deployAnchorStateRegistry();
   375      }
   376  
   377      /// @notice Initialize all of the implementations
   378      function initializeImplementations() public {
   379          console.log("Initializing implementations");
   380          initializeSystemConfig();
   381          initializeL1StandardBridge();
   382          initializeL1ERC721Bridge();
   383          initializeOptimismMintableERC20Factory();
   384          initializeL1CrossDomainMessenger();
   385          initializeL2OutputOracle();
   386          initializeDisputeGameFactory();
   387          initializeDelayedWETH();
   388          initializeAnchorStateRegistry();
   389  
   390          // Selectively initialize either the original OptimismPortal or the new OptimismPortal2. Since this will upgrade
   391          // the proxy, we cannot initialize both. FPAC warning can be removed once we're done with the old OptimismPortal
   392          // contract.
   393          if (cfg.useFaultProofs()) {
   394              console.log("WARNING: FPAC is enabled. Initializing the OptimismPortal proxy with the OptimismPortal2.");
   395              initializeOptimismPortal2();
   396          } else {
   397              initializeOptimismPortal();
   398          }
   399      }
   400  
   401      /// @notice Add Plasma setup to the OP chain
   402      function setupOpPlasma() public {
   403          console.log("Deploying OP Plasma");
   404          deployDataAvailabilityChallengeProxy();
   405          deployDataAvailabilityChallenge();
   406          initializeDataAvailabilityChallenge();
   407      }
   408  
   409      ////////////////////////////////////////////////////////////////
   410      //              Non-Proxied Deployment Functions              //
   411      ////////////////////////////////////////////////////////////////
   412  
   413      /// @notice Deploy the Safe
   414      function deploySafe() public broadcast returns (address addr_) {
   415          console.log("Deploying Safe");
   416          (SafeProxyFactory safeProxyFactory, Safe safeSingleton) = _getSafeFactory();
   417  
   418          address[] memory signers = new address[](1);
   419          signers[0] = msg.sender;
   420  
   421          bytes memory initData = abi.encodeWithSelector(
   422              Safe.setup.selector, signers, 1, address(0), hex"", address(0), address(0), 0, address(0)
   423          );
   424          address safe = address(safeProxyFactory.createProxyWithNonce(address(safeSingleton), initData, block.timestamp));
   425  
   426          save("SystemOwnerSafe", address(safe));
   427          console.log("New SystemOwnerSafe deployed at %s", address(safe));
   428          addr_ = safe;
   429      }
   430  
   431      /// @notice Deploy the AddressManager
   432      function deployAddressManager() public broadcast returns (address addr_) {
   433          console.log("Deploying AddressManager");
   434          AddressManager manager = new AddressManager();
   435          require(manager.owner() == msg.sender);
   436  
   437          save("AddressManager", address(manager));
   438          console.log("AddressManager deployed at %s", address(manager));
   439          addr_ = address(manager);
   440      }
   441  
   442      /// @notice Deploy the ProxyAdmin
   443      function deployProxyAdmin() public broadcast returns (address addr_) {
   444          console.log("Deploying ProxyAdmin");
   445          ProxyAdmin admin = new ProxyAdmin({ _owner: msg.sender });
   446          require(admin.owner() == msg.sender);
   447  
   448          AddressManager addressManager = AddressManager(mustGetAddress("AddressManager"));
   449          if (admin.addressManager() != addressManager) {
   450              admin.setAddressManager(addressManager);
   451          }
   452  
   453          require(admin.addressManager() == addressManager);
   454  
   455          save("ProxyAdmin", address(admin));
   456          console.log("ProxyAdmin deployed at %s", address(admin));
   457          addr_ = address(admin);
   458      }
   459  
   460      /// @notice Deploy the StorageSetter contract, used for upgrades.
   461      function deployStorageSetter() public broadcast returns (address addr_) {
   462          console.log("Deploying StorageSetter");
   463          StorageSetter setter = new StorageSetter{ salt: _implSalt() }();
   464          console.log("StorageSetter deployed at: %s", address(setter));
   465          string memory version = setter.version();
   466          console.log("StorageSetter version: %s", version);
   467          addr_ = address(setter);
   468      }
   469  
   470      ////////////////////////////////////////////////////////////////
   471      //                Proxy Deployment Functions                  //
   472      ////////////////////////////////////////////////////////////////
   473  
   474      /// @notice Deploy the L1StandardBridgeProxy using a ChugSplashProxy
   475      function deployL1StandardBridgeProxy() public broadcast returns (address addr_) {
   476          console.log("Deploying proxy for L1StandardBridge");
   477          address proxyAdmin = mustGetAddress("ProxyAdmin");
   478          L1ChugSplashProxy proxy = new L1ChugSplashProxy(proxyAdmin);
   479  
   480          require(EIP1967Helper.getAdmin(address(proxy)) == proxyAdmin);
   481  
   482          save("L1StandardBridgeProxy", address(proxy));
   483          console.log("L1StandardBridgeProxy deployed at %s", address(proxy));
   484          addr_ = address(proxy);
   485      }
   486  
   487      /// @notice Deploy the L1CrossDomainMessengerProxy using a ResolvedDelegateProxy
   488      function deployL1CrossDomainMessengerProxy() public broadcast returns (address addr_) {
   489          console.log("Deploying proxy for L1CrossDomainMessenger");
   490          AddressManager addressManager = AddressManager(mustGetAddress("AddressManager"));
   491          ResolvedDelegateProxy proxy = new ResolvedDelegateProxy(addressManager, "OVM_L1CrossDomainMessenger");
   492  
   493          save("L1CrossDomainMessengerProxy", address(proxy));
   494          console.log("L1CrossDomainMessengerProxy deployed at %s", address(proxy));
   495  
   496          addr_ = address(proxy);
   497      }
   498  
   499      /// @notice Deploys an ERC1967Proxy contract with the ProxyAdmin as the owner.
   500      /// @param _name The name of the proxy contract to be deployed.
   501      /// @return addr_ The address of the deployed proxy contract.
   502      function deployERC1967Proxy(string memory _name) public returns (address addr_) {
   503          addr_ = deployERC1967ProxyWithOwner(_name, mustGetAddress("ProxyAdmin"));
   504      }
   505  
   506      /// @notice Deploys an ERC1967Proxy contract with a specified owner.
   507      /// @param _name The name of the proxy contract to be deployed.
   508      /// @param _proxyOwner The address of the owner of the proxy contract.
   509      /// @return addr_ The address of the deployed proxy contract.
   510      function deployERC1967ProxyWithOwner(
   511          string memory _name,
   512          address _proxyOwner
   513      )
   514          public
   515          broadcast
   516          returns (address addr_)
   517      {
   518          console.log(string.concat("Deploying ERC1967 proxy for ", _name));
   519          Proxy proxy = new Proxy({ _admin: _proxyOwner });
   520  
   521          require(EIP1967Helper.getAdmin(address(proxy)) == _proxyOwner);
   522  
   523          save(_name, address(proxy));
   524          console.log("   at %s", address(proxy));
   525          addr_ = address(proxy);
   526      }
   527  
   528      /// @notice Deploy the DataAvailabilityChallengeProxy
   529      function deployDataAvailabilityChallengeProxy() public broadcast returns (address addr_) {
   530          console.log("Deploying proxy for DataAvailabilityChallenge");
   531          address proxyAdmin = mustGetAddress("ProxyAdmin");
   532          Proxy proxy = new Proxy({ _admin: proxyAdmin });
   533  
   534          require(EIP1967Helper.getAdmin(address(proxy)) == proxyAdmin);
   535  
   536          save("DataAvailabilityChallengeProxy", address(proxy));
   537          console.log("DataAvailabilityChallengeProxy deployed at %s", address(proxy));
   538  
   539          addr_ = address(proxy);
   540      }
   541  
   542      ////////////////////////////////////////////////////////////////
   543      //             Implementation Deployment Functions            //
   544      ////////////////////////////////////////////////////////////////
   545  
   546      /// @notice Deploy the SuperchainConfig contract
   547      function deploySuperchainConfig() public broadcast {
   548          SuperchainConfig superchainConfig = new SuperchainConfig{ salt: _implSalt() }();
   549  
   550          require(superchainConfig.guardian() == address(0));
   551          bytes32 initialized = vm.load(address(superchainConfig), bytes32(0));
   552          require(initialized != 0);
   553  
   554          save("SuperchainConfig", address(superchainConfig));
   555          console.log("SuperchainConfig deployed at %s", address(superchainConfig));
   556      }
   557  
   558      /// @notice Deploy the L1CrossDomainMessenger
   559      function deployL1CrossDomainMessenger() public broadcast returns (address addr_) {
   560          console.log("Deploying L1CrossDomainMessenger implementation");
   561          L1CrossDomainMessenger messenger = new L1CrossDomainMessenger{ salt: _implSalt() }();
   562  
   563          save("L1CrossDomainMessenger", address(messenger));
   564          console.log("L1CrossDomainMessenger deployed at %s", address(messenger));
   565  
   566          // Override the `L1CrossDomainMessenger` contract to the deployed implementation. This is necessary
   567          // to check the `L1CrossDomainMessenger` implementation alongside dependent contracts, which
   568          // are always proxies.
   569          Types.ContractSet memory contracts = _proxiesUnstrict();
   570          contracts.L1CrossDomainMessenger = address(messenger);
   571          ChainAssertions.checkL1CrossDomainMessenger({ _contracts: contracts, _vm: vm, _isProxy: false });
   572  
   573          addr_ = address(messenger);
   574      }
   575  
   576      /// @notice Deploy the OptimismPortal
   577      function deployOptimismPortal() public broadcast returns (address addr_) {
   578          console.log("Deploying OptimismPortal implementation");
   579  
   580          OptimismPortal portal = new OptimismPortal{ salt: _implSalt() }();
   581  
   582          save("OptimismPortal", address(portal));
   583          console.log("OptimismPortal deployed at %s", address(portal));
   584  
   585          // Override the `OptimismPortal` contract to the deployed implementation. This is necessary
   586          // to check the `OptimismPortal` implementation alongside dependent contracts, which
   587          // are always proxies.
   588          Types.ContractSet memory contracts = _proxiesUnstrict();
   589          contracts.OptimismPortal = address(portal);
   590          ChainAssertions.checkOptimismPortal({ _contracts: contracts, _cfg: cfg, _isProxy: false });
   591  
   592          addr_ = address(portal);
   593      }
   594  
   595      /// @notice Deploy the OptimismPortal2
   596      function deployOptimismPortal2() public broadcast returns (address addr_) {
   597          console.log("Deploying OptimismPortal2 implementation");
   598  
   599          // Could also verify this inside DeployConfig but doing it here is a bit more reliable.
   600          require(
   601              uint32(cfg.respectedGameType()) == cfg.respectedGameType(), "Deploy: respectedGameType must fit into uint32"
   602          );
   603  
   604          OptimismPortal2 portal = new OptimismPortal2{ salt: _implSalt() }({
   605              _proofMaturityDelaySeconds: cfg.proofMaturityDelaySeconds(),
   606              _disputeGameFinalityDelaySeconds: cfg.disputeGameFinalityDelaySeconds(),
   607              _initialRespectedGameType: GameType.wrap(uint32(cfg.respectedGameType()))
   608          });
   609  
   610          save("OptimismPortal2", address(portal));
   611          console.log("OptimismPortal2 deployed at %s", address(portal));
   612  
   613          // Override the `OptimismPortal2` contract to the deployed implementation. This is necessary
   614          // to check the `OptimismPortal2` implementation alongside dependent contracts, which
   615          // are always proxies.
   616          Types.ContractSet memory contracts = _proxiesUnstrict();
   617          contracts.OptimismPortal2 = address(portal);
   618          ChainAssertions.checkOptimismPortal2({ _contracts: contracts, _cfg: cfg, _isProxy: false });
   619  
   620          addr_ = address(portal);
   621      }
   622  
   623      /// @notice Deploy the L2OutputOracle
   624      function deployL2OutputOracle() public broadcast returns (address addr_) {
   625          console.log("Deploying L2OutputOracle implementation");
   626          L2OutputOracle oracle = new L2OutputOracle{ salt: _implSalt() }();
   627  
   628          save("L2OutputOracle", address(oracle));
   629          console.log("L2OutputOracle deployed at %s", address(oracle));
   630  
   631          // Override the `L2OutputOracle` contract to the deployed implementation. This is necessary
   632          // to check the `L2OutputOracle` implementation alongside dependent contracts, which
   633          // are always proxies.
   634          Types.ContractSet memory contracts = _proxiesUnstrict();
   635          contracts.L2OutputOracle = address(oracle);
   636          ChainAssertions.checkL2OutputOracle({
   637              _contracts: contracts,
   638              _cfg: cfg,
   639              _l2OutputOracleStartingTimestamp: 0,
   640              _isProxy: false
   641          });
   642  
   643          addr_ = address(oracle);
   644      }
   645  
   646      /// @notice Deploy the OptimismMintableERC20Factory
   647      function deployOptimismMintableERC20Factory() public broadcast returns (address addr_) {
   648          console.log("Deploying OptimismMintableERC20Factory implementation");
   649          OptimismMintableERC20Factory factory = new OptimismMintableERC20Factory{ salt: _implSalt() }();
   650  
   651          save("OptimismMintableERC20Factory", address(factory));
   652          console.log("OptimismMintableERC20Factory deployed at %s", address(factory));
   653  
   654          // Override the `OptimismMintableERC20Factory` contract to the deployed implementation. This is necessary
   655          // to check the `OptimismMintableERC20Factory` implementation alongside dependent contracts, which
   656          // are always proxies.
   657          Types.ContractSet memory contracts = _proxiesUnstrict();
   658          contracts.OptimismMintableERC20Factory = address(factory);
   659          ChainAssertions.checkOptimismMintableERC20Factory({ _contracts: contracts, _isProxy: false });
   660  
   661          addr_ = address(factory);
   662      }
   663  
   664      /// @notice Deploy the DisputeGameFactory
   665      function deployDisputeGameFactory() public broadcast returns (address addr_) {
   666          console.log("Deploying DisputeGameFactory implementation");
   667          DisputeGameFactory factory = new DisputeGameFactory{ salt: _implSalt() }();
   668          save("DisputeGameFactory", address(factory));
   669          console.log("DisputeGameFactory deployed at %s", address(factory));
   670  
   671          // Override the `DisputeGameFactory` contract to the deployed implementation. This is necessary to check the
   672          // `DisputeGameFactory` implementation alongside dependent contracts, which are always proxies.
   673          Types.ContractSet memory contracts = _proxiesUnstrict();
   674          contracts.DisputeGameFactory = address(factory);
   675          ChainAssertions.checkDisputeGameFactory({ _contracts: contracts, _expectedOwner: address(0) });
   676  
   677          addr_ = address(factory);
   678      }
   679  
   680      function deployDelayedWETH() public broadcast returns (address addr_) {
   681          console.log("Deploying DelayedWETH implementation");
   682          DelayedWETH weth = new DelayedWETH{ salt: _implSalt() }(cfg.faultGameWithdrawalDelay());
   683          save("DelayedWETH", address(weth));
   684          console.log("DelayedWETH deployed at %s", address(weth));
   685  
   686          // Override the `DelayedWETH` contract to the deployed implementation. This is necessary
   687          // to check the `DelayedWETH` implementation alongside dependent contracts, which are
   688          // always proxies.
   689          Types.ContractSet memory contracts = _proxiesUnstrict();
   690          contracts.DelayedWETH = address(weth);
   691          ChainAssertions.checkDelayedWETH({
   692              _contracts: contracts,
   693              _cfg: cfg,
   694              _isProxy: false,
   695              _expectedOwner: address(0)
   696          });
   697  
   698          addr_ = address(weth);
   699      }
   700  
   701      /// @notice Deploy the ProtocolVersions
   702      function deployProtocolVersions() public broadcast returns (address addr_) {
   703          console.log("Deploying ProtocolVersions implementation");
   704          ProtocolVersions versions = new ProtocolVersions{ salt: _implSalt() }();
   705          save("ProtocolVersions", address(versions));
   706          console.log("ProtocolVersions deployed at %s", address(versions));
   707  
   708          // Override the `ProtocolVersions` contract to the deployed implementation. This is necessary
   709          // to check the `ProtocolVersions` implementation alongside dependent contracts, which
   710          // are always proxies.
   711          Types.ContractSet memory contracts = _proxiesUnstrict();
   712          contracts.ProtocolVersions = address(versions);
   713          ChainAssertions.checkProtocolVersions({ _contracts: contracts, _cfg: cfg, _isProxy: false });
   714  
   715          addr_ = address(versions);
   716      }
   717  
   718      /// @notice Deploy the PreimageOracle
   719      function deployPreimageOracle() public broadcast returns (address addr_) {
   720          console.log("Deploying PreimageOracle implementation");
   721          PreimageOracle preimageOracle = new PreimageOracle{ salt: _implSalt() }({
   722              _minProposalSize: cfg.preimageOracleMinProposalSize(),
   723              _challengePeriod: cfg.preimageOracleChallengePeriod()
   724          });
   725          save("PreimageOracle", address(preimageOracle));
   726          console.log("PreimageOracle deployed at %s", address(preimageOracle));
   727  
   728          addr_ = address(preimageOracle);
   729      }
   730  
   731      /// @notice Deploy Mips
   732      function deployMips() public broadcast returns (address addr_) {
   733          console.log("Deploying Mips implementation");
   734          MIPS mips = new MIPS{ salt: _implSalt() }(IPreimageOracle(mustGetAddress("PreimageOracle")));
   735          save("Mips", address(mips));
   736          console.log("MIPS deployed at %s", address(mips));
   737  
   738          addr_ = address(mips);
   739      }
   740  
   741      /// @notice Deploy the AnchorStateRegistry
   742      function deployAnchorStateRegistry() public broadcast returns (address addr_) {
   743          console.log("Deploying AnchorStateRegistry implementation");
   744          AnchorStateRegistry anchorStateRegistry =
   745              new AnchorStateRegistry{ salt: _implSalt() }(DisputeGameFactory(mustGetAddress("DisputeGameFactoryProxy")));
   746          save("AnchorStateRegistry", address(anchorStateRegistry));
   747          console.log("AnchorStateRegistry deployed at %s", address(anchorStateRegistry));
   748  
   749          addr_ = address(anchorStateRegistry);
   750      }
   751  
   752      /// @notice Deploy the SystemConfig
   753      function deploySystemConfig() public broadcast returns (address addr_) {
   754          console.log("Deploying SystemConfig implementation");
   755          SystemConfig config = new SystemConfig{ salt: _implSalt() }();
   756  
   757          save("SystemConfig", address(config));
   758          console.log("SystemConfig deployed at %s", address(config));
   759  
   760          // Override the `SystemConfig` contract to the deployed implementation. This is necessary
   761          // to check the `SystemConfig` implementation alongside dependent contracts, which
   762          // are always proxies.
   763          Types.ContractSet memory contracts = _proxiesUnstrict();
   764          contracts.SystemConfig = address(config);
   765          ChainAssertions.checkSystemConfig({ _contracts: contracts, _cfg: cfg, _isProxy: false });
   766  
   767          addr_ = address(config);
   768      }
   769  
   770      /// @notice Deploy the L1StandardBridge
   771      function deployL1StandardBridge() public broadcast returns (address addr_) {
   772          console.log("Deploying L1StandardBridge implementation");
   773  
   774          L1StandardBridge bridge = new L1StandardBridge{ salt: _implSalt() }();
   775  
   776          save("L1StandardBridge", address(bridge));
   777          console.log("L1StandardBridge deployed at %s", address(bridge));
   778  
   779          // Override the `L1StandardBridge` contract to the deployed implementation. This is necessary
   780          // to check the `L1StandardBridge` implementation alongside dependent contracts, which
   781          // are always proxies.
   782          Types.ContractSet memory contracts = _proxiesUnstrict();
   783          contracts.L1StandardBridge = address(bridge);
   784          ChainAssertions.checkL1StandardBridge({ _contracts: contracts, _isProxy: false });
   785  
   786          addr_ = address(bridge);
   787      }
   788  
   789      /// @notice Deploy the L1ERC721Bridge
   790      function deployL1ERC721Bridge() public broadcast returns (address addr_) {
   791          console.log("Deploying L1ERC721Bridge implementation");
   792          L1ERC721Bridge bridge = new L1ERC721Bridge{ salt: _implSalt() }();
   793  
   794          save("L1ERC721Bridge", address(bridge));
   795          console.log("L1ERC721Bridge deployed at %s", address(bridge));
   796  
   797          // Override the `L1ERC721Bridge` contract to the deployed implementation. This is necessary
   798          // to check the `L1ERC721Bridge` implementation alongside dependent contracts, which
   799          // are always proxies.
   800          Types.ContractSet memory contracts = _proxiesUnstrict();
   801          contracts.L1ERC721Bridge = address(bridge);
   802  
   803          ChainAssertions.checkL1ERC721Bridge({ _contracts: contracts, _isProxy: false });
   804  
   805          addr_ = address(bridge);
   806      }
   807  
   808      /// @notice Transfer ownership of the address manager to the ProxyAdmin
   809      function transferAddressManagerOwnership() public broadcast {
   810          console.log("Transferring AddressManager ownership to ProxyAdmin");
   811          AddressManager addressManager = AddressManager(mustGetAddress("AddressManager"));
   812          address owner = addressManager.owner();
   813          address proxyAdmin = mustGetAddress("ProxyAdmin");
   814          if (owner != proxyAdmin) {
   815              addressManager.transferOwnership(proxyAdmin);
   816              console.log("AddressManager ownership transferred to %s", proxyAdmin);
   817          }
   818  
   819          require(addressManager.owner() == proxyAdmin);
   820      }
   821  
   822      /// @notice Deploy the DataAvailabilityChallenge
   823      function deployDataAvailabilityChallenge() public broadcast returns (address addr_) {
   824          console.log("Deploying DataAvailabilityChallenge implementation");
   825          DataAvailabilityChallenge dac = new DataAvailabilityChallenge();
   826          save("DataAvailabilityChallenge", address(dac));
   827          console.log("DataAvailabilityChallenge deployed at %s", address(dac));
   828  
   829          addr_ = address(dac);
   830      }
   831  
   832      ////////////////////////////////////////////////////////////////
   833      //                    Initialize Functions                    //
   834      ////////////////////////////////////////////////////////////////
   835  
   836      /// @notice Initialize the SuperchainConfig
   837      function initializeSuperchainConfig() public broadcast {
   838          address payable superchainConfigProxy = mustGetAddress("SuperchainConfigProxy");
   839          address payable superchainConfig = mustGetAddress("SuperchainConfig");
   840          _upgradeAndCallViaSafe({
   841              _proxy: superchainConfigProxy,
   842              _implementation: superchainConfig,
   843              _innerCallData: abi.encodeCall(SuperchainConfig.initialize, (cfg.superchainConfigGuardian(), false))
   844          });
   845  
   846          ChainAssertions.checkSuperchainConfig({ _contracts: _proxiesUnstrict(), _cfg: cfg, _isPaused: false });
   847      }
   848  
   849      /// @notice Initialize the DisputeGameFactory
   850      function initializeDisputeGameFactory() public broadcast {
   851          console.log("Upgrading and initializing DisputeGameFactory proxy");
   852          address disputeGameFactoryProxy = mustGetAddress("DisputeGameFactoryProxy");
   853          address disputeGameFactory = mustGetAddress("DisputeGameFactory");
   854  
   855          _upgradeAndCallViaSafe({
   856              _proxy: payable(disputeGameFactoryProxy),
   857              _implementation: disputeGameFactory,
   858              _innerCallData: abi.encodeCall(DisputeGameFactory.initialize, (msg.sender))
   859          });
   860  
   861          string memory version = DisputeGameFactory(disputeGameFactoryProxy).version();
   862          console.log("DisputeGameFactory version: %s", version);
   863  
   864          ChainAssertions.checkDisputeGameFactory({ _contracts: _proxiesUnstrict(), _expectedOwner: msg.sender });
   865      }
   866  
   867      function initializeDelayedWETH() public broadcast {
   868          console.log("Upgrading and initializing DelayedWETH proxy");
   869          address delayedWETHProxy = mustGetAddress("DelayedWETHProxy");
   870          address delayedWETH = mustGetAddress("DelayedWETH");
   871          address superchainConfigProxy = mustGetAddress("SuperchainConfigProxy");
   872  
   873          _upgradeAndCallViaSafe({
   874              _proxy: payable(delayedWETHProxy),
   875              _implementation: delayedWETH,
   876              _innerCallData: abi.encodeCall(DelayedWETH.initialize, (msg.sender, SuperchainConfig(superchainConfigProxy)))
   877          });
   878  
   879          string memory version = DelayedWETH(payable(delayedWETHProxy)).version();
   880          console.log("DelayedWETH version: %s", version);
   881  
   882          ChainAssertions.checkDelayedWETH({
   883              _contracts: _proxiesUnstrict(),
   884              _cfg: cfg,
   885              _isProxy: true,
   886              _expectedOwner: msg.sender
   887          });
   888      }
   889  
   890      function initializeAnchorStateRegistry() public broadcast {
   891          console.log("Upgrading and initializing AnchorStateRegistry proxy");
   892          address anchorStateRegistryProxy = mustGetAddress("AnchorStateRegistryProxy");
   893          address anchorStateRegistry = mustGetAddress("AnchorStateRegistry");
   894  
   895          AnchorStateRegistry.StartingAnchorRoot[] memory roots = new AnchorStateRegistry.StartingAnchorRoot[](3);
   896          roots[0] = AnchorStateRegistry.StartingAnchorRoot({
   897              gameType: GameTypes.CANNON,
   898              outputRoot: OutputRoot({
   899                  root: Hash.wrap(cfg.faultGameGenesisOutputRoot()),
   900                  l2BlockNumber: cfg.faultGameGenesisBlock()
   901              })
   902          });
   903          roots[1] = AnchorStateRegistry.StartingAnchorRoot({
   904              gameType: GameTypes.PERMISSIONED_CANNON,
   905              outputRoot: OutputRoot({
   906                  root: Hash.wrap(cfg.faultGameGenesisOutputRoot()),
   907                  l2BlockNumber: cfg.faultGameGenesisBlock()
   908              })
   909          });
   910          roots[2] = AnchorStateRegistry.StartingAnchorRoot({
   911              gameType: GameTypes.ALPHABET,
   912              outputRoot: OutputRoot({
   913                  root: Hash.wrap(cfg.faultGameGenesisOutputRoot()),
   914                  l2BlockNumber: cfg.faultGameGenesisBlock()
   915              })
   916          });
   917  
   918          _upgradeAndCallViaSafe({
   919              _proxy: payable(anchorStateRegistryProxy),
   920              _implementation: anchorStateRegistry,
   921              _innerCallData: abi.encodeCall(AnchorStateRegistry.initialize, (roots))
   922          });
   923  
   924          string memory version = AnchorStateRegistry(payable(anchorStateRegistryProxy)).version();
   925          console.log("AnchorStateRegistry version: %s", version);
   926      }
   927  
   928      /// @notice Initialize the SystemConfig
   929      function initializeSystemConfig() public broadcast {
   930          console.log("Upgrading and initializing SystemConfig proxy");
   931          address systemConfigProxy = mustGetAddress("SystemConfigProxy");
   932          address systemConfig = mustGetAddress("SystemConfig");
   933  
   934          bytes32 batcherHash = bytes32(uint256(uint160(cfg.batchSenderAddress())));
   935  
   936          _upgradeAndCallViaSafe({
   937              _proxy: payable(systemConfigProxy),
   938              _implementation: systemConfig,
   939              _innerCallData: abi.encodeCall(
   940                  SystemConfig.initialize,
   941                  (
   942                      cfg.finalSystemOwner(),
   943                      cfg.gasPriceOracleOverhead(),
   944                      cfg.gasPriceOracleScalar(),
   945                      batcherHash,
   946                      uint64(cfg.l2GenesisBlockGasLimit()),
   947                      cfg.p2pSequencerAddress(),
   948                      Constants.DEFAULT_RESOURCE_CONFIG(),
   949                      cfg.batchInboxAddress(),
   950                      SystemConfig.Addresses({
   951                          l1CrossDomainMessenger: mustGetAddress("L1CrossDomainMessengerProxy"),
   952                          l1ERC721Bridge: mustGetAddress("L1ERC721BridgeProxy"),
   953                          l1StandardBridge: mustGetAddress("L1StandardBridgeProxy"),
   954                          l2OutputOracle: mustGetAddress("L2OutputOracleProxy"),
   955                          optimismPortal: mustGetAddress("OptimismPortalProxy"),
   956                          optimismMintableERC20Factory: mustGetAddress("OptimismMintableERC20FactoryProxy")
   957                      })
   958                  )
   959                  )
   960          });
   961  
   962          SystemConfig config = SystemConfig(systemConfigProxy);
   963          string memory version = config.version();
   964          console.log("SystemConfig version: %s", version);
   965  
   966          ChainAssertions.checkSystemConfig({ _contracts: _proxies(), _cfg: cfg, _isProxy: true });
   967      }
   968  
   969      /// @notice Initialize the L1StandardBridge
   970      function initializeL1StandardBridge() public broadcast {
   971          console.log("Upgrading and initializing L1StandardBridge proxy");
   972          ProxyAdmin proxyAdmin = ProxyAdmin(mustGetAddress("ProxyAdmin"));
   973          address l1StandardBridgeProxy = mustGetAddress("L1StandardBridgeProxy");
   974          address l1StandardBridge = mustGetAddress("L1StandardBridge");
   975          address l1CrossDomainMessengerProxy = mustGetAddress("L1CrossDomainMessengerProxy");
   976          address superchainConfigProxy = mustGetAddress("SuperchainConfigProxy");
   977  
   978          uint256 proxyType = uint256(proxyAdmin.proxyType(l1StandardBridgeProxy));
   979          if (proxyType != uint256(ProxyAdmin.ProxyType.CHUGSPLASH)) {
   980              _callViaSafe({
   981                  _target: address(proxyAdmin),
   982                  _data: abi.encodeCall(ProxyAdmin.setProxyType, (l1StandardBridgeProxy, ProxyAdmin.ProxyType.CHUGSPLASH))
   983              });
   984          }
   985          require(uint256(proxyAdmin.proxyType(l1StandardBridgeProxy)) == uint256(ProxyAdmin.ProxyType.CHUGSPLASH));
   986  
   987          _upgradeAndCallViaSafe({
   988              _proxy: payable(l1StandardBridgeProxy),
   989              _implementation: l1StandardBridge,
   990              _innerCallData: abi.encodeCall(
   991                  L1StandardBridge.initialize,
   992                  (L1CrossDomainMessenger(l1CrossDomainMessengerProxy), SuperchainConfig(superchainConfigProxy))
   993                  )
   994          });
   995  
   996          string memory version = L1StandardBridge(payable(l1StandardBridgeProxy)).version();
   997          console.log("L1StandardBridge version: %s", version);
   998  
   999          ChainAssertions.checkL1StandardBridge({ _contracts: _proxies(), _isProxy: true });
  1000      }
  1001  
  1002      /// @notice Initialize the L1ERC721Bridge
  1003      function initializeL1ERC721Bridge() public broadcast {
  1004          console.log("Upgrading and initializing L1ERC721Bridge proxy");
  1005          address l1ERC721BridgeProxy = mustGetAddress("L1ERC721BridgeProxy");
  1006          address l1ERC721Bridge = mustGetAddress("L1ERC721Bridge");
  1007          address l1CrossDomainMessengerProxy = mustGetAddress("L1CrossDomainMessengerProxy");
  1008          address superchainConfigProxy = mustGetAddress("SuperchainConfigProxy");
  1009  
  1010          _upgradeAndCallViaSafe({
  1011              _proxy: payable(l1ERC721BridgeProxy),
  1012              _implementation: l1ERC721Bridge,
  1013              _innerCallData: abi.encodeCall(
  1014                  L1ERC721Bridge.initialize,
  1015                  (L1CrossDomainMessenger(payable(l1CrossDomainMessengerProxy)), SuperchainConfig(superchainConfigProxy))
  1016                  )
  1017          });
  1018  
  1019          L1ERC721Bridge bridge = L1ERC721Bridge(l1ERC721BridgeProxy);
  1020          string memory version = bridge.version();
  1021          console.log("L1ERC721Bridge version: %s", version);
  1022  
  1023          ChainAssertions.checkL1ERC721Bridge({ _contracts: _proxies(), _isProxy: true });
  1024      }
  1025  
  1026      /// @notice Ininitialize the OptimismMintableERC20Factory
  1027      function initializeOptimismMintableERC20Factory() public broadcast {
  1028          console.log("Upgrading and initializing OptimismMintableERC20Factory proxy");
  1029          address optimismMintableERC20FactoryProxy = mustGetAddress("OptimismMintableERC20FactoryProxy");
  1030          address optimismMintableERC20Factory = mustGetAddress("OptimismMintableERC20Factory");
  1031          address l1StandardBridgeProxy = mustGetAddress("L1StandardBridgeProxy");
  1032  
  1033          _upgradeAndCallViaSafe({
  1034              _proxy: payable(optimismMintableERC20FactoryProxy),
  1035              _implementation: optimismMintableERC20Factory,
  1036              _innerCallData: abi.encodeCall(OptimismMintableERC20Factory.initialize, (l1StandardBridgeProxy))
  1037          });
  1038  
  1039          OptimismMintableERC20Factory factory = OptimismMintableERC20Factory(optimismMintableERC20FactoryProxy);
  1040          string memory version = factory.version();
  1041          console.log("OptimismMintableERC20Factory version: %s", version);
  1042  
  1043          ChainAssertions.checkOptimismMintableERC20Factory({ _contracts: _proxies(), _isProxy: true });
  1044      }
  1045  
  1046      /// @notice initializeL1CrossDomainMessenger
  1047      function initializeL1CrossDomainMessenger() public broadcast {
  1048          console.log("Upgrading and initializing L1CrossDomainMessenger proxy");
  1049          ProxyAdmin proxyAdmin = ProxyAdmin(mustGetAddress("ProxyAdmin"));
  1050          address l1CrossDomainMessengerProxy = mustGetAddress("L1CrossDomainMessengerProxy");
  1051          address l1CrossDomainMessenger = mustGetAddress("L1CrossDomainMessenger");
  1052          address superchainConfigProxy = mustGetAddress("SuperchainConfigProxy");
  1053          address optimismPortalProxy = mustGetAddress("OptimismPortalProxy");
  1054  
  1055          uint256 proxyType = uint256(proxyAdmin.proxyType(l1CrossDomainMessengerProxy));
  1056          if (proxyType != uint256(ProxyAdmin.ProxyType.RESOLVED)) {
  1057              _callViaSafe({
  1058                  _target: address(proxyAdmin),
  1059                  _data: abi.encodeCall(ProxyAdmin.setProxyType, (l1CrossDomainMessengerProxy, ProxyAdmin.ProxyType.RESOLVED))
  1060              });
  1061          }
  1062          require(uint256(proxyAdmin.proxyType(l1CrossDomainMessengerProxy)) == uint256(ProxyAdmin.ProxyType.RESOLVED));
  1063  
  1064          string memory contractName = "OVM_L1CrossDomainMessenger";
  1065          string memory implName = proxyAdmin.implementationName(l1CrossDomainMessenger);
  1066          if (keccak256(bytes(contractName)) != keccak256(bytes(implName))) {
  1067              _callViaSafe({
  1068                  _target: address(proxyAdmin),
  1069                  _data: abi.encodeCall(ProxyAdmin.setImplementationName, (l1CrossDomainMessengerProxy, contractName))
  1070              });
  1071          }
  1072          require(
  1073              keccak256(bytes(proxyAdmin.implementationName(l1CrossDomainMessengerProxy)))
  1074                  == keccak256(bytes(contractName))
  1075          );
  1076  
  1077          _upgradeAndCallViaSafe({
  1078              _proxy: payable(l1CrossDomainMessengerProxy),
  1079              _implementation: l1CrossDomainMessenger,
  1080              _innerCallData: abi.encodeCall(
  1081                  L1CrossDomainMessenger.initialize,
  1082                  (SuperchainConfig(superchainConfigProxy), OptimismPortal(payable(optimismPortalProxy)))
  1083                  )
  1084          });
  1085  
  1086          L1CrossDomainMessenger messenger = L1CrossDomainMessenger(l1CrossDomainMessengerProxy);
  1087          string memory version = messenger.version();
  1088          console.log("L1CrossDomainMessenger version: %s", version);
  1089  
  1090          ChainAssertions.checkL1CrossDomainMessenger({ _contracts: _proxies(), _vm: vm, _isProxy: true });
  1091      }
  1092  
  1093      /// @notice Initialize the L2OutputOracle
  1094      function initializeL2OutputOracle() public broadcast {
  1095          console.log("Upgrading and initializing L2OutputOracle proxy");
  1096          address l2OutputOracleProxy = mustGetAddress("L2OutputOracleProxy");
  1097          address l2OutputOracle = mustGetAddress("L2OutputOracle");
  1098  
  1099          _upgradeAndCallViaSafe({
  1100              _proxy: payable(l2OutputOracleProxy),
  1101              _implementation: l2OutputOracle,
  1102              _innerCallData: abi.encodeCall(
  1103                  L2OutputOracle.initialize,
  1104                  (
  1105                      cfg.l2OutputOracleSubmissionInterval(),
  1106                      cfg.l2BlockTime(),
  1107                      cfg.l2OutputOracleStartingBlockNumber(),
  1108                      cfg.l2OutputOracleStartingTimestamp(),
  1109                      cfg.l2OutputOracleProposer(),
  1110                      cfg.l2OutputOracleChallenger(),
  1111                      cfg.finalizationPeriodSeconds()
  1112                  )
  1113                  )
  1114          });
  1115  
  1116          L2OutputOracle oracle = L2OutputOracle(l2OutputOracleProxy);
  1117          string memory version = oracle.version();
  1118          console.log("L2OutputOracle version: %s", version);
  1119  
  1120          ChainAssertions.checkL2OutputOracle({
  1121              _contracts: _proxies(),
  1122              _cfg: cfg,
  1123              _l2OutputOracleStartingTimestamp: cfg.l2OutputOracleStartingTimestamp(),
  1124              _isProxy: true
  1125          });
  1126      }
  1127  
  1128      /// @notice Initialize the OptimismPortal
  1129      function initializeOptimismPortal() public broadcast {
  1130          console.log("Upgrading and initializing OptimismPortal proxy");
  1131          address optimismPortalProxy = mustGetAddress("OptimismPortalProxy");
  1132          address optimismPortal = mustGetAddress("OptimismPortal");
  1133          address l2OutputOracleProxy = mustGetAddress("L2OutputOracleProxy");
  1134          address systemConfigProxy = mustGetAddress("SystemConfigProxy");
  1135          address superchainConfigProxy = mustGetAddress("SuperchainConfigProxy");
  1136  
  1137          _upgradeAndCallViaSafe({
  1138              _proxy: payable(optimismPortalProxy),
  1139              _implementation: optimismPortal,
  1140              _innerCallData: abi.encodeCall(
  1141                  OptimismPortal.initialize,
  1142                  (
  1143                      L2OutputOracle(l2OutputOracleProxy),
  1144                      SystemConfig(systemConfigProxy),
  1145                      SuperchainConfig(superchainConfigProxy)
  1146                  )
  1147                  )
  1148          });
  1149  
  1150          OptimismPortal portal = OptimismPortal(payable(optimismPortalProxy));
  1151          string memory version = portal.version();
  1152          console.log("OptimismPortal version: %s", version);
  1153  
  1154          ChainAssertions.checkOptimismPortal({ _contracts: _proxies(), _cfg: cfg, _isProxy: true });
  1155      }
  1156  
  1157      /// @notice Initialize the OptimismPortal2
  1158      function initializeOptimismPortal2() public broadcast {
  1159          console.log("Upgrading and initializing OptimismPortal2 proxy");
  1160          address optimismPortalProxy = mustGetAddress("OptimismPortalProxy");
  1161          address optimismPortal2 = mustGetAddress("OptimismPortal2");
  1162          address disputeGameFactoryProxy = mustGetAddress("DisputeGameFactoryProxy");
  1163          address systemConfigProxy = mustGetAddress("SystemConfigProxy");
  1164          address superchainConfigProxy = mustGetAddress("SuperchainConfigProxy");
  1165  
  1166          _upgradeAndCallViaSafe({
  1167              _proxy: payable(optimismPortalProxy),
  1168              _implementation: optimismPortal2,
  1169              _innerCallData: abi.encodeCall(
  1170                  OptimismPortal2.initialize,
  1171                  (
  1172                      DisputeGameFactory(disputeGameFactoryProxy),
  1173                      SystemConfig(systemConfigProxy),
  1174                      SuperchainConfig(superchainConfigProxy)
  1175                  )
  1176                  )
  1177          });
  1178  
  1179          OptimismPortal2 portal = OptimismPortal2(payable(optimismPortalProxy));
  1180          string memory version = portal.version();
  1181          console.log("OptimismPortal2 version: %s", version);
  1182  
  1183          ChainAssertions.checkOptimismPortal2({ _contracts: _proxies(), _cfg: cfg, _isProxy: true });
  1184      }
  1185  
  1186      function initializeProtocolVersions() public broadcast {
  1187          console.log("Upgrading and initializing ProtocolVersions proxy");
  1188          address protocolVersionsProxy = mustGetAddress("ProtocolVersionsProxy");
  1189          address protocolVersions = mustGetAddress("ProtocolVersions");
  1190  
  1191          address finalSystemOwner = cfg.finalSystemOwner();
  1192          uint256 requiredProtocolVersion = cfg.requiredProtocolVersion();
  1193          uint256 recommendedProtocolVersion = cfg.recommendedProtocolVersion();
  1194  
  1195          _upgradeAndCallViaSafe({
  1196              _proxy: payable(protocolVersionsProxy),
  1197              _implementation: protocolVersions,
  1198              _innerCallData: abi.encodeCall(
  1199                  ProtocolVersions.initialize,
  1200                  (
  1201                      finalSystemOwner,
  1202                      ProtocolVersion.wrap(requiredProtocolVersion),
  1203                      ProtocolVersion.wrap(recommendedProtocolVersion)
  1204                  )
  1205                  )
  1206          });
  1207  
  1208          ProtocolVersions versions = ProtocolVersions(protocolVersionsProxy);
  1209          string memory version = versions.version();
  1210          console.log("ProtocolVersions version: %s", version);
  1211  
  1212          ChainAssertions.checkProtocolVersions({ _contracts: _proxiesUnstrict(), _cfg: cfg, _isProxy: true });
  1213      }
  1214  
  1215      /// @notice Transfer ownership of the DisputeGameFactory contract to the final system owner
  1216      function transferDisputeGameFactoryOwnership() public broadcast {
  1217          console.log("Transferring DisputeGameFactory ownership to Safe");
  1218          DisputeGameFactory disputeGameFactory = DisputeGameFactory(mustGetAddress("DisputeGameFactoryProxy"));
  1219          address owner = disputeGameFactory.owner();
  1220  
  1221          address safe = mustGetAddress("SystemOwnerSafe");
  1222          if (owner != safe) {
  1223              disputeGameFactory.transferOwnership(safe);
  1224              console.log("DisputeGameFactory ownership transferred to Safe at: %s", safe);
  1225          }
  1226          ChainAssertions.checkDisputeGameFactory({ _contracts: _proxies(), _expectedOwner: safe });
  1227      }
  1228  
  1229      /// @notice Transfer ownership of the DelayedWETH contract to the final system owner
  1230      function transferDelayedWETHOwnership() public broadcast {
  1231          console.log("Transferring DelayedWETH ownership to Safe");
  1232          DelayedWETH weth = DelayedWETH(mustGetAddress("DelayedWETHProxy"));
  1233          address owner = weth.owner();
  1234  
  1235          address safe = mustGetAddress("SystemOwnerSafe");
  1236          if (owner != safe) {
  1237              weth.transferOwnership(safe);
  1238              console.log("DelayedWETH ownership transferred to Safe at: %s", safe);
  1239          }
  1240          ChainAssertions.checkDelayedWETH({ _contracts: _proxies(), _cfg: cfg, _isProxy: true, _expectedOwner: safe });
  1241      }
  1242  
  1243      /// @notice Loads the mips absolute prestate from the prestate-proof for devnets otherwise
  1244      ///         from the config.
  1245      function loadMipsAbsolutePrestate() internal returns (Claim mipsAbsolutePrestate_) {
  1246          if (block.chainid == Chains.LocalDevnet || block.chainid == Chains.GethDevnet) {
  1247              // Fetch the absolute prestate dump
  1248              string memory filePath = string.concat(vm.projectRoot(), "/../../op-program/bin/prestate-proof.json");
  1249              string[] memory commands = new string[](3);
  1250              commands[0] = "bash";
  1251              commands[1] = "-c";
  1252              commands[2] = string.concat("[[ -f ", filePath, " ]] && echo \"present\"");
  1253              if (vm.ffi(commands).length == 0) {
  1254                  revert("Cannon prestate dump not found, generate it with `make cannon-prestate` in the monorepo root.");
  1255              }
  1256              commands[2] = string.concat("cat ", filePath, " | jq -r .pre");
  1257              mipsAbsolutePrestate_ = Claim.wrap(abi.decode(vm.ffi(commands), (bytes32)));
  1258              console.log(
  1259                  "[Cannon Dispute Game] Using devnet MIPS Absolute prestate: %s",
  1260                  vm.toString(Claim.unwrap(mipsAbsolutePrestate_))
  1261              );
  1262          } else {
  1263              console.log(
  1264                  "[Cannon Dispute Game] Using absolute prestate from config: %x", cfg.faultGameAbsolutePrestate()
  1265              );
  1266              mipsAbsolutePrestate_ = Claim.wrap(bytes32(cfg.faultGameAbsolutePrestate()));
  1267          }
  1268      }
  1269  
  1270      /// @notice Sets the implementation for the `CANNON` game type in the `DisputeGameFactory`
  1271      function setCannonFaultGameImplementation(bool _allowUpgrade) public broadcast {
  1272          console.log("Setting Cannon FaultDisputeGame implementation");
  1273          DisputeGameFactory factory = DisputeGameFactory(mustGetAddress("DisputeGameFactoryProxy"));
  1274          DelayedWETH weth = DelayedWETH(mustGetAddress("DelayedWETHProxy"));
  1275  
  1276          // Set the Cannon FaultDisputeGame implementation in the factory.
  1277          _setFaultGameImplementation({
  1278              _factory: factory,
  1279              _allowUpgrade: _allowUpgrade,
  1280              _params: FaultDisputeGameParams({
  1281                  anchorStateRegistry: AnchorStateRegistry(mustGetAddress("AnchorStateRegistryProxy")),
  1282                  weth: weth,
  1283                  gameType: GameTypes.CANNON,
  1284                  absolutePrestate: loadMipsAbsolutePrestate(),
  1285                  faultVm: IBigStepper(mustGetAddress("Mips")),
  1286                  maxGameDepth: cfg.faultGameMaxDepth()
  1287              })
  1288          });
  1289      }
  1290  
  1291      /// @notice Sets the implementation for the `PERMISSIONED_CANNON` game type in the `DisputeGameFactory`
  1292      function setPermissionedCannonFaultGameImplementation(bool _allowUpgrade) public broadcast {
  1293          console.log("Setting Cannon PermissionedDisputeGame implementation");
  1294          DisputeGameFactory factory = DisputeGameFactory(mustGetAddress("DisputeGameFactoryProxy"));
  1295          DelayedWETH weth = DelayedWETH(mustGetAddress("DelayedWETHProxy"));
  1296  
  1297          // Set the Cannon FaultDisputeGame implementation in the factory.
  1298          _setFaultGameImplementation({
  1299              _factory: factory,
  1300              _allowUpgrade: _allowUpgrade,
  1301              _params: FaultDisputeGameParams({
  1302                  anchorStateRegistry: AnchorStateRegistry(mustGetAddress("AnchorStateRegistryProxy")),
  1303                  weth: weth,
  1304                  gameType: GameTypes.PERMISSIONED_CANNON,
  1305                  absolutePrestate: loadMipsAbsolutePrestate(),
  1306                  faultVm: IBigStepper(mustGetAddress("Mips")),
  1307                  maxGameDepth: cfg.faultGameMaxDepth()
  1308              })
  1309          });
  1310      }
  1311  
  1312      /// @notice Sets the implementation for the `ALPHABET` game type in the `DisputeGameFactory`
  1313      function setAlphabetFaultGameImplementation(bool _allowUpgrade) public onlyDevnet broadcast {
  1314          console.log("Setting Alphabet FaultDisputeGame implementation");
  1315          DisputeGameFactory factory = DisputeGameFactory(mustGetAddress("DisputeGameFactoryProxy"));
  1316          DelayedWETH weth = DelayedWETH(mustGetAddress("DelayedWETHProxy"));
  1317  
  1318          Claim outputAbsolutePrestate = Claim.wrap(bytes32(cfg.faultGameAbsolutePrestate()));
  1319          _setFaultGameImplementation({
  1320              _factory: factory,
  1321              _allowUpgrade: _allowUpgrade,
  1322              _params: FaultDisputeGameParams({
  1323                  anchorStateRegistry: AnchorStateRegistry(mustGetAddress("AnchorStateRegistryProxy")),
  1324                  weth: weth,
  1325                  gameType: GameTypes.ALPHABET,
  1326                  absolutePrestate: outputAbsolutePrestate,
  1327                  faultVm: IBigStepper(new AlphabetVM(outputAbsolutePrestate, PreimageOracle(mustGetAddress("PreimageOracle")))),
  1328                  // The max depth for the alphabet trace is always 3. Add 1 because split depth is fully inclusive.
  1329                  maxGameDepth: cfg.faultGameSplitDepth() + 3 + 1
  1330              })
  1331          });
  1332      }
  1333  
  1334      /// @notice Sets the implementation for the given fault game type in the `DisputeGameFactory`.
  1335      function _setFaultGameImplementation(
  1336          DisputeGameFactory _factory,
  1337          bool _allowUpgrade,
  1338          FaultDisputeGameParams memory _params
  1339      )
  1340          internal
  1341      {
  1342          if (address(_factory.gameImpls(_params.gameType)) != address(0) && !_allowUpgrade) {
  1343              console.log(
  1344                  "[WARN] DisputeGameFactoryProxy: `FaultDisputeGame` implementation already set for game type: %s",
  1345                  vm.toString(GameType.unwrap(_params.gameType))
  1346              );
  1347              return;
  1348          }
  1349  
  1350          uint32 rawGameType = GameType.unwrap(_params.gameType);
  1351          if (rawGameType != GameTypes.PERMISSIONED_CANNON.raw()) {
  1352              _factory.setImplementation(
  1353                  _params.gameType,
  1354                  new FaultDisputeGame({
  1355                      _gameType: _params.gameType,
  1356                      _absolutePrestate: _params.absolutePrestate,
  1357                      _maxGameDepth: _params.maxGameDepth,
  1358                      _splitDepth: cfg.faultGameSplitDepth(),
  1359                      _gameDuration: Duration.wrap(uint64(cfg.faultGameMaxDuration())),
  1360                      _vm: _params.faultVm,
  1361                      _weth: _params.weth,
  1362                      _anchorStateRegistry: _params.anchorStateRegistry,
  1363                      _l2ChainId: cfg.l2ChainID()
  1364                  })
  1365              );
  1366          } else {
  1367              _factory.setImplementation(
  1368                  _params.gameType,
  1369                  new PermissionedDisputeGame({
  1370                      _gameType: _params.gameType,
  1371                      _absolutePrestate: _params.absolutePrestate,
  1372                      _maxGameDepth: _params.maxGameDepth,
  1373                      _splitDepth: cfg.faultGameSplitDepth(),
  1374                      _gameDuration: Duration.wrap(uint64(cfg.faultGameMaxDuration())),
  1375                      _vm: _params.faultVm,
  1376                      _weth: _params.weth,
  1377                      _anchorStateRegistry: _params.anchorStateRegistry,
  1378                      _l2ChainId: cfg.l2ChainID(),
  1379                      _proposer: cfg.l2OutputOracleProposer(),
  1380                      _challenger: cfg.l2OutputOracleChallenger()
  1381                  })
  1382              );
  1383          }
  1384  
  1385          string memory gameTypeString;
  1386          if (rawGameType == GameTypes.CANNON.raw()) {
  1387              gameTypeString = "Cannon";
  1388          } else if (rawGameType == GameTypes.PERMISSIONED_CANNON.raw()) {
  1389              gameTypeString = "PermissionedCannon";
  1390          } else if (rawGameType == GameTypes.ALPHABET.raw()) {
  1391              gameTypeString = "Alphabet";
  1392          } else {
  1393              gameTypeString = "Unknown";
  1394          }
  1395  
  1396          console.log(
  1397              "DisputeGameFactoryProxy: set `FaultDisputeGame` implementation (Backend: %s | GameType: %s)",
  1398              gameTypeString,
  1399              vm.toString(rawGameType)
  1400          );
  1401      }
  1402  
  1403      /// @notice Initialize the DataAvailabilityChallenge
  1404      function initializeDataAvailabilityChallenge() public broadcast {
  1405          console.log("Upgrading and initializing DataAvailabilityChallenge proxy");
  1406          address dataAvailabilityChallengeProxy = mustGetAddress("DataAvailabilityChallengeProxy");
  1407          address dataAvailabilityChallenge = mustGetAddress("DataAvailabilityChallenge");
  1408  
  1409          address finalSystemOwner = cfg.finalSystemOwner();
  1410          uint256 daChallengeWindow = cfg.daChallengeWindow();
  1411          uint256 daResolveWindow = cfg.daResolveWindow();
  1412          uint256 daBondSize = cfg.daBondSize();
  1413          uint256 daResolverRefundPercentage = cfg.daResolverRefundPercentage();
  1414  
  1415          _upgradeAndCallViaSafe({
  1416              _proxy: payable(dataAvailabilityChallengeProxy),
  1417              _implementation: dataAvailabilityChallenge,
  1418              _innerCallData: abi.encodeCall(
  1419                  DataAvailabilityChallenge.initialize,
  1420                  (finalSystemOwner, daChallengeWindow, daResolveWindow, daBondSize, daResolverRefundPercentage)
  1421                  )
  1422          });
  1423  
  1424          DataAvailabilityChallenge dac = DataAvailabilityChallenge(payable(dataAvailabilityChallengeProxy));
  1425          string memory version = dac.version();
  1426          console.log("DataAvailabilityChallenge version: %s", version);
  1427  
  1428          require(dac.owner() == finalSystemOwner);
  1429          require(dac.challengeWindow() == daChallengeWindow);
  1430          require(dac.resolveWindow() == daResolveWindow);
  1431          require(dac.bondSize() == daBondSize);
  1432          require(dac.resolverRefundPercentage() == daResolverRefundPercentage);
  1433      }
  1434  }