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 }