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
PrevRandao: cfg.L1GenesisBlockMixHash,
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
}
......
......@@ -292,12 +292,8 @@ contract Deploy is Deployer {
dii.set(dii.mipsVersion.selector, Config.useMultithreadedCannon() ? 2 : 1);
string memory release = "dev";
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.protocolVersionsProxy.selector, artifacts.mustGetAddress("ProtocolVersionsProxy"));
dii.set(dii.salt.selector, _implSalt());
if (_isInterop) {
di = DeployImplementations(new DeployImplementationsInterop());
......
......@@ -26,15 +26,12 @@ import { OPContractsManagerInterop } from "src/L1/OPContractsManagerInterop.sol"
import { IOptimismPortalInterop } from "interfaces/L1/IOptimismPortalInterop.sol";
import { ISystemConfigInterop } from "interfaces/L1/ISystemConfigInterop.sol";
import { Blueprint } from "src/libraries/Blueprint.sol";
import { DeployUtils } from "scripts/libraries/DeployUtils.sol";
import { Solarray } from "scripts/libraries/Solarray.sol";
import { BaseDeployIO } from "scripts/deploy/BaseDeployIO.sol";
// See DeploySuperchain.s.sol for detailed comments on the script architecture used here.
contract DeployImplementationsInput is BaseDeployIO {
bytes32 internal _salt;
uint256 internal _withdrawalDelaySeconds;
uint256 internal _minProposalSizeBytes;
uint256 internal _challengePeriodSeconds;
......@@ -50,8 +47,6 @@ contract DeployImplementationsInput is BaseDeployIO {
ISuperchainConfig internal _superchainConfigProxy;
IProtocolVersions internal _protocolVersionsProxy;
string internal _standardVersionsToml;
function set(bytes4 _sel, uint256 _value) public {
require(_value != 0, "DeployImplementationsInput: cannot set zero value");
......@@ -76,7 +71,6 @@ contract DeployImplementationsInput is BaseDeployIO {
function set(bytes4 _sel, string memory _value) public {
require(!LibString.eq(_value, ""), "DeployImplementationsInput: cannot set empty string");
if (_sel == this.l1ContractsRelease.selector) _l1ContractsRelease = _value;
else if (_sel == this.standardVersionsToml.selector) _standardVersionsToml = _value;
else revert("DeployImplementationsInput: unknown selector");
}
......@@ -87,16 +81,6 @@ contract DeployImplementationsInput is BaseDeployIO {
else revert("DeployImplementationsInput: unknown selector");
}
function set(bytes4 _sel, bytes32 _value) public {
if (_sel == this.salt.selector) _salt = _value;
else revert("DeployImplementationsInput: unknown selector");
}
function salt() public view returns (bytes32) {
// TODO check if implementations are deployed based on code+salt and skip deploy if so.
return _salt;
}
function withdrawalDelaySeconds() public view returns (uint256) {
require(_withdrawalDelaySeconds != 0, "DeployImplementationsInput: not set");
return _withdrawalDelaySeconds;
......@@ -135,11 +119,6 @@ contract DeployImplementationsInput is BaseDeployIO {
return _l1ContractsRelease;
}
function standardVersionsToml() public view returns (string memory) {
require(!LibString.eq(_standardVersionsToml, ""), "DeployImplementationsInput: not set");
return _standardVersionsToml;
}
function superchainConfigProxy() public view returns (ISuperchainConfig) {
require(address(_superchainConfigProxy) != address(0), "DeployImplementationsInput: not set");
return _superchainConfigProxy;
......@@ -411,20 +390,22 @@ contract DeployImplementationsOutput is BaseDeployIO {
}
contract DeployImplementations is Script {
bytes32 internal _salt = DeployUtils.DEFAULT_SALT;
// -------- Core Deployment Methods --------
function run(DeployImplementationsInput _dii, DeployImplementationsOutput _dio) public {
// Deploy the implementations.
deploySystemConfigImpl(_dii, _dio);
deployL1CrossDomainMessengerImpl(_dii, _dio);
deployL1ERC721BridgeImpl(_dii, _dio);
deployL1StandardBridgeImpl(_dii, _dio);
deployOptimismMintableERC20FactoryImpl(_dii, _dio);
deploySystemConfigImpl(_dio);
deployL1CrossDomainMessengerImpl(_dio);
deployL1ERC721BridgeImpl(_dio);
deployL1StandardBridgeImpl(_dio);
deployOptimismMintableERC20FactoryImpl(_dio);
deployOptimismPortalImpl(_dii, _dio);
deployDelayedWETHImpl(_dii, _dio);
deployPreimageOracleSingleton(_dii, _dio);
deployMipsSingleton(_dii, _dio);
deployDisputeGameFactoryImpl(_dii, _dio);
deployDisputeGameFactoryImpl(_dio);
// Deploy the OP Contracts Manager with the new implementations set.
deployOPContractsManager(_dii, _dio);
......@@ -462,8 +443,14 @@ contract DeployImplementations is Script {
});
vm.broadcast(msg.sender);
opcm_ = new OPContractsManager(
superchainConfigProxy, protocolVersionsProxy, _l1ContractsRelease, _blueprints, implementations
opcm_ = OPContractsManager(
DeployUtils.createDeterministic({
_name: "OPContractsManager",
_args: abi.encode(
superchainConfigProxy, protocolVersionsProxy, _l1ContractsRelease, _blueprints, implementations
),
_salt: _salt
})
);
vm.label(address(opcm_), "OPContractsManager");
......@@ -478,42 +465,32 @@ contract DeployImplementations is Script {
virtual
{
string memory l1ContractsRelease = _dii.l1ContractsRelease();
string memory stdVerToml = _dii.standardVersionsToml();
string memory contractName = "op_contracts_manager";
OPContractsManager opcm;
address existingImplementation = getReleaseAddress(l1ContractsRelease, contractName, stdVerToml);
if (existingImplementation != address(0)) {
opcm = OPContractsManager(existingImplementation);
} else {
// First we deploy the blueprints for the singletons deployed by OPCM.
// forgefmt: disable-start
bytes32 salt = _dii.salt();
OPContractsManager.Blueprints memory blueprints;
address checkAddress;
vm.startBroadcast(msg.sender);
(blueprints.addressManager, checkAddress) = Blueprint.create(vm.getCode("AddressManager"), salt);
require(checkAddress == address(0), "OPCM-10");
(blueprints.proxy, checkAddress) = Blueprint.create(vm.getCode("Proxy"), salt);
require(checkAddress == address(0), "OPCM-20");
(blueprints.proxyAdmin, checkAddress) = Blueprint.create(vm.getCode("ProxyAdmin"), salt);
require(checkAddress == address(0), "OPCM-30");
(blueprints.l1ChugSplashProxy, checkAddress) = Blueprint.create(vm.getCode("L1ChugSplashProxy"), salt);
require(checkAddress == address(0), "OPCM-40");
(blueprints.resolvedDelegateProxy, checkAddress) = Blueprint.create(vm.getCode("ResolvedDelegateProxy"), salt);
require(checkAddress == address(0), "OPCM-50");
(blueprints.anchorStateRegistry, checkAddress) = Blueprint.create(vm.getCode("AnchorStateRegistry"), salt);
require(checkAddress == address(0), "OPCM-60");
// First we deploy the blueprints for the singletons deployed by OPCM.
// forgefmt: disable-start
OPContractsManager.Blueprints memory blueprints;
vm.startBroadcast(msg.sender);
address checkAddress;
(blueprints.addressManager, checkAddress) = DeployUtils.createDeterministicBlueprint(vm.getCode("AddressManager"), _salt);
require(checkAddress == address(0), "OPCM-10");
(blueprints.proxy, checkAddress) = DeployUtils.createDeterministicBlueprint(vm.getCode("Proxy"), _salt);
require(checkAddress == address(0), "OPCM-20");
(blueprints.proxyAdmin, checkAddress) = DeployUtils.createDeterministicBlueprint(vm.getCode("ProxyAdmin"), _salt);
require(checkAddress == address(0), "OPCM-30");
(blueprints.l1ChugSplashProxy, checkAddress) = DeployUtils.createDeterministicBlueprint(vm.getCode("L1ChugSplashProxy"), _salt);
require(checkAddress == address(0), "OPCM-40");
(blueprints.resolvedDelegateProxy, checkAddress) = DeployUtils.createDeterministicBlueprint(vm.getCode("ResolvedDelegateProxy"), _salt);
require(checkAddress == address(0), "OPCM-50");
(blueprints.anchorStateRegistry, checkAddress) = DeployUtils.createDeterministicBlueprint(vm.getCode("AnchorStateRegistry"), _salt);
require(checkAddress == address(0), "OPCM-60");
// The max initcode/runtimecode size is 48KB/24KB.
// But for Blueprint, the initcode is stored as runtime code, that's why it's necessary to split into 2 parts.
(blueprints.permissionedDisputeGame1, blueprints.permissionedDisputeGame2) = Blueprint.create(vm.getCode("PermissionedDisputeGame"), salt);
(blueprints.permissionlessDisputeGame1, blueprints.permissionlessDisputeGame2) = Blueprint.create(vm.getCode("FaultDisputeGame"), salt);
vm.stopBroadcast();
// forgefmt: disable-end
(blueprints.permissionedDisputeGame1, blueprints.permissionedDisputeGame2) = DeployUtils.createDeterministicBlueprint(vm.getCode("PermissionedDisputeGame"), _salt);
(blueprints.permissionlessDisputeGame1, blueprints.permissionlessDisputeGame2) = DeployUtils.createDeterministicBlueprint(vm.getCode("FaultDisputeGame"), _salt);
// forgefmt: disable-end
vm.stopBroadcast();
opcm = createOPCMContract(_dii, _dio, blueprints, l1ContractsRelease);
}
OPContractsManager opcm = createOPCMContract(_dii, _dio, blueprints, l1ContractsRelease);
vm.label(address(opcm), "OPContractsManager");
_dio.set(_dio.opcm.selector, address(opcm));
......@@ -521,143 +498,67 @@ contract DeployImplementations is Script {
// --- Core Contracts ---
function deploySystemConfigImpl(DeployImplementationsInput _dii, DeployImplementationsOutput _dio) public virtual {
string memory release = _dii.l1ContractsRelease();
string memory stdVerToml = _dii.standardVersionsToml();
// Using snake case for contract name to match the TOML file in superchain-registry.
string memory contractName = "system_config";
ISystemConfig impl;
address existingImplementation = getReleaseAddress(release, contractName, stdVerToml);
if (existingImplementation != address(0)) {
impl = ISystemConfig(existingImplementation);
} else {
// Deploy a new implementation for development builds.
vm.broadcast(msg.sender);
impl = ISystemConfig(
DeployUtils.create1({
_name: "SystemConfig",
_args: DeployUtils.encodeConstructor(abi.encodeCall(ISystemConfig.__constructor__, ()))
})
);
}
function deploySystemConfigImpl(DeployImplementationsOutput _dio) public virtual {
vm.broadcast(msg.sender);
ISystemConfig impl = ISystemConfig(
DeployUtils.createDeterministic({
_name: "SystemConfig",
_args: DeployUtils.encodeConstructor(abi.encodeCall(ISystemConfig.__constructor__, ())),
_salt: _salt
})
);
vm.label(address(impl), "SystemConfigImpl");
_dio.set(_dio.systemConfigImpl.selector, address(impl));
}
function deployL1CrossDomainMessengerImpl(
DeployImplementationsInput _dii,
DeployImplementationsOutput _dio
)
public
virtual
{
string memory release = _dii.l1ContractsRelease();
string memory stdVerToml = _dii.standardVersionsToml();
string memory contractName = "l1_cross_domain_messenger";
IL1CrossDomainMessenger impl;
address existingImplementation = getReleaseAddress(release, contractName, stdVerToml);
if (existingImplementation != address(0)) {
impl = IL1CrossDomainMessenger(existingImplementation);
} else {
vm.broadcast(msg.sender);
impl = IL1CrossDomainMessenger(
DeployUtils.create1({
_name: "L1CrossDomainMessenger",
_args: DeployUtils.encodeConstructor(abi.encodeCall(IL1CrossDomainMessenger.__constructor__, ()))
})
);
}
function deployL1CrossDomainMessengerImpl(DeployImplementationsOutput _dio) public virtual {
vm.broadcast(msg.sender);
IL1CrossDomainMessenger impl = IL1CrossDomainMessenger(
DeployUtils.createDeterministic({
_name: "L1CrossDomainMessenger",
_args: DeployUtils.encodeConstructor(abi.encodeCall(IL1CrossDomainMessenger.__constructor__, ())),
_salt: _salt
})
);
vm.label(address(impl), "L1CrossDomainMessengerImpl");
_dio.set(_dio.l1CrossDomainMessengerImpl.selector, address(impl));
}
function deployL1ERC721BridgeImpl(
DeployImplementationsInput _dii,
DeployImplementationsOutput _dio
)
public
virtual
{
string memory release = _dii.l1ContractsRelease();
string memory stdVerToml = _dii.standardVersionsToml();
string memory contractName = "l1_erc721_bridge";
IL1ERC721Bridge impl;
address existingImplementation = getReleaseAddress(release, contractName, stdVerToml);
if (existingImplementation != address(0)) {
impl = IL1ERC721Bridge(existingImplementation);
} else {
vm.broadcast(msg.sender);
impl = IL1ERC721Bridge(
DeployUtils.create1({
_name: "L1ERC721Bridge",
_args: DeployUtils.encodeConstructor(abi.encodeCall(IL1ERC721Bridge.__constructor__, ()))
})
);
}
function deployL1ERC721BridgeImpl(DeployImplementationsOutput _dio) public virtual {
vm.broadcast(msg.sender);
IL1ERC721Bridge impl = IL1ERC721Bridge(
DeployUtils.createDeterministic({
_name: "L1ERC721Bridge",
_args: DeployUtils.encodeConstructor(abi.encodeCall(IL1ERC721Bridge.__constructor__, ())),
_salt: _salt
})
);
vm.label(address(impl), "L1ERC721BridgeImpl");
_dio.set(_dio.l1ERC721BridgeImpl.selector, address(impl));
}
function deployL1StandardBridgeImpl(
DeployImplementationsInput _dii,
DeployImplementationsOutput _dio
)
public
virtual
{
string memory release = _dii.l1ContractsRelease();
string memory stdVerToml = _dii.standardVersionsToml();
string memory contractName = "l1_standard_bridge";
IL1StandardBridge impl;
address existingImplementation = getReleaseAddress(release, contractName, stdVerToml);
if (existingImplementation != address(0)) {
impl = IL1StandardBridge(payable(existingImplementation));
} else {
vm.broadcast(msg.sender);
impl = IL1StandardBridge(
DeployUtils.create1({
_name: "L1StandardBridge",
_args: DeployUtils.encodeConstructor(abi.encodeCall(IL1StandardBridge.__constructor__, ()))
})
);
}
function deployL1StandardBridgeImpl(DeployImplementationsOutput _dio) public virtual {
vm.broadcast(msg.sender);
IL1StandardBridge impl = IL1StandardBridge(
DeployUtils.createDeterministic({
_name: "L1StandardBridge",
_args: DeployUtils.encodeConstructor(abi.encodeCall(IL1StandardBridge.__constructor__, ())),
_salt: _salt
})
);
vm.label(address(impl), "L1StandardBridgeImpl");
_dio.set(_dio.l1StandardBridgeImpl.selector, address(impl));
}
function deployOptimismMintableERC20FactoryImpl(
DeployImplementationsInput _dii,
DeployImplementationsOutput _dio
)
public
virtual
{
string memory release = _dii.l1ContractsRelease();
string memory stdVerToml = _dii.standardVersionsToml();
string memory contractName = "optimism_mintable_erc20_factory";
IOptimismMintableERC20Factory impl;
address existingImplementation = getReleaseAddress(release, contractName, stdVerToml);
if (existingImplementation != address(0)) {
impl = IOptimismMintableERC20Factory(existingImplementation);
} else {
vm.broadcast(msg.sender);
impl = IOptimismMintableERC20Factory(
DeployUtils.create1({
_name: "OptimismMintableERC20Factory",
_args: DeployUtils.encodeConstructor(abi.encodeCall(IOptimismMintableERC20Factory.__constructor__, ()))
})
);
}
function deployOptimismMintableERC20FactoryImpl(DeployImplementationsOutput _dio) public virtual {
vm.broadcast(msg.sender);
IOptimismMintableERC20Factory impl = IOptimismMintableERC20Factory(
DeployUtils.createDeterministic({
_name: "OptimismMintableERC20Factory",
_args: DeployUtils.encodeConstructor(abi.encodeCall(IOptimismMintableERC20Factory.__constructor__, ())),
_salt: _salt
})
);
vm.label(address(impl), "OptimismMintableERC20FactoryImpl");
_dio.set(_dio.optimismMintableERC20FactoryImpl.selector, address(impl));
}
......@@ -706,56 +607,34 @@ contract DeployImplementations is Script {
public
virtual
{
string memory release = _dii.l1ContractsRelease();
string memory stdVerToml = _dii.standardVersionsToml();
string memory contractName = "optimism_portal";
IOptimismPortal2 impl;
address existingImplementation = getReleaseAddress(release, contractName, stdVerToml);
if (existingImplementation != address(0)) {
impl = IOptimismPortal2(payable(existingImplementation));
} else {
uint256 proofMaturityDelaySeconds = _dii.proofMaturityDelaySeconds();
uint256 disputeGameFinalityDelaySeconds = _dii.disputeGameFinalityDelaySeconds();
vm.broadcast(msg.sender);
impl = IOptimismPortal2(
DeployUtils.create1({
_name: "OptimismPortal2",
_args: DeployUtils.encodeConstructor(
abi.encodeCall(
IOptimismPortal2.__constructor__, (proofMaturityDelaySeconds, disputeGameFinalityDelaySeconds)
)
uint256 proofMaturityDelaySeconds = _dii.proofMaturityDelaySeconds();
uint256 disputeGameFinalityDelaySeconds = _dii.disputeGameFinalityDelaySeconds();
vm.broadcast(msg.sender);
IOptimismPortal2 impl = IOptimismPortal2(
DeployUtils.createDeterministic({
_name: "OptimismPortal2",
_args: DeployUtils.encodeConstructor(
abi.encodeCall(
IOptimismPortal2.__constructor__, (proofMaturityDelaySeconds, disputeGameFinalityDelaySeconds)
)
})
);
}
),
_salt: _salt
})
);
vm.label(address(impl), "OptimismPortalImpl");
_dio.set(_dio.optimismPortalImpl.selector, address(impl));
}
function deployDelayedWETHImpl(DeployImplementationsInput _dii, DeployImplementationsOutput _dio) public virtual {
string memory release = _dii.l1ContractsRelease();
string memory stdVerToml = _dii.standardVersionsToml();
string memory contractName = "delayed_weth";
IDelayedWETH impl;
address existingImplementation = getReleaseAddress(release, contractName, stdVerToml);
if (existingImplementation != address(0)) {
impl = IDelayedWETH(payable(existingImplementation));
} else {
uint256 withdrawalDelaySeconds = _dii.withdrawalDelaySeconds();
vm.broadcast(msg.sender);
impl = IDelayedWETH(
DeployUtils.create1({
_name: "DelayedWETH",
_args: DeployUtils.encodeConstructor(
abi.encodeCall(IDelayedWETH.__constructor__, (withdrawalDelaySeconds))
)
})
);
}
uint256 withdrawalDelaySeconds = _dii.withdrawalDelaySeconds();
vm.broadcast(msg.sender);
IDelayedWETH impl = IDelayedWETH(
DeployUtils.createDeterministic({
_name: "DelayedWETH",
_args: DeployUtils.encodeConstructor(abi.encodeCall(IDelayedWETH.__constructor__, (withdrawalDelaySeconds))),
_salt: _salt
})
);
vm.label(address(impl), "DelayedWETHImpl");
_dio.set(_dio.delayedWETHImpl.selector, address(impl));
}
......@@ -767,82 +646,46 @@ contract DeployImplementations is Script {
public
virtual
{
string memory release = _dii.l1ContractsRelease();
string memory stdVerToml = _dii.standardVersionsToml();
string memory contractName = "preimage_oracle";
IPreimageOracle singleton;
address existingImplementation = getReleaseAddress(release, contractName, stdVerToml);
if (existingImplementation != address(0)) {
singleton = IPreimageOracle(payable(existingImplementation));
} else {
uint256 minProposalSizeBytes = _dii.minProposalSizeBytes();
uint256 challengePeriodSeconds = _dii.challengePeriodSeconds();
vm.broadcast(msg.sender);
singleton = IPreimageOracle(
DeployUtils.create1({
_name: "PreimageOracle",
_args: DeployUtils.encodeConstructor(
abi.encodeCall(IPreimageOracle.__constructor__, (minProposalSizeBytes, challengePeriodSeconds))
)
})
);
}
uint256 minProposalSizeBytes = _dii.minProposalSizeBytes();
uint256 challengePeriodSeconds = _dii.challengePeriodSeconds();
vm.broadcast(msg.sender);
IPreimageOracle singleton = IPreimageOracle(
DeployUtils.createDeterministic({
_name: "PreimageOracle",
_args: DeployUtils.encodeConstructor(
abi.encodeCall(IPreimageOracle.__constructor__, (minProposalSizeBytes, challengePeriodSeconds))
),
_salt: _salt
})
);
vm.label(address(singleton), "PreimageOracleSingleton");
_dio.set(_dio.preimageOracleSingleton.selector, address(singleton));
}
function deployMipsSingleton(DeployImplementationsInput _dii, DeployImplementationsOutput _dio) public virtual {
string memory release = _dii.l1ContractsRelease();
string memory stdVerToml = _dii.standardVersionsToml();
string memory contractName = "mips";
IMIPS singleton;
address existingImplementation = getReleaseAddress(release, contractName, stdVerToml);
if (existingImplementation != address(0)) {
singleton = IMIPS(payable(existingImplementation));
} else {
uint256 mipsVersion = _dii.mipsVersion();
IPreimageOracle preimageOracle = IPreimageOracle(address(_dio.preimageOracleSingleton()));
vm.broadcast(msg.sender);
singleton = IMIPS(
DeployUtils.create1({
_name: mipsVersion == 1 ? "MIPS" : "MIPS64",
_args: DeployUtils.encodeConstructor(abi.encodeCall(IMIPS.__constructor__, (preimageOracle)))
})
);
}
uint256 mipsVersion = _dii.mipsVersion();
IPreimageOracle preimageOracle = IPreimageOracle(address(_dio.preimageOracleSingleton()));
vm.broadcast(msg.sender);
IMIPS singleton = IMIPS(
DeployUtils.createDeterministic({
_name: mipsVersion == 1 ? "MIPS" : "MIPS64",
_args: DeployUtils.encodeConstructor(abi.encodeCall(IMIPS.__constructor__, (preimageOracle))),
_salt: _salt
})
);
vm.label(address(singleton), "MIPSSingleton");
_dio.set(_dio.mipsSingleton.selector, address(singleton));
}
function deployDisputeGameFactoryImpl(
DeployImplementationsInput _dii,
DeployImplementationsOutput _dio
)
public
virtual
{
string memory release = _dii.l1ContractsRelease();
string memory stdVerToml = _dii.standardVersionsToml();
string memory contractName = "dispute_game_factory";
IDisputeGameFactory impl;
address existingImplementation = getReleaseAddress(release, contractName, stdVerToml);
if (existingImplementation != address(0)) {
impl = IDisputeGameFactory(payable(existingImplementation));
} else {
vm.broadcast(msg.sender);
impl = IDisputeGameFactory(
DeployUtils.create1({
_name: "DisputeGameFactory",
_args: DeployUtils.encodeConstructor(abi.encodeCall(IDisputeGameFactory.__constructor__, ()))
})
);
}
function deployDisputeGameFactoryImpl(DeployImplementationsOutput _dio) public virtual {
vm.broadcast(msg.sender);
IDisputeGameFactory impl = IDisputeGameFactory(
DeployUtils.createDeterministic({
_name: "DisputeGameFactory",
_args: DeployUtils.encodeConstructor(abi.encodeCall(IDisputeGameFactory.__constructor__, ())),
_salt: _salt
})
);
vm.label(address(impl), "DisputeGameFactoryImpl");
_dio.set(_dio.disputeGameFactoryImpl.selector, address(impl));
}
......@@ -869,30 +712,6 @@ contract DeployImplementations is Script {
dii_ = DeployImplementationsInput(DeployUtils.toIOAddress(msg.sender, "optimism.DeployImplementationsInput"));
dio_ = DeployImplementationsOutput(DeployUtils.toIOAddress(msg.sender, "optimism.DeployImplementationsOutput"));
}
// Zero address is returned if the address is not found in '_standardVersionsToml'.
function getReleaseAddress(
string memory _version,
string memory _contractName,
string memory _standardVersionsToml
)
internal
pure
returns (address addr_)
{
string memory baseKey = string.concat('.releases["', _version, '"].', _contractName);
string memory implAddressKey = string.concat(baseKey, ".implementation_address");
string memory addressKey = string.concat(baseKey, ".address");
try vm.parseTomlAddress(_standardVersionsToml, implAddressKey) returns (address parsedAddr_) {
addr_ = parsedAddr_;
} catch {
try vm.parseTomlAddress(_standardVersionsToml, addressKey) returns (address parsedAddr_) {
addr_ = parsedAddr_;
} catch {
addr_ = address(0);
}
}
}
}
// Similar to how DeploySuperchain.s.sol contains a lot of comments to thoroughly document the script
......@@ -955,8 +774,14 @@ contract DeployImplementationsInterop is DeployImplementations {
});
vm.broadcast(msg.sender);
opcm_ = new OPContractsManagerInterop(
superchainConfigProxy, protocolVersionsProxy, _l1ContractsRelease, _blueprints, implementations
opcm_ = OPContractsManagerInterop(
DeployUtils.createDeterministic({
_name: "OPContractsManagerInterop",
_args: abi.encode(
superchainConfigProxy, protocolVersionsProxy, _l1ContractsRelease, _blueprints, implementations
),
_salt: _salt
})
);
vm.label(address(opcm_), "OPContractsManager");
......@@ -970,61 +795,34 @@ contract DeployImplementationsInterop is DeployImplementations {
public
override
{
string memory release = _dii.l1ContractsRelease();
string memory stdVerToml = _dii.standardVersionsToml();
string memory contractName = "optimism_portal";
IOptimismPortalInterop impl;
address existingImplementation = getReleaseAddress(release, contractName, stdVerToml);
if (existingImplementation != address(0)) {
impl = IOptimismPortalInterop(payable(existingImplementation));
} else {
uint256 proofMaturityDelaySeconds = _dii.proofMaturityDelaySeconds();
uint256 disputeGameFinalityDelaySeconds = _dii.disputeGameFinalityDelaySeconds();
vm.broadcast(msg.sender);
impl = IOptimismPortalInterop(
DeployUtils.create1({
_name: "OptimismPortalInterop",
_args: DeployUtils.encodeConstructor(
abi.encodeCall(
IOptimismPortalInterop.__constructor__,
(proofMaturityDelaySeconds, disputeGameFinalityDelaySeconds)
)
uint256 proofMaturityDelaySeconds = _dii.proofMaturityDelaySeconds();
uint256 disputeGameFinalityDelaySeconds = _dii.disputeGameFinalityDelaySeconds();
vm.broadcast(msg.sender);
IOptimismPortalInterop impl = IOptimismPortalInterop(
DeployUtils.createDeterministic({
_name: "OptimismPortalInterop",
_args: DeployUtils.encodeConstructor(
abi.encodeCall(
IOptimismPortalInterop.__constructor__, (proofMaturityDelaySeconds, disputeGameFinalityDelaySeconds)
)
})
);
}
),
_salt: _salt
})
);
vm.label(address(impl), "OptimismPortalImpl");
_dio.set(_dio.optimismPortalImpl.selector, address(impl));
}
function deploySystemConfigImpl(
DeployImplementationsInput _dii,
DeployImplementationsOutput _dio
)
public
override
{
string memory release = _dii.l1ContractsRelease();
string memory stdVerToml = _dii.standardVersionsToml();
string memory contractName = "system_config";
ISystemConfigInterop impl;
address existingImplementation = getReleaseAddress(release, contractName, stdVerToml);
if (existingImplementation != address(0)) {
impl = ISystemConfigInterop(existingImplementation);
} else {
vm.broadcast(msg.sender);
impl = ISystemConfigInterop(
DeployUtils.create1({
_name: "SystemConfigInterop",
_args: DeployUtils.encodeConstructor(abi.encodeCall(ISystemConfigInterop.__constructor__, ()))
})
);
}
function deploySystemConfigImpl(DeployImplementationsOutput _dio) public override {
vm.broadcast(msg.sender);
ISystemConfigInterop impl = ISystemConfigInterop(
DeployUtils.createDeterministic({
_name: "SystemConfigInterop",
_args: DeployUtils.encodeConstructor(abi.encodeCall(ISystemConfigInterop.__constructor__, ())),
_salt: _salt
})
);
vm.label(address(impl), "SystemConfigImpl");
_dio.set(_dio.systemConfigImpl.selector, address(impl));
}
......
......@@ -292,6 +292,8 @@ contract DeploySuperchainOutput is BaseDeployIO {
// 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.
contract DeploySuperchain is Script {
bytes32 internal _salt = DeployUtils.DEFAULT_SALT;
// -------- Core Deployment Methods --------
function run(DeploySuperchainInput _dsi, DeploySuperchainOutput _dso) public {
......@@ -342,15 +344,17 @@ contract DeploySuperchain is Script {
// Deploy implementation contracts.
vm.startBroadcast(msg.sender);
ISuperchainConfig superchainConfigImpl = ISuperchainConfig(
DeployUtils.create1({
DeployUtils.createDeterministic({
_name: "SuperchainConfig",
_args: DeployUtils.encodeConstructor(abi.encodeCall(ISuperchainConfig.__constructor__, ()))
_args: DeployUtils.encodeConstructor(abi.encodeCall(ISuperchainConfig.__constructor__, ())),
_salt: _salt
})
);
IProtocolVersions protocolVersionsImpl = IProtocolVersions(
DeployUtils.create1({
DeployUtils.createDeterministic({
_name: "ProtocolVersions",
_args: DeployUtils.encodeConstructor(abi.encodeCall(IProtocolVersions.__constructor__, ()))
_args: DeployUtils.encodeConstructor(abi.encodeCall(IProtocolVersions.__constructor__, ())),
_salt: _salt
})
);
vm.stopBroadcast();
......
......@@ -10,6 +10,7 @@ import { Artifacts } from "scripts/Artifacts.s.sol";
import { LibString } from "@solady/utils/LibString.sol";
import { Bytes } from "src/libraries/Bytes.sol";
import { Constants } from "src/libraries/Constants.sol";
import { Blueprint } from "src/libraries/Blueprint.sol";
// Interfaces
import { IProxy } from "interfaces/universal/IProxy.sol";
......@@ -20,6 +21,8 @@ import { IResolvedDelegateProxy } from "interfaces/legacy/IResolvedDelegateProxy
library DeployUtils {
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.
/// @param _name Name of the contract to deploy.
/// @param _args ABI-encoded constructor arguments.
......@@ -97,19 +100,11 @@ library DeployUtils {
/// @param _args ABI-encoded constructor arguments.
/// @param _salt Salt for the CREATE2 operation.
/// @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);
address preComputedAddress = vm.computeCreate2Address(_salt, keccak256(initCode));
require(preComputedAddress.code.length == 0, "DeployUtils: contract already deployed");
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_);
return create2asm(initCode, _salt);
}
/// @notice Deploys a contract with the given name via CREATE2.
......@@ -120,6 +115,18 @@ library DeployUtils {
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.
/// @param _save Artifacts contract.
/// @param _name Name of the contract to deploy.
......@@ -195,6 +202,64 @@ library DeployUtils {
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
/// 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
......
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 {
vm.expectRevert("DeployImplementationsInput: not set");
dii.protocolVersionsProxy();
vm.expectRevert("DeployImplementationsInput: not set");
dii.standardVersionsToml();
}
}
......@@ -225,14 +222,10 @@ contract DeployImplementations_Test is Test {
IProtocolVersions protocolVersionsProxy = IProtocolVersions(makeAddr("protocolVersionsProxy"));
function setUp() public virtual {
vm.etch(address(superchainConfigProxy), hex"01");
vm.etch(address(protocolVersionsProxy), hex"01");
deployImplementations = new DeployImplementations();
(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
......@@ -247,67 +240,73 @@ contract DeployImplementations_Test is Test {
}
function test_deployImplementation_succeeds() public {
string memory deployContractsRelease = "dev-release";
dii.set(dii.l1ContractsRelease.selector, deployContractsRelease);
deployImplementations.deploySystemConfigImpl(dii, dio);
deployImplementations.deploySystemConfigImpl(dio);
assertTrue(address(0) != address(dio.systemConfigImpl()));
}
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";
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);
address srSystemConfigImpl = address(0xF56D96B2535B932656d3c04Ebf51baBff241D886);
vm.etch(address(srSystemConfigImpl), hex"01");
assertEq(srSystemConfigImpl, address(dio.systemConfigImpl()));
address srL1CrossDomainMessengerImpl = address(0xD3494713A5cfaD3F5359379DfA074E2Ac8C6Fd65);
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");
// Perform the initial deployment.
deployImplementations.deploySystemConfigImpl(dio);
deployImplementations.deployL1CrossDomainMessengerImpl(dio);
deployImplementations.deployL1ERC721BridgeImpl(dio);
deployImplementations.deployL1StandardBridgeImpl(dio);
deployImplementations.deployOptimismMintableERC20FactoryImpl(dio);
deployImplementations.deployOptimismPortalImpl(dii, dio);
assertEq(srOptimismPortalImpl, address(dio.optimismPortalImpl()));
address srDelayedWETHImpl = address(0x71e966Ae981d1ce531a7b6d23DC0f27B38409087);
vm.etch(address(srDelayedWETHImpl), hex"01");
deployImplementations.deployDelayedWETHImpl(dii, dio);
assertEq(srDelayedWETHImpl, address(dio.delayedWETHImpl()));
address srPreimageOracleSingleton = address(0x9c065e11870B891D214Bc2Da7EF1f9DDFA1BE277);
vm.etch(address(srPreimageOracleSingleton), hex"01");
deployImplementations.deployPreimageOracleSingleton(dii, dio);
assertEq(srPreimageOracleSingleton, address(dio.preimageOracleSingleton()));
address srMipsSingleton = address(0x16e83cE5Ce29BF90AD9Da06D2fE6a15d5f344ce4);
vm.etch(address(srMipsSingleton), hex"01");
deployImplementations.deployMipsSingleton(dii, dio);
assertEq(srMipsSingleton, address(dio.mipsSingleton()));
address srDisputeGameFactoryImpl = address(0xc641A33cab81C559F2bd4b21EA34C290E2440C2B);
vm.etch(address(srDisputeGameFactoryImpl), hex"01");
deployImplementations.deployDisputeGameFactoryImpl(dii, dio);
assertEq(srDisputeGameFactoryImpl, address(dio.disputeGameFactoryImpl()));
deployImplementations.deployDisputeGameFactoryImpl(dio);
deployImplementations.deployOPContractsManager(dii, dio);
// Store the original addresses.
address systemConfigImpl = address(dio.systemConfigImpl());
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 {
......
......@@ -398,11 +398,6 @@ contract DeployOPChain_TestBase is Test {
dii.set(dii.l1ContractsRelease.selector, release);
dii.set(dii.superchainConfigProxy.selector, address(superchainConfigProxy));
dii.set(dii.protocolVersionsProxy.selector, address(protocolVersionsProxy));
// End users of the DeployImplementations contract will need to set the `standardVersionsToml`.
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);
......
......@@ -234,6 +234,15 @@ contract DeploySuperchain_Test is Test {
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_) {
slot_ = stdstore.enable_packed_slots().target(address(dsi)).sig(_selector).find();
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