Commit eea9572d authored by Matthew Slipper's avatar Matthew Slipper Committed by GitHub

ctb: Make implementations deployments deterministic and idempotent (#13717)

* ctb: Make implementations deployments deterministic and idempotent

* code review updates

* cr updates

* imports

* make superchain deployments deterministic

* forgot to add test

* code review updates

* broadcast in dpeloysuperchain

* add forgotten broadcast
parent f0f0643d
...@@ -114,7 +114,7 @@ func CreateL1(logger log.Logger, fa *foundry.ArtifactsFS, srcFS *foundry.SourceM ...@@ -114,7 +114,7 @@ func CreateL1(logger log.Logger, fa *foundry.ArtifactsFS, srcFS *foundry.SourceM
PrevRandao: cfg.L1GenesisBlockMixHash, PrevRandao: cfg.L1GenesisBlockMixHash,
BlobHashes: nil, BlobHashes: nil,
} }
l1Host := script.NewHost(logger.New("role", "l1", "chain", cfg.ChainID), fa, srcFS, l1Context) l1Host := script.NewHost(logger.New("role", "l1", "chain", cfg.ChainID), fa, srcFS, l1Context, script.WithCreate2Deployer())
return l1Host return l1Host
} }
......
...@@ -292,12 +292,8 @@ contract Deploy is Deployer { ...@@ -292,12 +292,8 @@ contract Deploy is Deployer {
dii.set(dii.mipsVersion.selector, Config.useMultithreadedCannon() ? 2 : 1); dii.set(dii.mipsVersion.selector, Config.useMultithreadedCannon() ? 2 : 1);
string memory release = "dev"; string memory release = "dev";
dii.set(dii.l1ContractsRelease.selector, release); dii.set(dii.l1ContractsRelease.selector, release);
dii.set(
dii.standardVersionsToml.selector, string.concat(vm.projectRoot(), "/test/fixtures/standard-versions.toml")
);
dii.set(dii.superchainConfigProxy.selector, artifacts.mustGetAddress("SuperchainConfigProxy")); dii.set(dii.superchainConfigProxy.selector, artifacts.mustGetAddress("SuperchainConfigProxy"));
dii.set(dii.protocolVersionsProxy.selector, artifacts.mustGetAddress("ProtocolVersionsProxy")); dii.set(dii.protocolVersionsProxy.selector, artifacts.mustGetAddress("ProtocolVersionsProxy"));
dii.set(dii.salt.selector, _implSalt());
if (_isInterop) { if (_isInterop) {
di = DeployImplementations(new DeployImplementationsInterop()); di = DeployImplementations(new DeployImplementationsInterop());
......
...@@ -292,6 +292,8 @@ contract DeploySuperchainOutput is BaseDeployIO { ...@@ -292,6 +292,8 @@ contract DeploySuperchainOutput is BaseDeployIO {
// default sender would be the broadcaster during test, but the broadcaster needs to be the deployer // default sender would be the broadcaster during test, but the broadcaster needs to be the deployer
// since they are set to the initial proxy admin owner. // since they are set to the initial proxy admin owner.
contract DeploySuperchain is Script { contract DeploySuperchain is Script {
bytes32 internal _salt = DeployUtils.DEFAULT_SALT;
// -------- Core Deployment Methods -------- // -------- Core Deployment Methods --------
function run(DeploySuperchainInput _dsi, DeploySuperchainOutput _dso) public { function run(DeploySuperchainInput _dsi, DeploySuperchainOutput _dso) public {
...@@ -342,15 +344,17 @@ contract DeploySuperchain is Script { ...@@ -342,15 +344,17 @@ contract DeploySuperchain is Script {
// Deploy implementation contracts. // Deploy implementation contracts.
vm.startBroadcast(msg.sender); vm.startBroadcast(msg.sender);
ISuperchainConfig superchainConfigImpl = ISuperchainConfig( ISuperchainConfig superchainConfigImpl = ISuperchainConfig(
DeployUtils.create1({ DeployUtils.createDeterministic({
_name: "SuperchainConfig", _name: "SuperchainConfig",
_args: DeployUtils.encodeConstructor(abi.encodeCall(ISuperchainConfig.__constructor__, ())) _args: DeployUtils.encodeConstructor(abi.encodeCall(ISuperchainConfig.__constructor__, ())),
_salt: _salt
}) })
); );
IProtocolVersions protocolVersionsImpl = IProtocolVersions( IProtocolVersions protocolVersionsImpl = IProtocolVersions(
DeployUtils.create1({ DeployUtils.createDeterministic({
_name: "ProtocolVersions", _name: "ProtocolVersions",
_args: DeployUtils.encodeConstructor(abi.encodeCall(IProtocolVersions.__constructor__, ())) _args: DeployUtils.encodeConstructor(abi.encodeCall(IProtocolVersions.__constructor__, ())),
_salt: _salt
}) })
); );
vm.stopBroadcast(); vm.stopBroadcast();
......
...@@ -10,6 +10,7 @@ import { Artifacts } from "scripts/Artifacts.s.sol"; ...@@ -10,6 +10,7 @@ import { Artifacts } from "scripts/Artifacts.s.sol";
import { LibString } from "@solady/utils/LibString.sol"; import { LibString } from "@solady/utils/LibString.sol";
import { Bytes } from "src/libraries/Bytes.sol"; import { Bytes } from "src/libraries/Bytes.sol";
import { Constants } from "src/libraries/Constants.sol"; import { Constants } from "src/libraries/Constants.sol";
import { Blueprint } from "src/libraries/Blueprint.sol";
// Interfaces // Interfaces
import { IProxy } from "interfaces/universal/IProxy.sol"; import { IProxy } from "interfaces/universal/IProxy.sol";
...@@ -20,6 +21,8 @@ import { IResolvedDelegateProxy } from "interfaces/legacy/IResolvedDelegateProxy ...@@ -20,6 +21,8 @@ import { IResolvedDelegateProxy } from "interfaces/legacy/IResolvedDelegateProxy
library DeployUtils { library DeployUtils {
Vm internal constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code"))))); Vm internal constant vm = Vm(address(uint160(uint256(keccak256("hevm cheat code")))));
bytes32 internal constant DEFAULT_SALT = keccak256("op-stack-contract-impls-salt-v0");
/// @notice Deploys a contract with the given name and arguments via CREATE. /// @notice Deploys a contract with the given name and arguments via CREATE.
/// @param _name Name of the contract to deploy. /// @param _name Name of the contract to deploy.
/// @param _args ABI-encoded constructor arguments. /// @param _args ABI-encoded constructor arguments.
...@@ -97,19 +100,11 @@ library DeployUtils { ...@@ -97,19 +100,11 @@ library DeployUtils {
/// @param _args ABI-encoded constructor arguments. /// @param _args ABI-encoded constructor arguments.
/// @param _salt Salt for the CREATE2 operation. /// @param _salt Salt for the CREATE2 operation.
/// @return addr_ Address of the deployed contract. /// @return addr_ Address of the deployed contract.
function create2(string memory _name, bytes memory _args, bytes32 _salt) internal returns (address payable addr_) { function create2(string memory _name, bytes memory _args, bytes32 _salt) internal returns (address payable) {
bytes memory initCode = abi.encodePacked(vm.getCode(_name), _args); bytes memory initCode = abi.encodePacked(vm.getCode(_name), _args);
address preComputedAddress = vm.computeCreate2Address(_salt, keccak256(initCode)); address preComputedAddress = vm.computeCreate2Address(_salt, keccak256(initCode));
require(preComputedAddress.code.length == 0, "DeployUtils: contract already deployed"); require(preComputedAddress.code.length == 0, "DeployUtils: contract already deployed");
assembly { return create2asm(initCode, _salt);
addr_ := create2(0, add(initCode, 0x20), mload(initCode), _salt)
if iszero(addr_) {
let size := returndatasize()
returndatacopy(0, 0, size)
revert(0, size)
}
}
assertValidContractAddress(addr_);
} }
/// @notice Deploys a contract with the given name via CREATE2. /// @notice Deploys a contract with the given name via CREATE2.
...@@ -120,6 +115,18 @@ library DeployUtils { ...@@ -120,6 +115,18 @@ library DeployUtils {
return create2(_name, hex"", _salt); return create2(_name, hex"", _salt);
} }
function create2asm(bytes memory _initCode, bytes32 _salt) internal returns (address payable addr_) {
assembly {
addr_ := create2(0, add(_initCode, 0x20), mload(_initCode), _salt)
if iszero(addr_) {
let size := returndatasize()
returndatacopy(0, 0, size)
revert(0, size)
}
}
assertValidContractAddress(addr_);
}
/// @notice Deploys a contract with the given name and arguments via CREATE2 and saves the result. /// @notice Deploys a contract with the given name and arguments via CREATE2 and saves the result.
/// @param _save Artifacts contract. /// @param _save Artifacts contract.
/// @param _name Name of the contract to deploy. /// @param _name Name of the contract to deploy.
...@@ -195,6 +202,64 @@ library DeployUtils { ...@@ -195,6 +202,64 @@ library DeployUtils {
return create2AndSave(_save, _name, _name, hex"", _salt); return create2AndSave(_save, _name, _name, hex"", _salt);
} }
/// @notice Deploys a contract with the given name using CREATE2. If the contract is already deployed, this method
/// does nothing.
/// @param _name Name of the contract to deploy.
/// @param _args ABI-encoded constructor arguments.
function createDeterministic(
string memory _name,
bytes memory _args,
bytes32 _salt
)
internal
returns (address payable addr_)
{
bytes memory initCode = abi.encodePacked(vm.getCode(_name), _args);
address preComputedAddress = vm.computeCreate2Address(_salt, keccak256(initCode));
if (preComputedAddress.code.length > 0) {
addr_ = payable(preComputedAddress);
} else {
addr_ = DeployUtils.create2asm(initCode, _salt);
}
}
/// @notice Deploys a blueprint contract with the given name using CREATE2. If the contract is already deployed,
/// this method does nothing.
/// @param _rawBytecode Raw bytecode of the contract the blueprint will deploy.
function createDeterministicBlueprint(
bytes memory _rawBytecode,
bytes32 _salt
)
internal
returns (address newContract1_, address newContract2_)
{
uint32 maxSize = Blueprint.maxInitCodeSize();
if (_rawBytecode.length <= maxSize) {
bytes memory bpBytecode = Blueprint.blueprintDeployerBytecode(_rawBytecode);
newContract1_ = vm.computeCreate2Address(_salt, keccak256(bpBytecode));
if (newContract1_.code.length == 0) {
(address deployedContract) = Blueprint.deploySmallBytecode(bpBytecode, _salt);
require(deployedContract == newContract1_, "DeployUtils: unexpected blueprint address");
}
newContract2_ = address(0);
} else {
bytes memory part1Slice = Bytes.slice(_rawBytecode, 0, maxSize);
bytes memory part2Slice = Bytes.slice(_rawBytecode, maxSize, _rawBytecode.length - maxSize);
bytes memory bp1Bytecode = Blueprint.blueprintDeployerBytecode(part1Slice);
bytes memory bp2Bytecode = Blueprint.blueprintDeployerBytecode(part2Slice);
newContract1_ = vm.computeCreate2Address(_salt, keccak256(bp1Bytecode));
if (newContract1_.code.length == 0) {
address deployedContract = Blueprint.deploySmallBytecode(bp1Bytecode, _salt);
require(deployedContract == newContract1_, "DeployUtils: unexpected part 1 blueprint address");
}
newContract2_ = vm.computeCreate2Address(_salt, keccak256(bp2Bytecode));
if (newContract2_.code.length == 0) {
address deployedContract = Blueprint.deploySmallBytecode(bp2Bytecode, _salt);
require(deployedContract == newContract2_, "DeployUtils: unexpected part 2 blueprint address");
}
}
}
/// @notice Takes a sender and an identifier and returns a deterministic address based on the /// @notice Takes a sender and an identifier and returns a deterministic address based on the
/// two. The result is used to etch the input and output contracts to a deterministic /// two. The result is used to etch the input and output contracts to a deterministic
/// address based on those two values, where the identifier represents the input or /// address based on those two values, where the identifier represents the input or
......
standard_release = "op-contracts/v1.6.0"
[releases]
# Contracts which are
# * unproxied singletons: specify a standard "address"
# * proxied : specify a standard "implementation_address"
# * neither : specify neither a standard "address" nor "implementation_address"
# Fault Proofs https://github.com/ethereum-optimism/optimism/releases/tag/op-contracts%2Fv1.6.0
[releases."op-contracts/v1.6.0"]
optimism_portal = { version = "3.10.0", implementation_address = "0xe2F826324b2faf99E513D16D266c3F80aE87832B" }
system_config = { version = "2.2.0", implementation_address = "0xF56D96B2535B932656d3c04Ebf51baBff241D886" }
anchor_state_registry = { version = "2.0.0" }
delayed_weth = { version = "1.1.0", implementation_address = "0x71e966Ae981d1ce531a7b6d23DC0f27B38409087" }
dispute_game_factory = { version = "1.0.0", implementation_address = "0xc641A33cab81C559F2bd4b21EA34C290E2440C2B" }
fault_dispute_game = { version = "1.3.0" }
permissioned_dispute_game = { version = "1.3.0" }
mips = { version = "1.1.0", address = "0x16e83cE5Ce29BF90AD9Da06D2fE6a15d5f344ce4" }
preimage_oracle = { version = "1.1.2", address = "0x9c065e11870B891D214Bc2Da7EF1f9DDFA1BE277" }
l1_cross_domain_messenger = { version = "2.3.0", implementation_address = "0xD3494713A5cfaD3F5359379DfA074E2Ac8C6Fd65" }
l1_erc721_bridge = { version = "2.1.0", implementation_address = "0xAE2AF01232a6c4a4d3012C5eC5b1b35059caF10d" }
l1_standard_bridge = { version = "2.1.0", implementation_address = "0x64B5a5Ed26DCb17370Ff4d33a8D503f0fbD06CfF" }
# l2_output_oracle -- This contract not used in fault proofs
optimism_mintable_erc20_factory = { version = "1.9.0", implementation_address = "0xE01efbeb1089D1d1dB9c6c8b135C934C0734c846" }
# Fault Proofs https://github.com/ethereum-optimism/optimism/releases/tag/op-contracts%2Fv1.4.0
[releases."op-contracts/v1.4.0"]
optimism_portal = { version = "3.10.0", implementation_address = "0xe2F826324b2faf99E513D16D266c3F80aE87832B" }
system_config = { version = "2.2.0", implementation_address = "0xF56D96B2535B932656d3c04Ebf51baBff241D886" }
anchor_state_registry = { version = "1.0.0" }
delayed_weth = { version = "1.0.0", implementation_address = "0x97988d5624F1ba266E1da305117BCf20713bee08" }
dispute_game_factory = { version = "1.0.0", implementation_address = "0xc641A33cab81C559F2bd4b21EA34C290E2440C2B" }
fault_dispute_game = { version = "1.2.0" }
permissioned_dispute_game = { version = "1.2.0" }
mips = { version = "1.0.1", address = "0x0f8EdFbDdD3c0256A80AD8C0F2560B1807873C9c" }
preimage_oracle = { version = "1.0.0", address = "0xD326E10B8186e90F4E2adc5c13a2d0C137ee8b34" }
# MCP https://github.com/ethereum-optimism/optimism/releases/tag/op-contracts%2Fv1.3.0
[releases."op-contracts/v1.3.0"]
l1_cross_domain_messenger = { version = "2.3.0", implementation_address = "0xD3494713A5cfaD3F5359379DfA074E2Ac8C6Fd65" }
l1_erc721_bridge = { version = "2.1.0", implementation_address = "0xAE2AF01232a6c4a4d3012C5eC5b1b35059caF10d" }
l1_standard_bridge = { version = "2.1.0", implementation_address = "0x64B5a5Ed26DCb17370Ff4d33a8D503f0fbD06CfF" }
l2_output_oracle = { version = "1.8.0", implementation_address = "0xF243BEd163251380e78068d317ae10f26042B292" }
optimism_mintable_erc20_factory = { version = "1.9.0", implementation_address = "0xE01efbeb1089D1d1dB9c6c8b135C934C0734c846" }
optimism_portal = { version = "2.5.0", implementation_address = "0x2D778797049FE9259d947D1ED8e5442226dFB589" }
system_config = { version = "1.12.0", implementation_address = "0xba2492e52F45651B60B8B38d4Ea5E2390C64Ffb1" }
...@@ -68,9 +68,6 @@ contract DeployImplementationsInput_Test is Test { ...@@ -68,9 +68,6 @@ contract DeployImplementationsInput_Test is Test {
vm.expectRevert("DeployImplementationsInput: not set"); vm.expectRevert("DeployImplementationsInput: not set");
dii.protocolVersionsProxy(); dii.protocolVersionsProxy();
vm.expectRevert("DeployImplementationsInput: not set");
dii.standardVersionsToml();
} }
} }
...@@ -225,14 +222,10 @@ contract DeployImplementations_Test is Test { ...@@ -225,14 +222,10 @@ contract DeployImplementations_Test is Test {
IProtocolVersions protocolVersionsProxy = IProtocolVersions(makeAddr("protocolVersionsProxy")); IProtocolVersions protocolVersionsProxy = IProtocolVersions(makeAddr("protocolVersionsProxy"));
function setUp() public virtual { function setUp() public virtual {
vm.etch(address(superchainConfigProxy), hex"01");
vm.etch(address(protocolVersionsProxy), hex"01");
deployImplementations = new DeployImplementations(); deployImplementations = new DeployImplementations();
(dii, dio) = deployImplementations.etchIOContracts(); (dii, dio) = deployImplementations.etchIOContracts();
// End users of the DeployImplementations contract will need to set the `standardVersionsToml`.
string memory standardVersionsTomlPath =
string.concat(vm.projectRoot(), "/test/fixtures/standard-versions.toml");
string memory standardVersionsToml = vm.readFile(standardVersionsTomlPath);
dii.set(dii.standardVersionsToml.selector, standardVersionsToml);
} }
// By deploying the `DeployImplementations` contract with this virtual function, we provide a // By deploying the `DeployImplementations` contract with this virtual function, we provide a
...@@ -247,67 +240,73 @@ contract DeployImplementations_Test is Test { ...@@ -247,67 +240,73 @@ contract DeployImplementations_Test is Test {
} }
function test_deployImplementation_succeeds() public { function test_deployImplementation_succeeds() public {
string memory deployContractsRelease = "dev-release"; deployImplementations.deploySystemConfigImpl(dio);
dii.set(dii.l1ContractsRelease.selector, deployContractsRelease);
deployImplementations.deploySystemConfigImpl(dii, dio);
assertTrue(address(0) != address(dio.systemConfigImpl())); assertTrue(address(0) != address(dio.systemConfigImpl()));
} }
function test_reuseImplementation_succeeds() public { function test_reuseImplementation_succeeds() public {
// All hardcoded addresses below are taken from the superchain-registry config:
// https://github.com/ethereum-optimism/superchain-registry/blob/be65d22f8128cf0c4e5b4e1f677daf86843426bf/validation/standard/standard-versions.toml#L11
string memory testRelease = "op-contracts/v1.6.0"; string memory testRelease = "op-contracts/v1.6.0";
dii.set(dii.l1ContractsRelease.selector, testRelease); dii.set(dii.l1ContractsRelease.selector, testRelease);
dii.set(dii.proofMaturityDelaySeconds.selector, 1);
dii.set(dii.disputeGameFinalityDelaySeconds.selector, 1);
dii.set(dii.withdrawalDelaySeconds.selector, 1);
dii.set(dii.minProposalSizeBytes.selector, 1);
dii.set(dii.challengePeriodSeconds.selector, 1);
dii.set(dii.mipsVersion.selector, 1);
dii.set(dii.superchainConfigProxy.selector, address(superchainConfigProxy));
dii.set(dii.protocolVersionsProxy.selector, address(protocolVersionsProxy));
deployImplementations.deploySystemConfigImpl(dii, dio); // Perform the initial deployment.
address srSystemConfigImpl = address(0xF56D96B2535B932656d3c04Ebf51baBff241D886); deployImplementations.deploySystemConfigImpl(dio);
vm.etch(address(srSystemConfigImpl), hex"01"); deployImplementations.deployL1CrossDomainMessengerImpl(dio);
assertEq(srSystemConfigImpl, address(dio.systemConfigImpl())); deployImplementations.deployL1ERC721BridgeImpl(dio);
deployImplementations.deployL1StandardBridgeImpl(dio);
address srL1CrossDomainMessengerImpl = address(0xD3494713A5cfaD3F5359379DfA074E2Ac8C6Fd65); deployImplementations.deployOptimismMintableERC20FactoryImpl(dio);
vm.etch(address(srL1CrossDomainMessengerImpl), hex"01");
deployImplementations.deployL1CrossDomainMessengerImpl(dii, dio);
assertEq(srL1CrossDomainMessengerImpl, address(dio.l1CrossDomainMessengerImpl()));
address srL1ERC721BridgeImpl = address(0xAE2AF01232a6c4a4d3012C5eC5b1b35059caF10d);
vm.etch(address(srL1ERC721BridgeImpl), hex"01");
deployImplementations.deployL1ERC721BridgeImpl(dii, dio);
assertEq(srL1ERC721BridgeImpl, address(dio.l1ERC721BridgeImpl()));
address srL1StandardBridgeImpl = address(0x64B5a5Ed26DCb17370Ff4d33a8D503f0fbD06CfF);
vm.etch(address(srL1StandardBridgeImpl), hex"01");
deployImplementations.deployL1StandardBridgeImpl(dii, dio);
assertEq(srL1StandardBridgeImpl, address(dio.l1StandardBridgeImpl()));
address srOptimismMintableERC20FactoryImpl = address(0xE01efbeb1089D1d1dB9c6c8b135C934C0734c846);
vm.etch(address(srOptimismMintableERC20FactoryImpl), hex"01");
deployImplementations.deployOptimismMintableERC20FactoryImpl(dii, dio);
assertEq(srOptimismMintableERC20FactoryImpl, address(dio.optimismMintableERC20FactoryImpl()));
address srOptimismPortalImpl = address(0xe2F826324b2faf99E513D16D266c3F80aE87832B);
vm.etch(address(srOptimismPortalImpl), hex"01");
deployImplementations.deployOptimismPortalImpl(dii, dio); deployImplementations.deployOptimismPortalImpl(dii, dio);
assertEq(srOptimismPortalImpl, address(dio.optimismPortalImpl()));
address srDelayedWETHImpl = address(0x71e966Ae981d1ce531a7b6d23DC0f27B38409087);
vm.etch(address(srDelayedWETHImpl), hex"01");
deployImplementations.deployDelayedWETHImpl(dii, dio); deployImplementations.deployDelayedWETHImpl(dii, dio);
assertEq(srDelayedWETHImpl, address(dio.delayedWETHImpl()));
address srPreimageOracleSingleton = address(0x9c065e11870B891D214Bc2Da7EF1f9DDFA1BE277);
vm.etch(address(srPreimageOracleSingleton), hex"01");
deployImplementations.deployPreimageOracleSingleton(dii, dio); deployImplementations.deployPreimageOracleSingleton(dii, dio);
assertEq(srPreimageOracleSingleton, address(dio.preimageOracleSingleton()));
address srMipsSingleton = address(0x16e83cE5Ce29BF90AD9Da06D2fE6a15d5f344ce4);
vm.etch(address(srMipsSingleton), hex"01");
deployImplementations.deployMipsSingleton(dii, dio); deployImplementations.deployMipsSingleton(dii, dio);
assertEq(srMipsSingleton, address(dio.mipsSingleton())); deployImplementations.deployDisputeGameFactoryImpl(dio);
deployImplementations.deployOPContractsManager(dii, dio);
address srDisputeGameFactoryImpl = address(0xc641A33cab81C559F2bd4b21EA34C290E2440C2B);
vm.etch(address(srDisputeGameFactoryImpl), hex"01"); // Store the original addresses.
deployImplementations.deployDisputeGameFactoryImpl(dii, dio); address systemConfigImpl = address(dio.systemConfigImpl());
assertEq(srDisputeGameFactoryImpl, address(dio.disputeGameFactoryImpl())); address l1CrossDomainMessengerImpl = address(dio.l1CrossDomainMessengerImpl());
address l1ERC721BridgeImpl = address(dio.l1ERC721BridgeImpl());
address l1StandardBridgeImpl = address(dio.l1StandardBridgeImpl());
address optimismMintableERC20FactoryImpl = address(dio.optimismMintableERC20FactoryImpl());
address optimismPortalImpl = address(dio.optimismPortalImpl());
address delayedWETHImpl = address(dio.delayedWETHImpl());
address preimageOracleSingleton = address(dio.preimageOracleSingleton());
address mipsSingleton = address(dio.mipsSingleton());
address disputeGameFactoryImpl = address(dio.disputeGameFactoryImpl());
address opcm = address(dio.opcm());
// Do the deployments again. Thi should be a noop.
deployImplementations.deploySystemConfigImpl(dio);
deployImplementations.deployL1CrossDomainMessengerImpl(dio);
deployImplementations.deployL1ERC721BridgeImpl(dio);
deployImplementations.deployL1StandardBridgeImpl(dio);
deployImplementations.deployOptimismMintableERC20FactoryImpl(dio);
deployImplementations.deployOptimismPortalImpl(dii, dio);
deployImplementations.deployDelayedWETHImpl(dii, dio);
deployImplementations.deployPreimageOracleSingleton(dii, dio);
deployImplementations.deployMipsSingleton(dii, dio);
deployImplementations.deployDisputeGameFactoryImpl(dio);
deployImplementations.deployOPContractsManager(dii, dio);
// Assert that the addresses did not change.
assertEq(systemConfigImpl, address(dio.systemConfigImpl()), "100");
assertEq(l1CrossDomainMessengerImpl, address(dio.l1CrossDomainMessengerImpl()), "200");
assertEq(l1ERC721BridgeImpl, address(dio.l1ERC721BridgeImpl()), "300");
assertEq(l1StandardBridgeImpl, address(dio.l1StandardBridgeImpl()), "400");
assertEq(optimismMintableERC20FactoryImpl, address(dio.optimismMintableERC20FactoryImpl()), "500");
assertEq(optimismPortalImpl, address(dio.optimismPortalImpl()), "600");
assertEq(delayedWETHImpl, address(dio.delayedWETHImpl()), "700");
assertEq(preimageOracleSingleton, address(dio.preimageOracleSingleton()), "800");
assertEq(mipsSingleton, address(dio.mipsSingleton()), "900");
assertEq(disputeGameFactoryImpl, address(dio.disputeGameFactoryImpl()), "1000");
assertEq(opcm, address(dio.opcm()), "1100");
} }
function testFuzz_run_memory_succeeds(bytes32 _seed) public { function testFuzz_run_memory_succeeds(bytes32 _seed) public {
......
...@@ -398,11 +398,6 @@ contract DeployOPChain_TestBase is Test { ...@@ -398,11 +398,6 @@ contract DeployOPChain_TestBase is Test {
dii.set(dii.l1ContractsRelease.selector, release); dii.set(dii.l1ContractsRelease.selector, release);
dii.set(dii.superchainConfigProxy.selector, address(superchainConfigProxy)); dii.set(dii.superchainConfigProxy.selector, address(superchainConfigProxy));
dii.set(dii.protocolVersionsProxy.selector, address(protocolVersionsProxy)); dii.set(dii.protocolVersionsProxy.selector, address(protocolVersionsProxy));
// End users of the DeployImplementations contract will need to set the `standardVersionsToml`.
string memory standardVersionsTomlPath =
string.concat(vm.projectRoot(), "/test/fixtures/standard-versions.toml");
string memory standardVersionsToml = vm.readFile(standardVersionsTomlPath);
dii.set(dii.standardVersionsToml.selector, standardVersionsToml);
deployImplementations.run(dii, dio); deployImplementations.run(dii, dio);
......
...@@ -234,6 +234,15 @@ contract DeploySuperchain_Test is Test { ...@@ -234,6 +234,15 @@ contract DeploySuperchain_Test is Test {
vm.store(address(dsi), bytes32(slot), bytes32(unwrap(defaultRecommendedProtocolVersion))); vm.store(address(dsi), bytes32(slot), bytes32(unwrap(defaultRecommendedProtocolVersion)));
} }
function test_deploySuperchainImplementationContracts_reuseAddresses_succeeds() public {
deploySuperchain.deploySuperchainImplementationContracts(dsi, dso);
address originalConfig = address(dso.superchainConfigImpl());
address originalProtocolVersions = address(dso.protocolVersionsImpl());
deploySuperchain.deploySuperchainImplementationContracts(dsi, dso);
assertEq(address(dso.superchainConfigImpl()), originalConfig, "100");
assertEq(address(dso.protocolVersionsImpl()), originalProtocolVersions, "200");
}
function zeroOutSlotForSelector(bytes4 _selector) internal returns (uint256 slot_) { function zeroOutSlotForSelector(bytes4 _selector) internal returns (uint256 slot_) {
slot_ = stdstore.enable_packed_slots().target(address(dsi)).sig(_selector).find(); slot_ = stdstore.enable_packed_slots().target(address(dsi)).sig(_selector).find();
vm.store(address(dsi), bytes32(slot_), bytes32(0)); vm.store(address(dsi), bytes32(slot_), bytes32(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