Commit e9e203ae authored by Maurelian's avatar Maurelian Committed by GitHub

Add deployImplementations to ForkLive flow (#13573)

* Add deployImplementations to ForkLive flow

* feat: remove legacy code

* feat: Add comments

* fix comment

* feat: Compatibility with standalone Artifacts

* feat: use etchLabelAndAllowCheatcodes

* feat: more readable ForkLive

* refactor deploy and forklive flow

* fix checks

* feat: Remove the _suffix arg from deployImpls

* feat: Allow overwriting a saved deployment (logs a warning)

* feat: update comment

* feat: Save the impls we need to save

* fix comment

* feat: replace mustGetAddress(Impl) with EIP1967 helper

* fix: impl retrieval in l1xDM

* fix: impl retrieval in l1xDM

* feat: restore import

* lint

* delete outdated comment
parent 7964731d
...@@ -158,8 +158,10 @@ contract Artifacts { ...@@ -158,8 +158,10 @@ contract Artifacts {
if (bytes(_name).length == 0) { if (bytes(_name).length == 0) {
revert InvalidDeployment("EmptyName"); revert InvalidDeployment("EmptyName");
} }
if (bytes(_namedDeployments[_name].name).length > 0) { Deployment memory existing = _namedDeployments[_name];
revert InvalidDeployment("AlreadyExists"); if (bytes(existing.name).length > 0) {
console.log("Warning: Deployment already exists for %s.", _name);
console.log("Overwriting %s with %s", existing.addr, _deployed);
} }
Deployment memory deployment = Deployment({ name: _name, addr: payable(_deployed) }); Deployment memory deployment = Deployment({ name: _name, addr: payable(_deployed) });
......
...@@ -275,10 +275,12 @@ contract Deploy is Deployer { ...@@ -275,10 +275,12 @@ contract Deploy is Deployer {
} }
/// @notice Deploy all of the implementations /// @notice Deploy all of the implementations
/// @param _isInterop Whether to use interop
function deployImplementations(bool _isInterop) public { function deployImplementations(bool _isInterop) public {
require(_isInterop == cfg.useInterop(), "Deploy: Interop setting mismatch."); require(_isInterop == cfg.useInterop(), "Deploy: Interop setting mismatch.");
console.log("Deploying implementations"); console.log("Deploying implementations");
DeployImplementations di = new DeployImplementations(); DeployImplementations di = new DeployImplementations();
(DeployImplementationsInput dii, DeployImplementationsOutput dio) = di.etchIOContracts(); (DeployImplementationsInput dii, DeployImplementationsOutput dio) = di.etchIOContracts();
...@@ -302,21 +304,30 @@ contract Deploy is Deployer { ...@@ -302,21 +304,30 @@ contract Deploy is Deployer {
} }
di.run(dii, dio); di.run(dii, dio);
artifacts.save("L1CrossDomainMessengerImpl", address(dio.l1CrossDomainMessengerImpl())); // Save the implementation addresses which are needed outside of this function or script.
artifacts.save("OptimismMintableERC20FactoryImpl", address(dio.optimismMintableERC20FactoryImpl())); // When called in a fork test, this will overwrite the existing implementations.
artifacts.save("SystemConfigImpl", address(dio.systemConfigImpl()));
artifacts.save("L1StandardBridgeImpl", address(dio.l1StandardBridgeImpl()));
artifacts.save("L1ERC721BridgeImpl", address(dio.l1ERC721BridgeImpl()));
// Fault proofs
artifacts.save("OptimismPortal2Impl", address(dio.optimismPortalImpl()));
artifacts.save("DisputeGameFactoryImpl", address(dio.disputeGameFactoryImpl()));
artifacts.save("DelayedWETHImpl", address(dio.delayedWETHImpl()));
artifacts.save("PreimageOracleSingleton", address(dio.preimageOracleSingleton()));
artifacts.save("MipsSingleton", address(dio.mipsSingleton())); artifacts.save("MipsSingleton", address(dio.mipsSingleton()));
artifacts.save("OPContractsManager", address(dio.opcm())); artifacts.save("OPContractsManager", address(dio.opcm()));
artifacts.save("DelayedWETHImpl", address(dio.delayedWETHImpl()));
// Get a contract set from the implementation addresses which were just deployed.
Types.ContractSet memory contracts = Types.ContractSet({
L1CrossDomainMessenger: address(dio.l1CrossDomainMessengerImpl()),
L1StandardBridge: address(dio.l1StandardBridgeImpl()),
L2OutputOracle: address(0),
DisputeGameFactory: address(dio.disputeGameFactoryImpl()),
DelayedWETH: address(dio.delayedWETHImpl()),
PermissionedDelayedWETH: address(dio.delayedWETHImpl()),
AnchorStateRegistry: address(0),
OptimismMintableERC20Factory: address(dio.optimismMintableERC20FactoryImpl()),
OptimismPortal: address(dio.optimismPortalImpl()),
SystemConfig: address(dio.systemConfigImpl()),
L1ERC721Bridge: address(dio.l1ERC721BridgeImpl()),
// We didn't deploy new versions of these in this function, so just read the existing ones.
ProtocolVersions: artifacts.mustGetAddress("ProtocolVersionsImpl"),
SuperchainConfig: artifacts.mustGetAddress("SuperchainConfigImpl")
});
Types.ContractSet memory contracts = _impls();
ChainAssertions.checkL1CrossDomainMessenger({ _contracts: contracts, _vm: vm, _isProxy: false }); ChainAssertions.checkL1CrossDomainMessenger({ _contracts: contracts, _vm: vm, _isProxy: false });
ChainAssertions.checkL1StandardBridge({ _contracts: contracts, _isProxy: false }); ChainAssertions.checkL1StandardBridge({ _contracts: contracts, _isProxy: false });
ChainAssertions.checkL1ERC721Bridge({ _contracts: contracts, _isProxy: false }); ChainAssertions.checkL1ERC721Bridge({ _contracts: contracts, _isProxy: false });
...@@ -339,8 +350,8 @@ contract Deploy is Deployer { ...@@ -339,8 +350,8 @@ contract Deploy is Deployer {
}); });
ChainAssertions.checkOPContractsManager({ ChainAssertions.checkOPContractsManager({
_contracts: contracts, _contracts: contracts,
_opcm: OPContractsManager(artifacts.mustGetAddress("OPContractsManager")), _opcm: OPContractsManager(address(dio.opcm())),
_mips: IMIPS(artifacts.mustGetAddress("MipsSingleton")) _mips: IMIPS(address(dio.mipsSingleton()))
}); });
if (_isInterop) { if (_isInterop) {
ChainAssertions.checkSystemConfigInterop({ _contracts: contracts, _cfg: cfg, _isProxy: false }); ChainAssertions.checkSystemConfigInterop({ _contracts: contracts, _cfg: cfg, _isProxy: false });
......
...@@ -29,7 +29,7 @@ contract L1CrossDomainMessenger_Test is CommonTest { ...@@ -29,7 +29,7 @@ contract L1CrossDomainMessenger_Test is CommonTest {
/// @notice Marked virtual to be overridden in /// @notice Marked virtual to be overridden in
/// test/kontrol/deployment/DeploymentSummary.t.sol /// test/kontrol/deployment/DeploymentSummary.t.sol
function test_constructor_succeeds() external virtual { function test_constructor_succeeds() external virtual {
IL1CrossDomainMessenger impl = IL1CrossDomainMessenger(artifacts.mustGetAddress("L1CrossDomainMessengerImpl")); IL1CrossDomainMessenger impl = IL1CrossDomainMessenger(addressManager.getAddress("OVM_L1CrossDomainMessenger"));
assertEq(address(impl.superchainConfig()), address(0)); assertEq(address(impl.superchainConfig()), address(0));
assertEq(address(impl.PORTAL()), address(0)); assertEq(address(impl.PORTAL()), address(0));
assertEq(address(impl.portal()), address(0)); assertEq(address(impl.portal()), address(0));
......
...@@ -9,6 +9,7 @@ import { ERC721 } from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; ...@@ -9,6 +9,7 @@ import { ERC721 } from "@openzeppelin/contracts/token/ERC721/ERC721.sol";
// Libraries // Libraries
import { Predeploys } from "src/libraries/Predeploys.sol"; import { Predeploys } from "src/libraries/Predeploys.sol";
import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol";
// Interfaces // Interfaces
import { ISuperchainConfig } from "interfaces/L1/ISuperchainConfig.sol"; import { ISuperchainConfig } from "interfaces/L1/ISuperchainConfig.sol";
...@@ -69,7 +70,7 @@ contract L1ERC721Bridge_Test is CommonTest { ...@@ -69,7 +70,7 @@ contract L1ERC721Bridge_Test is CommonTest {
/// @notice Marked virtual to be overridden in /// @notice Marked virtual to be overridden in
/// test/kontrol/deployment/DeploymentSummary.t.sol /// test/kontrol/deployment/DeploymentSummary.t.sol
function test_constructor_succeeds() public virtual { function test_constructor_succeeds() public virtual {
IL1ERC721Bridge impl = IL1ERC721Bridge(artifacts.mustGetAddress("L1ERC721BridgeImpl")); IL1ERC721Bridge impl = IL1ERC721Bridge(EIP1967Helper.getImplementation(address(l1ERC721Bridge)));
assertEq(address(impl.MESSENGER()), address(0)); assertEq(address(impl.MESSENGER()), address(0));
assertEq(address(impl.messenger()), address(0)); assertEq(address(impl.messenger()), address(0));
assertEq(address(impl.superchainConfig()), address(0)); assertEq(address(impl.superchainConfig()), address(0));
......
...@@ -12,6 +12,7 @@ import { StandardBridge } from "src/universal/StandardBridge.sol"; ...@@ -12,6 +12,7 @@ import { StandardBridge } from "src/universal/StandardBridge.sol";
// Libraries // Libraries
import { Predeploys } from "src/libraries/Predeploys.sol"; import { Predeploys } from "src/libraries/Predeploys.sol";
import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol"; import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol";
import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol";
// Interfaces // Interfaces
import { ICrossDomainMessenger } from "interfaces/universal/ICrossDomainMessenger.sol"; import { ICrossDomainMessenger } from "interfaces/universal/ICrossDomainMessenger.sol";
...@@ -38,7 +39,7 @@ contract L1StandardBridge_Initialize_Test is CommonTest { ...@@ -38,7 +39,7 @@ contract L1StandardBridge_Initialize_Test is CommonTest {
/// @notice Marked virtual to be overridden in /// @notice Marked virtual to be overridden in
/// test/kontrol/deployment/DeploymentSummary.t.sol /// test/kontrol/deployment/DeploymentSummary.t.sol
function test_constructor_succeeds() external virtual { function test_constructor_succeeds() external virtual {
IL1StandardBridge impl = IL1StandardBridge(artifacts.mustGetAddress("L1StandardBridgeImpl")); IL1StandardBridge impl = IL1StandardBridge(payable(EIP1967Helper.getImplementation(address(l1StandardBridge))));
assertEq(address(impl.superchainConfig()), address(0)); assertEq(address(impl.superchainConfig()), address(0));
// The constructor now uses _disableInitializers, whereas OP Mainnet has these values in storage // The constructor now uses _disableInitializers, whereas OP Mainnet has these values in storage
......
...@@ -19,6 +19,7 @@ import { Constants } from "src/libraries/Constants.sol"; ...@@ -19,6 +19,7 @@ import { Constants } from "src/libraries/Constants.sol";
import { Predeploys } from "src/libraries/Predeploys.sol"; import { Predeploys } from "src/libraries/Predeploys.sol";
import { GasPayingToken } from "src/libraries/GasPayingToken.sol"; import { GasPayingToken } from "src/libraries/GasPayingToken.sol";
import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol"; import { AddressAliasHelper } from "src/vendor/AddressAliasHelper.sol";
import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol";
import "src/dispute/lib/Types.sol"; import "src/dispute/lib/Types.sol";
import "src/libraries/PortalErrors.sol"; import "src/libraries/PortalErrors.sol";
...@@ -42,7 +43,7 @@ contract OptimismPortal2_Test is CommonTest { ...@@ -42,7 +43,7 @@ contract OptimismPortal2_Test is CommonTest {
/// @notice Marked virtual to be overridden in /// @notice Marked virtual to be overridden in
/// test/kontrol/deployment/DeploymentSummary.t.sol /// test/kontrol/deployment/DeploymentSummary.t.sol
function test_constructor_succeeds() external virtual { function test_constructor_succeeds() external virtual {
IOptimismPortal2 opImpl = IOptimismPortal2(payable(artifacts.mustGetAddress("OptimismPortal2Impl"))); IOptimismPortal2 opImpl = IOptimismPortal2(payable(EIP1967Helper.getImplementation(address(optimismPortal2))));
assertEq(address(opImpl.disputeGameFactory()), address(0)); assertEq(address(opImpl.disputeGameFactory()), address(0));
assertEq(address(opImpl.systemConfig()), address(0)); assertEq(address(opImpl.systemConfig()), address(0));
assertEq(address(opImpl.superchainConfig()), address(0)); assertEq(address(opImpl.superchainConfig()), address(0));
......
...@@ -11,6 +11,7 @@ import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; ...@@ -11,6 +11,7 @@ import { ERC20 } from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import { Constants } from "src/libraries/Constants.sol"; import { Constants } from "src/libraries/Constants.sol";
import { Predeploys } from "src/libraries/Predeploys.sol"; import { Predeploys } from "src/libraries/Predeploys.sol";
import { GasPayingToken } from "src/libraries/GasPayingToken.sol"; import { GasPayingToken } from "src/libraries/GasPayingToken.sol";
import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol";
// Interfaces // Interfaces
import { IResourceMetering } from "interfaces/L1/IResourceMetering.sol"; import { IResourceMetering } from "interfaces/L1/IResourceMetering.sol";
...@@ -42,7 +43,7 @@ contract SystemConfig_Initialize_Test is SystemConfig_Init { ...@@ -42,7 +43,7 @@ contract SystemConfig_Initialize_Test is SystemConfig_Init {
batcherHash = bytes32(uint256(uint160(deploy.cfg().batchSenderAddress()))); batcherHash = bytes32(uint256(uint160(deploy.cfg().batchSenderAddress())));
gasLimit = uint64(deploy.cfg().l2GenesisBlockGasLimit()); gasLimit = uint64(deploy.cfg().l2GenesisBlockGasLimit());
unsafeBlockSigner = deploy.cfg().p2pSequencerAddress(); unsafeBlockSigner = deploy.cfg().p2pSequencerAddress();
systemConfigImpl = artifacts.mustGetAddress("SystemConfigImpl"); systemConfigImpl = EIP1967Helper.getImplementation(address(systemConfig));
optimismMintableERC20Factory = artifacts.mustGetAddress("OptimismMintableERC20FactoryProxy"); optimismMintableERC20Factory = artifacts.mustGetAddress("OptimismMintableERC20FactoryProxy");
} }
......
...@@ -6,6 +6,7 @@ import { stdJson } from "forge-std/StdJson.sol"; ...@@ -6,6 +6,7 @@ import { stdJson } from "forge-std/StdJson.sol";
// Scripts // Scripts
import { Deployer } from "scripts/deploy/Deployer.sol"; import { Deployer } from "scripts/deploy/Deployer.sol";
import { Deploy } from "scripts/deploy/Deploy.s.sol";
// Libraries // Libraries
import { GameTypes } from "src/dispute/lib/Types.sol"; import { GameTypes } from "src/dispute/lib/Types.sol";
...@@ -19,9 +20,9 @@ import { IAddressManager } from "interfaces/legacy/IAddressManager.sol"; ...@@ -19,9 +20,9 @@ import { IAddressManager } from "interfaces/legacy/IAddressManager.sol";
/// @title ForkLive /// @title ForkLive
/// @notice This script is called by Setup.sol as a preparation step for the foundry test suite, and is run as an /// @notice This script is called by Setup.sol as a preparation step for the foundry test suite, and is run as an
/// alternative to Deploy.s.sol, when `FORK_TEST=true` is set in the env. /// alternative to Deploy.s.sol, when `FORK_TEST=true` is set in the env.
/// Like Deploy.s.sol this script saves the system addresses to disk so that they can be read into memory later /// Like Deploy.s.sol this script saves the system addresses to the Artifacts contract so that they can be
/// on, however rather than deploying new contracts from the local source code, it simply reads the addresses /// read by other contracts. However, rather than deploying new contracts from the local source code, it
/// from the superchain-registry. /// simply reads the addresses from the superchain-registry.
/// Therefore this script can only be run against a fork of a production network which is listed in the /// Therefore this script can only be run against a fork of a production network which is listed in the
/// superchain-registry. /// superchain-registry.
/// This contract must not have constructor logic because it is set into state using `etch`. /// This contract must not have constructor logic because it is set into state using `etch`.
...@@ -40,17 +41,29 @@ contract ForkLive is Deployer { ...@@ -40,17 +41,29 @@ contract ForkLive is Deployer {
return vm.envOr("FORK_OP_CHAIN", string("op")); return vm.envOr("FORK_OP_CHAIN", string("op"));
} }
/// @notice Reads a standard chains addresses from the superchain-registry and saves them to disk. /// @notice Forks, upgrades and tests a production network.
/// @dev This function sets up the system to test by:
/// 1. reading the superchain-registry to get the contract addresses we wish to test from that network.
/// 2. deploying the updated OPCM and implementations of the contracts.
/// 3. upgrading the system using the OPCM.upgrade() function.
function run() public { function run() public {
// Read the superchain registry and save the addresses to the Artifacts contract.
_readSuperchainRegistry();
// Now deploy the updated OPCM and implementations of the contracts
_deployNewImplementations();
}
/// @notice Reads the superchain config files and saves the addresses to disk.
/// @dev During development of an upgrade which adds a new contract, the contract will not yet be present in the
/// superchain-registry. In this case, the contract will be deployed by the upgrade process, and will need to
/// be stored by artifacts.save() after the call to opcm.upgrade().
/// After the upgrade is complete, the superchain-registry will be updated and the contract will be present. At
/// that point, this function will need to be updated to read the new contract from the superchain-registry
/// using either the `saveProxyAndImpl` or `artifacts.save()` functions.
function _readSuperchainRegistry() internal {
string memory superchainBasePath = "./lib/superchain-registry/superchain/configs/"; string memory superchainBasePath = "./lib/superchain-registry/superchain/configs/";
// Read the superchain config files
// During development of an upgrade which adds a new contract, the contract will not yet be present in the
// superchain-registry. In this case, the contract will be deployed by the upgrade process, and will need to
// be saved by after the call to opcm.upgrade().
// After the upgrade is complete, the superchain-registry will be updated and the contract will be present.
// At this point, the test will need to be updated to read the new contract from the superchain-registry using
// either the `saveProxyAndImpl` or `save` functions.
string memory superchainToml = vm.readFile(string.concat(superchainBasePath, baseChain(), "/superchain.toml")); string memory superchainToml = vm.readFile(string.concat(superchainBasePath, baseChain(), "/superchain.toml"));
string memory opToml = vm.readFile(string.concat(superchainBasePath, baseChain(), "/", opChain(), ".toml")); string memory opToml = vm.readFile(string.concat(superchainBasePath, baseChain(), "/", opChain(), ".toml"));
...@@ -99,6 +112,13 @@ contract ForkLive is Deployer { ...@@ -99,6 +112,13 @@ contract ForkLive is Deployer {
artifacts.save("PermissionedDelayedWETHProxy", address(permissionedDisputeGame.weth())); artifacts.save("PermissionedDelayedWETHProxy", address(permissionedDisputeGame.weth()));
} }
/// @notice Calls to the Deploy.s.sol contract etched by Setup.sol to a deterministic address, sets up the
/// environment, and deploys new implementations.
function _deployNewImplementations() internal {
Deploy deploy = Deploy(address(uint160(uint256(keccak256(abi.encode("optimism.deploy"))))));
deploy.deployImplementations({ _isInterop: false });
}
/// @notice Saves the proxy and implementation addresses for a contract name /// @notice Saves the proxy and implementation addresses for a contract name
/// @param _contractName The name of the contract to save /// @param _contractName The name of the contract to save
/// @param _tomlPath The path to the superchain config file /// @param _tomlPath The path to the superchain config file
...@@ -106,6 +126,7 @@ contract ForkLive is Deployer { ...@@ -106,6 +126,7 @@ contract ForkLive is Deployer {
function saveProxyAndImpl(string memory _contractName, string memory _tomlPath, string memory _tomlKey) internal { function saveProxyAndImpl(string memory _contractName, string memory _tomlPath, string memory _tomlKey) internal {
address proxy = vm.parseTomlAddress(_tomlPath, _tomlKey); address proxy = vm.parseTomlAddress(_tomlPath, _tomlKey);
artifacts.save(string.concat(_contractName, "Proxy"), proxy); artifacts.save(string.concat(_contractName, "Proxy"), proxy);
address impl = EIP1967Helper.getImplementation(proxy); address impl = EIP1967Helper.getImplementation(proxy);
require(impl != address(0), "Upgrade: Implementation address is zero"); require(impl != address(0), "Upgrade: Implementation address is zero");
artifacts.save(string.concat(_contractName, "Impl"), impl); artifacts.save(string.concat(_contractName, "Impl"), impl);
......
...@@ -67,6 +67,11 @@ contract Setup { ...@@ -67,6 +67,11 @@ contract Setup {
/// mutating any nonces. MUST not have constructor logic. /// mutating any nonces. MUST not have constructor logic.
Deploy internal constant deploy = Deploy(address(uint160(uint256(keccak256(abi.encode("optimism.deploy")))))); Deploy internal constant deploy = Deploy(address(uint160(uint256(keccak256(abi.encode("optimism.deploy"))))));
/// @notice The address of the ForkLive contract. Set into state with `etch` to avoid
/// mutating any nonces. MUST not have constructor logic.
ForkLive internal constant forkLive =
ForkLive(address(uint160(uint256(keccak256(abi.encode("optimism.forklive"))))));
/// @notice The address of the Artifacts contract. Set into state by Deployer.setUp() with `etch` to avoid /// @notice The address of the Artifacts contract. Set into state by Deployer.setUp() with `etch` to avoid
/// mutating any nonces. MUST not have constructor logic. /// mutating any nonces. MUST not have constructor logic.
Artifacts public constant artifacts = Artifacts public constant artifacts =
...@@ -78,9 +83,6 @@ contract Setup { ...@@ -78,9 +83,6 @@ contract Setup {
/// @notice Allows users of Setup to override what L2 genesis is being created. /// @notice Allows users of Setup to override what L2 genesis is being created.
Fork l2Fork = LATEST_FORK; Fork l2Fork = LATEST_FORK;
/// @notice Indicates whether a test is running against a forked production network.
bool private _isForkTest;
// L1 contracts // L1 contracts
IDisputeGameFactory disputeGameFactory; IDisputeGameFactory disputeGameFactory;
IAnchorStateRegistry anchorStateRegistry; IAnchorStateRegistry anchorStateRegistry;
...@@ -122,7 +124,7 @@ contract Setup { ...@@ -122,7 +124,7 @@ contract Setup {
/// @notice Indicates whether a test is running against a forked production network. /// @notice Indicates whether a test is running against a forked production network.
function isForkTest() public view returns (bool) { function isForkTest() public view returns (bool) {
return _isForkTest; return vm.envOr("FORK_TEST", false);
} }
/// @dev Deploys either the Deploy.s.sol or Fork.s.sol contract, by fetching the bytecode dynamically using /// @dev Deploys either the Deploy.s.sol or Fork.s.sol contract, by fetching the bytecode dynamically using
...@@ -135,30 +137,24 @@ contract Setup { ...@@ -135,30 +137,24 @@ contract Setup {
function setUp() public virtual { function setUp() public virtual {
console.log("Setup: L1 setup start!"); console.log("Setup: L1 setup start!");
// Optimistically etch, label and allow cheatcodes for the Deploy.s.sol contract if (isForkTest()) {
DeployUtils.etchLabelAndAllowCheatcodes({ _etchTo: address(deploy), _cname: "Deploy" });
_isForkTest = vm.envOr("FORK_TEST", false);
if (_isForkTest) {
vm.createSelectFork(vm.envString("FORK_RPC_URL"), vm.envUint("FORK_BLOCK_NUMBER")); vm.createSelectFork(vm.envString("FORK_RPC_URL"), vm.envUint("FORK_BLOCK_NUMBER"));
require( require(
block.chainid == Chains.Sepolia || block.chainid == Chains.Mainnet, block.chainid == Chains.Sepolia || block.chainid == Chains.Mainnet,
"Setup: ETH_RPC_URL must be set to a production (Sepolia or Mainnet) RPC URL" "Setup: ETH_RPC_URL must be set to a production (Sepolia or Mainnet) RPC URL"
); );
// Overwrite the Deploy.s.sol contract with the ForkLive.s.sol contract
DeployUtils.etchLabelAndAllowCheatcodes({ _etchTo: address(deploy), _cname: "ForkLive" });
} }
// deploy.setUp() will either: // Etch the contracts used to setup the test environment
// 1. deploy a fresh system or DeployUtils.etchLabelAndAllowCheatcodes({ _etchTo: address(deploy), _cname: "Deploy" });
// 2. fork from L1 DeployUtils.etchLabelAndAllowCheatcodes({ _etchTo: address(forkLive), _cname: "ForkLive" });
// It will then save the appropriate name/address pairs to disk using artifacts.save()
deploy.setUp(); deploy.setUp();
forkLive.setUp();
console.log("Setup: L1 setup done!"); console.log("Setup: L1 setup done!");
// Return early if this is a fork test if (isForkTest()) {
if (_isForkTest) { // Return early if this is a fork test as we don't need to setup L2
console.log("Setup: fork test detected, skipping L2 genesis generation"); console.log("Setup: fork test detected, skipping L2 genesis generation");
return; return;
} }
...@@ -172,7 +168,7 @@ contract Setup { ...@@ -172,7 +168,7 @@ contract Setup {
/// @dev Skips tests when running against a forked production network. /// @dev Skips tests when running against a forked production network.
function skipIfForkTest(string memory message) public { function skipIfForkTest(string memory message) public {
if (_isForkTest) { if (isForkTest()) {
vm.skip(true); vm.skip(true);
console.log(string.concat("Skipping fork test: ", message)); console.log(string.concat("Skipping fork test: ", message));
} }
...@@ -181,7 +177,7 @@ contract Setup { ...@@ -181,7 +177,7 @@ contract Setup {
/// @dev Returns early when running against a forked production network. Useful for allowing a portion of a test /// @dev Returns early when running against a forked production network. Useful for allowing a portion of a test
/// to run. /// to run.
function returnIfForkTest(string memory message) public view { function returnIfForkTest(string memory message) public view {
if (_isForkTest) { if (isForkTest()) {
console.log(string.concat("Returning early from fork test: ", message)); console.log(string.concat("Returning early from fork test: ", message));
assembly { assembly {
return(0, 0) return(0, 0)
...@@ -198,7 +194,12 @@ contract Setup { ...@@ -198,7 +194,12 @@ contract Setup {
hex"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3" hex"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe03601600081602082378035828234f58015156039578182fd5b8082525050506014600cf3"
); );
deploy.run(); if (isForkTest()) {
forkLive.run();
} else {
deploy.run();
}
console.log("Setup: completed L1 deployment, registering addresses now"); console.log("Setup: completed L1 deployment, registering addresses now");
optimismPortal2 = IOptimismPortal2(artifacts.mustGetAddress("OptimismPortalProxy")); optimismPortal2 = IOptimismPortal2(artifacts.mustGetAddress("OptimismPortalProxy"));
...@@ -228,7 +229,7 @@ contract Setup { ...@@ -228,7 +229,7 @@ contract Setup {
/// @dev Sets up the L2 contracts. Depends on `L1()` being called first. /// @dev Sets up the L2 contracts. Depends on `L1()` being called first.
function L2() public { function L2() public {
// Fork tests focus on L1 contracts so there is no need to do all the work of setting up L2. // Fork tests focus on L1 contracts so there is no need to do all the work of setting up L2.
if (_isForkTest) { if (isForkTest()) {
console.log("Setup: fork test detected, skipping L2 setup"); console.log("Setup: fork test detected, skipping L2 setup");
return; return;
} }
......
...@@ -12,6 +12,7 @@ import { Process } from "scripts/libraries/Process.sol"; ...@@ -12,6 +12,7 @@ import { Process } from "scripts/libraries/Process.sol";
import { LibString } from "@solady/utils/LibString.sol"; import { LibString } from "@solady/utils/LibString.sol";
import { Constants } from "src/libraries/Constants.sol"; import { Constants } from "src/libraries/Constants.sol";
import { GameType } from "src/dispute/lib/Types.sol"; import { GameType } from "src/dispute/lib/Types.sol";
import { EIP1967Helper } from "test/mocks/EIP1967Helper.sol";
// Interfaces // Interfaces
import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol"; import { ISystemConfig } from "interfaces/L1/ISystemConfig.sol";
...@@ -57,7 +58,7 @@ contract Initializer_Test is CommonTest { ...@@ -57,7 +58,7 @@ contract Initializer_Test is CommonTest {
contracts.push( contracts.push(
InitializeableContract({ InitializeableContract({
name: "SuperchainConfigImpl", name: "SuperchainConfigImpl",
target: artifacts.mustGetAddress("SuperchainConfigImpl"), target: EIP1967Helper.getImplementation(address(superchainConfig)),
initCalldata: abi.encodeCall(superchainConfig.initialize, (address(0), false)) initCalldata: abi.encodeCall(superchainConfig.initialize, (address(0), false))
}) })
); );
...@@ -73,7 +74,7 @@ contract Initializer_Test is CommonTest { ...@@ -73,7 +74,7 @@ contract Initializer_Test is CommonTest {
contracts.push( contracts.push(
InitializeableContract({ InitializeableContract({
name: "L1CrossDomainMessengerImpl", name: "L1CrossDomainMessengerImpl",
target: artifacts.mustGetAddress("L1CrossDomainMessengerImpl"), target: addressManager.getAddress("OVM_L1CrossDomainMessenger"),
initCalldata: abi.encodeCall( initCalldata: abi.encodeCall(
l1CrossDomainMessenger.initialize, (superchainConfig, optimismPortal2, systemConfig) l1CrossDomainMessenger.initialize, (superchainConfig, optimismPortal2, systemConfig)
) )
...@@ -93,7 +94,7 @@ contract Initializer_Test is CommonTest { ...@@ -93,7 +94,7 @@ contract Initializer_Test is CommonTest {
contracts.push( contracts.push(
InitializeableContract({ InitializeableContract({
name: "DisputeGameFactoryImpl", name: "DisputeGameFactoryImpl",
target: artifacts.mustGetAddress("DisputeGameFactoryImpl"), target: EIP1967Helper.getImplementation(address(disputeGameFactory)),
initCalldata: abi.encodeCall(disputeGameFactory.initialize, (address(0))) initCalldata: abi.encodeCall(disputeGameFactory.initialize, (address(0)))
}) })
); );
...@@ -109,7 +110,7 @@ contract Initializer_Test is CommonTest { ...@@ -109,7 +110,7 @@ contract Initializer_Test is CommonTest {
contracts.push( contracts.push(
InitializeableContract({ InitializeableContract({
name: "DelayedWETHImpl", name: "DelayedWETHImpl",
target: artifacts.mustGetAddress("DelayedWETHImpl"), target: EIP1967Helper.getImplementation(address(delayedWeth)),
initCalldata: abi.encodeCall(delayedWeth.initialize, (address(0), ISuperchainConfig(address(0)))) initCalldata: abi.encodeCall(delayedWeth.initialize, (address(0), ISuperchainConfig(address(0))))
}) })
); );
...@@ -125,7 +126,7 @@ contract Initializer_Test is CommonTest { ...@@ -125,7 +126,7 @@ contract Initializer_Test is CommonTest {
contracts.push( contracts.push(
InitializeableContract({ InitializeableContract({
name: "OptimismPortal2Impl", name: "OptimismPortal2Impl",
target: artifacts.mustGetAddress("OptimismPortal2Impl"), target: EIP1967Helper.getImplementation(address(optimismPortal2)),
initCalldata: abi.encodeCall( initCalldata: abi.encodeCall(
optimismPortal2.initialize, optimismPortal2.initialize,
( (
...@@ -157,7 +158,7 @@ contract Initializer_Test is CommonTest { ...@@ -157,7 +158,7 @@ contract Initializer_Test is CommonTest {
contracts.push( contracts.push(
InitializeableContract({ InitializeableContract({
name: "SystemConfigImpl", name: "SystemConfigImpl",
target: artifacts.mustGetAddress("SystemConfigImpl"), target: EIP1967Helper.getImplementation(address(systemConfig)),
initCalldata: abi.encodeCall( initCalldata: abi.encodeCall(
systemConfig.initialize, systemConfig.initialize,
( (
...@@ -229,7 +230,7 @@ contract Initializer_Test is CommonTest { ...@@ -229,7 +230,7 @@ contract Initializer_Test is CommonTest {
contracts.push( contracts.push(
InitializeableContract({ InitializeableContract({
name: "ProtocolVersionsImpl", name: "ProtocolVersionsImpl",
target: artifacts.mustGetAddress("ProtocolVersionsImpl"), target: EIP1967Helper.getImplementation(address(protocolVersions)),
initCalldata: abi.encodeCall( initCalldata: abi.encodeCall(
protocolVersions.initialize, (address(0), ProtocolVersion.wrap(1), ProtocolVersion.wrap(2)) protocolVersions.initialize, (address(0), ProtocolVersion.wrap(1), ProtocolVersion.wrap(2))
) )
...@@ -249,7 +250,7 @@ contract Initializer_Test is CommonTest { ...@@ -249,7 +250,7 @@ contract Initializer_Test is CommonTest {
contracts.push( contracts.push(
InitializeableContract({ InitializeableContract({
name: "L1StandardBridgeImpl", name: "L1StandardBridgeImpl",
target: artifacts.mustGetAddress("L1StandardBridgeImpl"), target: EIP1967Helper.getImplementation(address(l1StandardBridge)),
initCalldata: abi.encodeCall( initCalldata: abi.encodeCall(
l1StandardBridge.initialize, (l1CrossDomainMessenger, superchainConfig, systemConfig) l1StandardBridge.initialize, (l1CrossDomainMessenger, superchainConfig, systemConfig)
) )
...@@ -269,7 +270,7 @@ contract Initializer_Test is CommonTest { ...@@ -269,7 +270,7 @@ contract Initializer_Test is CommonTest {
contracts.push( contracts.push(
InitializeableContract({ InitializeableContract({
name: "L1ERC721BridgeImpl", name: "L1ERC721BridgeImpl",
target: artifacts.mustGetAddress("L1ERC721BridgeImpl"), target: EIP1967Helper.getImplementation(address(l1ERC721Bridge)),
initCalldata: abi.encodeCall(l1ERC721Bridge.initialize, (l1CrossDomainMessenger, superchainConfig)) initCalldata: abi.encodeCall(l1ERC721Bridge.initialize, (l1CrossDomainMessenger, superchainConfig))
}) })
); );
...@@ -285,7 +286,7 @@ contract Initializer_Test is CommonTest { ...@@ -285,7 +286,7 @@ contract Initializer_Test is CommonTest {
contracts.push( contracts.push(
InitializeableContract({ InitializeableContract({
name: "OptimismMintableERC20FactoryImpl", name: "OptimismMintableERC20FactoryImpl",
target: artifacts.mustGetAddress("OptimismMintableERC20FactoryImpl"), target: EIP1967Helper.getImplementation(address(l1OptimismMintableERC20Factory)),
initCalldata: abi.encodeCall(l1OptimismMintableERC20Factory.initialize, (address(l1StandardBridge))) initCalldata: abi.encodeCall(l1OptimismMintableERC20Factory.initialize, (address(l1StandardBridge)))
}) })
); );
...@@ -301,7 +302,7 @@ contract Initializer_Test is CommonTest { ...@@ -301,7 +302,7 @@ contract Initializer_Test is CommonTest {
contracts.push( contracts.push(
InitializeableContract({ InitializeableContract({
name: "DataAvailabilityChallengeImpl", name: "DataAvailabilityChallengeImpl",
target: artifacts.mustGetAddress("DataAvailabilityChallengeImpl"), target: EIP1967Helper.getImplementation(address(dataAvailabilityChallenge)),
initCalldata: abi.encodeCall(dataAvailabilityChallenge.initialize, (address(0), 0, 0, 0, 0)) initCalldata: abi.encodeCall(dataAvailabilityChallenge.initialize, (address(0), 0, 0, 0, 0))
}) })
); );
...@@ -317,7 +318,7 @@ contract Initializer_Test is CommonTest { ...@@ -317,7 +318,7 @@ contract Initializer_Test is CommonTest {
contracts.push( contracts.push(
InitializeableContract({ InitializeableContract({
name: "AnchorStateRegistryImpl", name: "AnchorStateRegistryImpl",
target: address(anchorStateRegistry), target: EIP1967Helper.getImplementation(address(anchorStateRegistry)),
initCalldata: abi.encodeCall( initCalldata: abi.encodeCall(
anchorStateRegistry.initialize, anchorStateRegistry.initialize,
(new IAnchorStateRegistry.StartingAnchorRoot[](1), ISuperchainConfig(address(0))) (new IAnchorStateRegistry.StartingAnchorRoot[](1), ISuperchainConfig(address(0)))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment