Commit ef1bf0ac authored by Matt Solomon's avatar Matt Solomon Committed by GitHub

opsm: remove remaining structs (#11854)

* refactor: remove structs from DeployImplementations

* refactor: remove structs from DeployOPChain

* test: fix tests

* Update packages/contracts-bedrock/test/DeployOPChain.t.sol
Co-authored-by: default avatarBlaine Malone <blainemalone01@gmail.com>

* Update packages/contracts-bedrock/test/DeployOPChain.t.sol
Co-authored-by: default avatarBlaine Malone <blainemalone01@gmail.com>

* test: add missing assertions

* fix: update fuzz test timeout

---------
Co-authored-by: default avatarBlaine Malone <blainemalone01@gmail.com>
Co-authored-by: default avatarKelvin Fichter <kelvinfichter@gmail.com>
parent 935de9cb
...@@ -3,6 +3,8 @@ pragma solidity 0.8.15; ...@@ -3,6 +3,8 @@ pragma solidity 0.8.15;
import { Script } from "forge-std/Script.sol"; import { Script } from "forge-std/Script.sol";
import { LibString } from "@solady/utils/LibString.sol";
import { ProxyAdmin } from "src/universal/ProxyAdmin.sol"; import { ProxyAdmin } from "src/universal/ProxyAdmin.sol";
import { Proxy } from "src/universal/Proxy.sol"; import { Proxy } from "src/universal/Proxy.sol";
import { L1ChugSplashProxy } from "src/legacy/L1ChugSplashProxy.sol"; import { L1ChugSplashProxy } from "src/legacy/L1ChugSplashProxy.sol";
...@@ -36,119 +38,128 @@ import { Solarray } from "scripts/libraries/Solarray.sol"; ...@@ -36,119 +38,128 @@ import { Solarray } from "scripts/libraries/Solarray.sol";
// See DeploySuperchain.s.sol for detailed comments on the script architecture used here. // See DeploySuperchain.s.sol for detailed comments on the script architecture used here.
contract DeployImplementationsInput { contract DeployImplementationsInput {
struct Input { uint256 internal _withdrawalDelaySeconds;
uint256 withdrawalDelaySeconds; uint256 internal _minProposalSizeBytes;
uint256 minProposalSizeBytes; uint256 internal _challengePeriodSeconds;
uint256 challengePeriodSeconds; uint256 internal _proofMaturityDelaySeconds;
uint256 proofMaturityDelaySeconds; uint256 internal _disputeGameFinalityDelaySeconds;
uint256 disputeGameFinalityDelaySeconds;
// We also deploy OP Stack Manager here, which has a dependency on the prior step of deploying // The release version to set OPSM implementations for, of the format `op-contracts/vX.Y.Z`.
// the superchain contracts. string internal _release;
string release; // The release version to set OPSM implementations for, of the format `op-contracts/vX.Y.Z`.
SuperchainConfig superchainConfigProxy; // Outputs from DeploySuperchain.s.sol.
ProtocolVersions protocolVersionsProxy; SuperchainConfig internal _superchainConfigProxy;
} ProtocolVersions internal _protocolVersionsProxy;
bool public inputSet = false; function set(bytes4 sel, uint256 _value) public {
Input internal inputs; require(_value != 0, "DeployImplementationsInput: cannot set zero value");
function loadInputFile(string memory _infile) public { if (sel == this.withdrawalDelaySeconds.selector) {
_infile; _withdrawalDelaySeconds = _value;
Input memory parsedInput; } else if (sel == this.minProposalSizeBytes.selector) {
loadInput(parsedInput); _minProposalSizeBytes = _value;
require(false, "DeployImplementationsInput: not implemented"); } else if (sel == this.challengePeriodSeconds.selector) {
require(_value <= type(uint64).max, "DeployImplementationsInput: challengePeriodSeconds too large");
_challengePeriodSeconds = _value;
} else if (sel == this.proofMaturityDelaySeconds.selector) {
_proofMaturityDelaySeconds = _value;
} else if (sel == this.disputeGameFinalityDelaySeconds.selector) {
_disputeGameFinalityDelaySeconds = _value;
} else {
revert("DeployImplementationsInput: unknown selector");
}
} }
function loadInput(Input memory _input) public { function set(bytes4 sel, string memory _value) public {
require(!inputSet, "DeployImplementationsInput: input already set"); require(!LibString.eq(_value, ""), "DeployImplementationsInput: cannot set empty string");
require( if (sel == this.release.selector) _release = _value;
_input.challengePeriodSeconds <= type(uint64).max, "DeployImplementationsInput: challenge period too large" else revert("DeployImplementationsInput: unknown selector");
);
inputSet = true;
inputs = _input;
} }
function assertInputSet() internal view { function set(bytes4 sel, address _addr) public {
require(inputSet, "DeployImplementationsInput: input not set"); require(_addr != address(0), "DeployImplementationsInput: cannot set zero address");
if (sel == this.superchainConfigProxy.selector) _superchainConfigProxy = SuperchainConfig(_addr);
else if (sel == this.protocolVersionsProxy.selector) _protocolVersionsProxy = ProtocolVersions(_addr);
else revert("DeployImplementationsInput: unknown selector");
} }
function input() public view returns (Input memory) { function loadInputFile(string memory _infile) public pure {
assertInputSet(); _infile;
return inputs; require(false, "DeployImplementationsInput: not implemented");
} }
function withdrawalDelaySeconds() public view returns (uint256) { function withdrawalDelaySeconds() public view returns (uint256) {
assertInputSet(); require(_withdrawalDelaySeconds != 0, "DeployImplementationsInput: not set");
return inputs.withdrawalDelaySeconds; return _withdrawalDelaySeconds;
} }
function minProposalSizeBytes() public view returns (uint256) { function minProposalSizeBytes() public view returns (uint256) {
assertInputSet(); require(_minProposalSizeBytes != 0, "DeployImplementationsInput: not set");
return inputs.minProposalSizeBytes; return _minProposalSizeBytes;
} }
function challengePeriodSeconds() public view returns (uint256) { function challengePeriodSeconds() public view returns (uint256) {
assertInputSet(); require(_challengePeriodSeconds != 0, "DeployImplementationsInput: not set");
return inputs.challengePeriodSeconds; require(
_challengePeriodSeconds <= type(uint64).max, "DeployImplementationsInput: challengePeriodSeconds too large"
);
return _challengePeriodSeconds;
} }
function proofMaturityDelaySeconds() public view returns (uint256) { function proofMaturityDelaySeconds() public view returns (uint256) {
assertInputSet(); require(_proofMaturityDelaySeconds != 0, "DeployImplementationsInput: not set");
return inputs.proofMaturityDelaySeconds; return _proofMaturityDelaySeconds;
} }
function disputeGameFinalityDelaySeconds() public view returns (uint256) { function disputeGameFinalityDelaySeconds() public view returns (uint256) {
assertInputSet(); require(_disputeGameFinalityDelaySeconds != 0, "DeployImplementationsInput: not set");
return inputs.disputeGameFinalityDelaySeconds; return _disputeGameFinalityDelaySeconds;
} }
function release() public view returns (string memory) { function release() public view returns (string memory) {
assertInputSet(); require(!LibString.eq(_release, ""), "DeployImplementationsInput: not set");
return inputs.release; return _release;
} }
function superchainConfigProxy() public view returns (SuperchainConfig) { function superchainConfigProxy() public view returns (SuperchainConfig) {
assertInputSet(); require(address(_superchainConfigProxy) != address(0), "DeployImplementationsInput: not set");
return inputs.superchainConfigProxy; return _superchainConfigProxy;
} }
function protocolVersionsProxy() public view returns (ProtocolVersions) { function protocolVersionsProxy() public view returns (ProtocolVersions) {
assertInputSet(); require(address(_protocolVersionsProxy) != address(0), "DeployImplementationsInput: not set");
return inputs.protocolVersionsProxy; return _protocolVersionsProxy;
} }
} }
contract DeployImplementationsOutput { contract DeployImplementationsOutput {
struct Output { OPStackManager internal _opsm;
OPStackManager opsm; DelayedWETH internal _delayedWETHImpl;
DelayedWETH delayedWETHImpl; OptimismPortal2 internal _optimismPortalImpl;
OptimismPortal2 optimismPortalImpl; PreimageOracle internal _preimageOracleSingleton;
PreimageOracle preimageOracleSingleton; MIPS internal _mipsSingleton;
MIPS mipsSingleton; SystemConfig internal _systemConfigImpl;
SystemConfig systemConfigImpl; L1CrossDomainMessenger internal _l1CrossDomainMessengerImpl;
L1CrossDomainMessenger l1CrossDomainMessengerImpl; L1ERC721Bridge internal _l1ERC721BridgeImpl;
L1ERC721Bridge l1ERC721BridgeImpl; L1StandardBridge internal _l1StandardBridgeImpl;
L1StandardBridge l1StandardBridgeImpl; OptimismMintableERC20Factory internal _optimismMintableERC20FactoryImpl;
OptimismMintableERC20Factory optimismMintableERC20FactoryImpl; DisputeGameFactory internal _disputeGameFactoryImpl;
DisputeGameFactory disputeGameFactoryImpl;
}
Output internal outputs;
function set(bytes4 sel, address _addr) public { function set(bytes4 sel, address _addr) public {
require(_addr != address(0), "DeployImplementationsOutput: cannot set zero address");
// forgefmt: disable-start // forgefmt: disable-start
if (sel == this.opsm.selector) outputs.opsm = OPStackManager(payable(_addr)); if (sel == this.opsm.selector) _opsm = OPStackManager(payable(_addr));
else if (sel == this.optimismPortalImpl.selector) outputs.optimismPortalImpl = OptimismPortal2(payable(_addr)); else if (sel == this.optimismPortalImpl.selector) _optimismPortalImpl = OptimismPortal2(payable(_addr));
else if (sel == this.delayedWETHImpl.selector) outputs.delayedWETHImpl = DelayedWETH(payable(_addr)); else if (sel == this.delayedWETHImpl.selector) _delayedWETHImpl = DelayedWETH(payable(_addr));
else if (sel == this.preimageOracleSingleton.selector) outputs.preimageOracleSingleton = PreimageOracle(_addr); else if (sel == this.preimageOracleSingleton.selector) _preimageOracleSingleton = PreimageOracle(_addr);
else if (sel == this.mipsSingleton.selector) outputs.mipsSingleton = MIPS(_addr); else if (sel == this.mipsSingleton.selector) _mipsSingleton = MIPS(_addr);
else if (sel == this.systemConfigImpl.selector) outputs.systemConfigImpl = SystemConfig(_addr); else if (sel == this.systemConfigImpl.selector) _systemConfigImpl = SystemConfig(_addr);
else if (sel == this.l1CrossDomainMessengerImpl.selector) outputs.l1CrossDomainMessengerImpl = L1CrossDomainMessenger(_addr); else if (sel == this.l1CrossDomainMessengerImpl.selector) _l1CrossDomainMessengerImpl = L1CrossDomainMessenger(_addr);
else if (sel == this.l1ERC721BridgeImpl.selector) outputs.l1ERC721BridgeImpl = L1ERC721Bridge(_addr); else if (sel == this.l1ERC721BridgeImpl.selector) _l1ERC721BridgeImpl = L1ERC721Bridge(_addr);
else if (sel == this.l1StandardBridgeImpl.selector) outputs.l1StandardBridgeImpl = L1StandardBridge(payable(_addr)); else if (sel == this.l1StandardBridgeImpl.selector) _l1StandardBridgeImpl = L1StandardBridge(payable(_addr));
else if (sel == this.optimismMintableERC20FactoryImpl.selector) outputs.optimismMintableERC20FactoryImpl = OptimismMintableERC20Factory(_addr); else if (sel == this.optimismMintableERC20FactoryImpl.selector) _optimismMintableERC20FactoryImpl = OptimismMintableERC20Factory(_addr);
else if (sel == this.disputeGameFactoryImpl.selector) outputs.disputeGameFactoryImpl = DisputeGameFactory(_addr); else if (sel == this.disputeGameFactoryImpl.selector) _disputeGameFactoryImpl = DisputeGameFactory(_addr);
else revert("DeployImplementationsOutput: unknown selector"); else revert("DeployImplementationsOutput: unknown selector");
// forgefmt: disable-end // forgefmt: disable-end
} }
...@@ -158,80 +169,76 @@ contract DeployImplementationsOutput { ...@@ -158,80 +169,76 @@ contract DeployImplementationsOutput {
require(false, "DeployImplementationsOutput: not implemented"); require(false, "DeployImplementationsOutput: not implemented");
} }
function output() public view returns (Output memory) {
return outputs;
}
function checkOutput() public view { function checkOutput() public view {
address[] memory addrs = Solarray.addresses( address[] memory addrs = Solarray.addresses(
address(outputs.opsm), address(this.opsm()),
address(outputs.optimismPortalImpl), address(this.optimismPortalImpl()),
address(outputs.delayedWETHImpl), address(this.delayedWETHImpl()),
address(outputs.preimageOracleSingleton), address(this.preimageOracleSingleton()),
address(outputs.mipsSingleton), address(this.mipsSingleton()),
address(outputs.systemConfigImpl), address(this.systemConfigImpl()),
address(outputs.l1CrossDomainMessengerImpl), address(this.l1CrossDomainMessengerImpl()),
address(outputs.l1ERC721BridgeImpl), address(this.l1ERC721BridgeImpl()),
address(outputs.l1StandardBridgeImpl), address(this.l1StandardBridgeImpl()),
address(outputs.optimismMintableERC20FactoryImpl), address(this.optimismMintableERC20FactoryImpl()),
address(outputs.disputeGameFactoryImpl) address(this.disputeGameFactoryImpl())
); );
DeployUtils.assertValidContractAddresses(addrs); DeployUtils.assertValidContractAddresses(addrs);
} }
function opsm() public view returns (OPStackManager) { function opsm() public view returns (OPStackManager) {
DeployUtils.assertValidContractAddress(address(outputs.opsm)); DeployUtils.assertValidContractAddress(address(_opsm));
return outputs.opsm; return _opsm;
} }
function optimismPortalImpl() public view returns (OptimismPortal2) { function optimismPortalImpl() public view returns (OptimismPortal2) {
DeployUtils.assertValidContractAddress(address(outputs.optimismPortalImpl)); DeployUtils.assertValidContractAddress(address(_optimismPortalImpl));
return outputs.optimismPortalImpl; return _optimismPortalImpl;
} }
function delayedWETHImpl() public view returns (DelayedWETH) { function delayedWETHImpl() public view returns (DelayedWETH) {
DeployUtils.assertValidContractAddress(address(outputs.delayedWETHImpl)); DeployUtils.assertValidContractAddress(address(_delayedWETHImpl));
return outputs.delayedWETHImpl; return _delayedWETHImpl;
} }
function preimageOracleSingleton() public view returns (PreimageOracle) { function preimageOracleSingleton() public view returns (PreimageOracle) {
DeployUtils.assertValidContractAddress(address(outputs.preimageOracleSingleton)); DeployUtils.assertValidContractAddress(address(_preimageOracleSingleton));
return outputs.preimageOracleSingleton; return _preimageOracleSingleton;
} }
function mipsSingleton() public view returns (MIPS) { function mipsSingleton() public view returns (MIPS) {
DeployUtils.assertValidContractAddress(address(outputs.mipsSingleton)); DeployUtils.assertValidContractAddress(address(_mipsSingleton));
return outputs.mipsSingleton; return _mipsSingleton;
} }
function systemConfigImpl() public view returns (SystemConfig) { function systemConfigImpl() public view returns (SystemConfig) {
DeployUtils.assertValidContractAddress(address(outputs.systemConfigImpl)); DeployUtils.assertValidContractAddress(address(_systemConfigImpl));
return outputs.systemConfigImpl; return _systemConfigImpl;
} }
function l1CrossDomainMessengerImpl() public view returns (L1CrossDomainMessenger) { function l1CrossDomainMessengerImpl() public view returns (L1CrossDomainMessenger) {
DeployUtils.assertValidContractAddress(address(outputs.l1CrossDomainMessengerImpl)); DeployUtils.assertValidContractAddress(address(_l1CrossDomainMessengerImpl));
return outputs.l1CrossDomainMessengerImpl; return _l1CrossDomainMessengerImpl;
} }
function l1ERC721BridgeImpl() public view returns (L1ERC721Bridge) { function l1ERC721BridgeImpl() public view returns (L1ERC721Bridge) {
DeployUtils.assertValidContractAddress(address(outputs.l1ERC721BridgeImpl)); DeployUtils.assertValidContractAddress(address(_l1ERC721BridgeImpl));
return outputs.l1ERC721BridgeImpl; return _l1ERC721BridgeImpl;
} }
function l1StandardBridgeImpl() public view returns (L1StandardBridge) { function l1StandardBridgeImpl() public view returns (L1StandardBridge) {
DeployUtils.assertValidContractAddress(address(outputs.l1StandardBridgeImpl)); DeployUtils.assertValidContractAddress(address(_l1StandardBridgeImpl));
return outputs.l1StandardBridgeImpl; return _l1StandardBridgeImpl;
} }
function optimismMintableERC20FactoryImpl() public view returns (OptimismMintableERC20Factory) { function optimismMintableERC20FactoryImpl() public view returns (OptimismMintableERC20Factory) {
DeployUtils.assertValidContractAddress(address(outputs.optimismMintableERC20FactoryImpl)); DeployUtils.assertValidContractAddress(address(_optimismMintableERC20FactoryImpl));
return outputs.optimismMintableERC20FactoryImpl; return _optimismMintableERC20FactoryImpl;
} }
function disputeGameFactoryImpl() public view returns (DisputeGameFactory) { function disputeGameFactoryImpl() public view returns (DisputeGameFactory) {
DeployUtils.assertValidContractAddress(address(outputs.disputeGameFactoryImpl)); DeployUtils.assertValidContractAddress(address(_disputeGameFactoryImpl));
return outputs.disputeGameFactoryImpl; return _disputeGameFactoryImpl;
} }
} }
...@@ -247,19 +254,7 @@ contract DeployImplementations is Script { ...@@ -247,19 +254,7 @@ contract DeployImplementations is Script {
require(false, "DeployImplementations: run is not implemented"); require(false, "DeployImplementations: run is not implemented");
} }
function run(DeployImplementationsInput.Input memory _input)
public
returns (DeployImplementationsOutput.Output memory)
{
(DeployImplementationsInput dii, DeployImplementationsOutput dio) = etchIOContracts();
dii.loadInput(_input);
run(dii, dio);
return dio.output();
}
function run(DeployImplementationsInput _dii, DeployImplementationsOutput _dio) public { function run(DeployImplementationsInput _dii, DeployImplementationsOutput _dio) public {
require(_dii.inputSet(), "DeployImplementations: input not set");
// Deploy the implementations. // Deploy the implementations.
deploySystemConfigImpl(_dii, _dio); deploySystemConfigImpl(_dii, _dio);
deployL1CrossDomainMessengerImpl(_dii, _dio); deployL1CrossDomainMessengerImpl(_dii, _dio);
...@@ -521,7 +516,7 @@ contract DeployImplementations is Script { ...@@ -521,7 +516,7 @@ contract DeployImplementations is Script {
// -------- Utilities -------- // -------- Utilities --------
function etchIOContracts() internal returns (DeployImplementationsInput dii_, DeployImplementationsOutput dio_) { function etchIOContracts() public returns (DeployImplementationsInput dii_, DeployImplementationsOutput dio_) {
(dii_, dio_) = getIOContracts(); (dii_, dio_) = getIOContracts();
vm.etch(address(dii_), type(DeployImplementationsInput).runtimeCode); vm.etch(address(dii_), type(DeployImplementationsInput).runtimeCode);
vm.etch(address(dio_), type(DeployImplementationsOutput).runtimeCode); vm.etch(address(dio_), type(DeployImplementationsOutput).runtimeCode);
......
...@@ -3,6 +3,8 @@ pragma solidity 0.8.15; ...@@ -3,6 +3,8 @@ pragma solidity 0.8.15;
import { Script } from "forge-std/Script.sol"; import { Script } from "forge-std/Script.sol";
import { SafeCast } from "@openzeppelin/contracts/utils/math/SafeCast.sol";
import { DeployUtils } from "scripts/libraries/DeployUtils.sol"; import { DeployUtils } from "scripts/libraries/DeployUtils.sol";
import { Solarray } from "scripts/libraries/Solarray.sol"; import { Solarray } from "scripts/libraries/Solarray.sol";
...@@ -24,151 +26,138 @@ import { L1StandardBridge } from "src/L1/L1StandardBridge.sol"; ...@@ -24,151 +26,138 @@ import { L1StandardBridge } from "src/L1/L1StandardBridge.sol";
import { OptimismMintableERC20Factory } from "src/universal/OptimismMintableERC20Factory.sol"; import { OptimismMintableERC20Factory } from "src/universal/OptimismMintableERC20Factory.sol";
contract DeployOPChainInput { contract DeployOPChainInput {
struct Roles { address internal _opChainProxyAdminOwner;
address opChainProxyAdminOwner; address internal _systemConfigOwner;
address systemConfigOwner; address internal _batcher;
address batcher; address internal _unsafeBlockSigner;
address unsafeBlockSigner; address internal _proposer;
address proposer; address internal _challenger;
address challenger;
}
// TODO Add fault proofs inputs in a future PR. // TODO Add fault proofs inputs in a future PR.
struct Input { uint32 internal _basefeeScalar;
Roles roles; uint32 internal _blobBaseFeeScalar;
uint32 basefeeScalar; uint256 internal _l2ChainId;
uint32 blobBaseFeeScalar; OPStackManager internal _opsm;
uint256 l2ChainId;
OPStackManager opsm; function set(bytes4 _sel, address _addr) public {
} require(_addr != address(0), "DeployOPChainInput: cannot set zero address");
if (_sel == this.opChainProxyAdminOwner.selector) _opChainProxyAdminOwner = _addr;
bool public inputSet = false; else if (_sel == this.systemConfigOwner.selector) _systemConfigOwner = _addr;
Input internal inputs; else if (_sel == this.batcher.selector) _batcher = _addr;
else if (_sel == this.unsafeBlockSigner.selector) _unsafeBlockSigner = _addr;
function loadInputFile(string memory _infile) public { else if (_sel == this.proposer.selector) _proposer = _addr;
else if (_sel == this.challenger.selector) _challenger = _addr;
else if (_sel == this.opsm.selector) _opsm = OPStackManager(_addr);
else revert("DeployOPChainInput: unknown selector");
}
function set(bytes4 _sel, uint256 _value) public {
if (_sel == this.basefeeScalar.selector) {
_basefeeScalar = SafeCast.toUint32(_value);
} else if (_sel == this.blobBaseFeeScalar.selector) {
_blobBaseFeeScalar = SafeCast.toUint32(_value);
} else if (_sel == this.l2ChainId.selector) {
require(_value != 0 && _value != block.chainid, "DeployOPChainInput: invalid l2ChainId");
_l2ChainId = _value;
} else {
revert("DeployOPChainInput: unknown selector");
}
}
function loadInputFile(string memory _infile) public pure {
_infile; _infile;
Input memory parsedInput;
loadInput(parsedInput);
require(false, "DeployOPChainInput: not implemented"); require(false, "DeployOPChainInput: not implemented");
} }
function loadInput(Input memory _input) public {
require(!inputSet, "DeployOPChainInput: input already set");
require(_input.roles.opChainProxyAdminOwner != address(0), "DeployOPChainInput: null opChainProxyAdminOwner");
require(_input.roles.systemConfigOwner != address(0), "DeployOPChainInput: null systemConfigOwner");
require(_input.roles.batcher != address(0), "DeployOPChainInput: null batcher");
require(_input.roles.unsafeBlockSigner != address(0), "DeployOPChainInput: null unsafeBlockSigner");
require(_input.roles.proposer != address(0), "DeployOPChainInput: null proposer");
require(_input.roles.challenger != address(0), "DeployOPChainInput: null challenger");
require(_input.l2ChainId != 0 && _input.l2ChainId != block.chainid, "DeployOPChainInput: invalid l2ChainId");
require(address(_input.opsm) != address(0), "DeployOPChainInput: null opsm");
inputSet = true;
inputs = _input;
}
function assertInputSet() internal view {
require(inputSet, "DeployOPChainInput: input not set");
}
function input() public view returns (Input memory) {
assertInputSet();
return inputs;
}
function opChainProxyAdminOwner() public view returns (address) { function opChainProxyAdminOwner() public view returns (address) {
assertInputSet(); require(_opChainProxyAdminOwner != address(0), "DeployOPChainInput: not set");
return inputs.roles.opChainProxyAdminOwner; return _opChainProxyAdminOwner;
} }
function systemConfigOwner() public view returns (address) { function systemConfigOwner() public view returns (address) {
assertInputSet(); require(_systemConfigOwner != address(0), "DeployOPChainInput: not set");
return inputs.roles.systemConfigOwner; return _systemConfigOwner;
} }
function batcher() public view returns (address) { function batcher() public view returns (address) {
assertInputSet(); require(_batcher != address(0), "DeployOPChainInput: not set");
return inputs.roles.batcher; return _batcher;
} }
function unsafeBlockSigner() public view returns (address) { function unsafeBlockSigner() public view returns (address) {
assertInputSet(); require(_unsafeBlockSigner != address(0), "DeployOPChainInput: not set");
return inputs.roles.unsafeBlockSigner; return _unsafeBlockSigner;
} }
function proposer() public view returns (address) { function proposer() public view returns (address) {
assertInputSet(); require(_proposer != address(0), "DeployOPChainInput: not set");
return inputs.roles.proposer; return _proposer;
} }
function challenger() public view returns (address) { function challenger() public view returns (address) {
assertInputSet(); require(_challenger != address(0), "DeployOPChainInput: not set");
return inputs.roles.challenger; return _challenger;
} }
function basefeeScalar() public view returns (uint32) { function basefeeScalar() public view returns (uint32) {
assertInputSet(); require(_basefeeScalar != 0, "DeployOPChainInput: not set");
return inputs.basefeeScalar; return _basefeeScalar;
} }
function blobBaseFeeScalar() public view returns (uint32) { function blobBaseFeeScalar() public view returns (uint32) {
assertInputSet(); require(_blobBaseFeeScalar != 0, "DeployOPChainInput: not set");
return inputs.blobBaseFeeScalar; return _blobBaseFeeScalar;
} }
function l2ChainId() public view returns (uint256) { function l2ChainId() public view returns (uint256) {
assertInputSet(); require(_l2ChainId != 0, "DeployOPChainInput: not set");
return inputs.l2ChainId; require(_l2ChainId != block.chainid, "DeployOPChainInput: invalid l2ChainId");
return _l2ChainId;
} }
function opsm() public view returns (OPStackManager) { function opsm() public view returns (OPStackManager) {
assertInputSet(); require(address(_opsm) != address(0), "DeployOPChainInput: not set");
return inputs.opsm; return _opsm;
} }
} }
contract DeployOPChainOutput { contract DeployOPChainOutput {
struct Output { ProxyAdmin internal _opChainProxyAdmin;
ProxyAdmin opChainProxyAdmin; AddressManager internal _addressManager;
AddressManager addressManager; L1ERC721Bridge internal _l1ERC721BridgeProxy;
L1ERC721Bridge l1ERC721BridgeProxy; SystemConfig internal _systemConfigProxy;
SystemConfig systemConfigProxy; OptimismMintableERC20Factory internal _optimismMintableERC20FactoryProxy;
OptimismMintableERC20Factory optimismMintableERC20FactoryProxy; L1StandardBridge internal _l1StandardBridgeProxy;
L1StandardBridge l1StandardBridgeProxy; L1CrossDomainMessenger internal _l1CrossDomainMessengerProxy;
L1CrossDomainMessenger l1CrossDomainMessengerProxy; OptimismPortal2 internal _optimismPortalProxy;
// Fault proof contracts below. DisputeGameFactory internal _disputeGameFactoryProxy;
OptimismPortal2 optimismPortalProxy; DisputeGameFactory internal _disputeGameFactoryImpl;
DisputeGameFactory disputeGameFactoryProxy; AnchorStateRegistry internal _anchorStateRegistryProxy;
DisputeGameFactory disputeGameFactoryImpl; AnchorStateRegistry internal _anchorStateRegistryImpl;
AnchorStateRegistry anchorStateRegistryProxy; FaultDisputeGame internal _faultDisputeGame;
AnchorStateRegistry anchorStateRegistryImpl; PermissionedDisputeGame internal _permissionedDisputeGame;
FaultDisputeGame faultDisputeGame; DelayedWETH internal _delayedWETHPermissionedGameProxy;
PermissionedDisputeGame permissionedDisputeGame; DelayedWETH internal _delayedWETHPermissionlessGameProxy;
DelayedWETH delayedWETHPermissionedGameProxy;
DelayedWETH delayedWETHPermissionlessGameProxy;
}
Output internal outputs;
function set(bytes4 sel, address _addr) public { function set(bytes4 sel, address _addr) public {
require(_addr != address(0), "DeployOPChainOutput: cannot set zero address");
// forgefmt: disable-start // forgefmt: disable-start
if (sel == this.opChainProxyAdmin.selector) outputs.opChainProxyAdmin = ProxyAdmin(_addr) ; if (sel == this.opChainProxyAdmin.selector) _opChainProxyAdmin = ProxyAdmin(_addr) ;
else if (sel == this.addressManager.selector) outputs.addressManager = AddressManager(_addr) ; else if (sel == this.addressManager.selector) _addressManager = AddressManager(_addr) ;
else if (sel == this.l1ERC721BridgeProxy.selector) outputs.l1ERC721BridgeProxy = L1ERC721Bridge(_addr) ; else if (sel == this.l1ERC721BridgeProxy.selector) _l1ERC721BridgeProxy = L1ERC721Bridge(_addr) ;
else if (sel == this.systemConfigProxy.selector) outputs.systemConfigProxy = SystemConfig(_addr) ; else if (sel == this.systemConfigProxy.selector) _systemConfigProxy = SystemConfig(_addr) ;
else if (sel == this.optimismMintableERC20FactoryProxy.selector) outputs.optimismMintableERC20FactoryProxy = OptimismMintableERC20Factory(_addr) ; else if (sel == this.optimismMintableERC20FactoryProxy.selector) _optimismMintableERC20FactoryProxy = OptimismMintableERC20Factory(_addr) ;
else if (sel == this.l1StandardBridgeProxy.selector) outputs.l1StandardBridgeProxy = L1StandardBridge(payable(_addr)) ; else if (sel == this.l1StandardBridgeProxy.selector) _l1StandardBridgeProxy = L1StandardBridge(payable(_addr)) ;
else if (sel == this.l1CrossDomainMessengerProxy.selector) outputs.l1CrossDomainMessengerProxy = L1CrossDomainMessenger(_addr) ; else if (sel == this.l1CrossDomainMessengerProxy.selector) _l1CrossDomainMessengerProxy = L1CrossDomainMessenger(_addr) ;
else if (sel == this.optimismPortalProxy.selector) outputs.optimismPortalProxy = OptimismPortal2(payable(_addr)) ; else if (sel == this.optimismPortalProxy.selector) _optimismPortalProxy = OptimismPortal2(payable(_addr)) ;
else if (sel == this.disputeGameFactoryProxy.selector) outputs.disputeGameFactoryProxy = DisputeGameFactory(_addr) ; else if (sel == this.disputeGameFactoryProxy.selector) _disputeGameFactoryProxy = DisputeGameFactory(_addr) ;
else if (sel == this.disputeGameFactoryImpl.selector) outputs.disputeGameFactoryImpl = DisputeGameFactory(_addr) ; else if (sel == this.disputeGameFactoryImpl.selector) _disputeGameFactoryImpl = DisputeGameFactory(_addr) ;
else if (sel == this.anchorStateRegistryProxy.selector) outputs.anchorStateRegistryProxy = AnchorStateRegistry(_addr) ; else if (sel == this.anchorStateRegistryProxy.selector) _anchorStateRegistryProxy = AnchorStateRegistry(_addr) ;
else if (sel == this.anchorStateRegistryImpl.selector) outputs.anchorStateRegistryImpl = AnchorStateRegistry(_addr) ; else if (sel == this.anchorStateRegistryImpl.selector) _anchorStateRegistryImpl = AnchorStateRegistry(_addr) ;
else if (sel == this.faultDisputeGame.selector) outputs.faultDisputeGame = FaultDisputeGame(_addr) ; else if (sel == this.faultDisputeGame.selector) _faultDisputeGame = FaultDisputeGame(_addr) ;
else if (sel == this.permissionedDisputeGame.selector) outputs.permissionedDisputeGame = PermissionedDisputeGame(_addr) ; else if (sel == this.permissionedDisputeGame.selector) _permissionedDisputeGame = PermissionedDisputeGame(_addr) ;
else if (sel == this.delayedWETHPermissionedGameProxy.selector) outputs.delayedWETHPermissionedGameProxy = DelayedWETH(payable(_addr)) ; else if (sel == this.delayedWETHPermissionedGameProxy.selector) _delayedWETHPermissionedGameProxy = DelayedWETH(payable(_addr)) ;
else if (sel == this.delayedWETHPermissionlessGameProxy.selector) outputs.delayedWETHPermissionlessGameProxy = DelayedWETH(payable(_addr)) ; else if (sel == this.delayedWETHPermissionlessGameProxy.selector) _delayedWETHPermissionlessGameProxy = DelayedWETH(payable(_addr)) ;
else revert("DeployOPChainOutput: unknown selector"); else revert("DeployOPChainOutput: unknown selector");
// forgefmt: disable-end // forgefmt: disable-end
} }
...@@ -178,114 +167,110 @@ contract DeployOPChainOutput { ...@@ -178,114 +167,110 @@ contract DeployOPChainOutput {
require(false, "DeployOPChainOutput: not implemented"); require(false, "DeployOPChainOutput: not implemented");
} }
function output() public view returns (Output memory) {
return outputs;
}
function checkOutput() public view { function checkOutput() public view {
// With 16 addresses, we'd get a stack too deep error if we tried to do this inline as a // With 16 addresses, we'd get a stack too deep error if we tried to do this inline as a
// single call to `Solarray.addresses`. So we split it into two calls. // single call to `Solarray.addresses`. So we split it into two calls.
address[] memory addrs1 = Solarray.addresses( address[] memory addrs1 = Solarray.addresses(
address(outputs.opChainProxyAdmin), address(_opChainProxyAdmin),
address(outputs.addressManager), address(_addressManager),
address(outputs.l1ERC721BridgeProxy), address(_l1ERC721BridgeProxy),
address(outputs.systemConfigProxy), address(_systemConfigProxy),
address(outputs.optimismMintableERC20FactoryProxy), address(_optimismMintableERC20FactoryProxy),
address(outputs.l1StandardBridgeProxy), address(_l1StandardBridgeProxy),
address(outputs.l1CrossDomainMessengerProxy) address(_l1CrossDomainMessengerProxy)
); );
address[] memory addrs2 = Solarray.addresses( address[] memory addrs2 = Solarray.addresses(
address(outputs.optimismPortalProxy), address(_optimismPortalProxy),
address(outputs.disputeGameFactoryProxy), address(_disputeGameFactoryProxy),
address(outputs.disputeGameFactoryImpl), address(_disputeGameFactoryImpl),
address(outputs.anchorStateRegistryProxy), address(_anchorStateRegistryProxy),
address(outputs.anchorStateRegistryImpl), address(_anchorStateRegistryImpl),
address(outputs.faultDisputeGame), address(_faultDisputeGame),
address(outputs.permissionedDisputeGame), address(_permissionedDisputeGame),
address(outputs.delayedWETHPermissionedGameProxy), address(_delayedWETHPermissionedGameProxy),
address(outputs.delayedWETHPermissionlessGameProxy) address(_delayedWETHPermissionlessGameProxy)
); );
DeployUtils.assertValidContractAddresses(Solarray.extend(addrs1, addrs2)); DeployUtils.assertValidContractAddresses(Solarray.extend(addrs1, addrs2));
} }
function opChainProxyAdmin() public view returns (ProxyAdmin) { function opChainProxyAdmin() public view returns (ProxyAdmin) {
DeployUtils.assertValidContractAddress(address(outputs.opChainProxyAdmin)); DeployUtils.assertValidContractAddress(address(_opChainProxyAdmin));
return outputs.opChainProxyAdmin; return _opChainProxyAdmin;
} }
function addressManager() public view returns (AddressManager) { function addressManager() public view returns (AddressManager) {
DeployUtils.assertValidContractAddress(address(outputs.addressManager)); DeployUtils.assertValidContractAddress(address(_addressManager));
return outputs.addressManager; return _addressManager;
} }
function l1ERC721BridgeProxy() public view returns (L1ERC721Bridge) { function l1ERC721BridgeProxy() public view returns (L1ERC721Bridge) {
DeployUtils.assertValidContractAddress(address(outputs.l1ERC721BridgeProxy)); DeployUtils.assertValidContractAddress(address(_l1ERC721BridgeProxy));
return outputs.l1ERC721BridgeProxy; return _l1ERC721BridgeProxy;
} }
function systemConfigProxy() public view returns (SystemConfig) { function systemConfigProxy() public view returns (SystemConfig) {
DeployUtils.assertValidContractAddress(address(outputs.systemConfigProxy)); DeployUtils.assertValidContractAddress(address(_systemConfigProxy));
return outputs.systemConfigProxy; return _systemConfigProxy;
} }
function optimismMintableERC20FactoryProxy() public view returns (OptimismMintableERC20Factory) { function optimismMintableERC20FactoryProxy() public view returns (OptimismMintableERC20Factory) {
DeployUtils.assertValidContractAddress(address(outputs.optimismMintableERC20FactoryProxy)); DeployUtils.assertValidContractAddress(address(_optimismMintableERC20FactoryProxy));
return outputs.optimismMintableERC20FactoryProxy; return _optimismMintableERC20FactoryProxy;
} }
function l1StandardBridgeProxy() public view returns (L1StandardBridge) { function l1StandardBridgeProxy() public view returns (L1StandardBridge) {
DeployUtils.assertValidContractAddress(address(outputs.l1StandardBridgeProxy)); DeployUtils.assertValidContractAddress(address(_l1StandardBridgeProxy));
return outputs.l1StandardBridgeProxy; return _l1StandardBridgeProxy;
} }
function l1CrossDomainMessengerProxy() public view returns (L1CrossDomainMessenger) { function l1CrossDomainMessengerProxy() public view returns (L1CrossDomainMessenger) {
DeployUtils.assertValidContractAddress(address(outputs.l1CrossDomainMessengerProxy)); DeployUtils.assertValidContractAddress(address(_l1CrossDomainMessengerProxy));
return outputs.l1CrossDomainMessengerProxy; return _l1CrossDomainMessengerProxy;
} }
function optimismPortalProxy() public view returns (OptimismPortal2) { function optimismPortalProxy() public view returns (OptimismPortal2) {
DeployUtils.assertValidContractAddress(address(outputs.optimismPortalProxy)); DeployUtils.assertValidContractAddress(address(_optimismPortalProxy));
return outputs.optimismPortalProxy; return _optimismPortalProxy;
} }
function disputeGameFactoryProxy() public view returns (DisputeGameFactory) { function disputeGameFactoryProxy() public view returns (DisputeGameFactory) {
DeployUtils.assertValidContractAddress(address(outputs.disputeGameFactoryProxy)); DeployUtils.assertValidContractAddress(address(_disputeGameFactoryProxy));
return outputs.disputeGameFactoryProxy; return _disputeGameFactoryProxy;
} }
function disputeGameFactoryImpl() public view returns (DisputeGameFactory) { function disputeGameFactoryImpl() public view returns (DisputeGameFactory) {
DeployUtils.assertValidContractAddress(address(outputs.disputeGameFactoryImpl)); DeployUtils.assertValidContractAddress(address(_disputeGameFactoryImpl));
return outputs.disputeGameFactoryImpl; return _disputeGameFactoryImpl;
} }
function anchorStateRegistryProxy() public view returns (AnchorStateRegistry) { function anchorStateRegistryProxy() public view returns (AnchorStateRegistry) {
DeployUtils.assertValidContractAddress(address(outputs.anchorStateRegistryProxy)); DeployUtils.assertValidContractAddress(address(_anchorStateRegistryProxy));
return outputs.anchorStateRegistryProxy; return _anchorStateRegistryProxy;
} }
function anchorStateRegistryImpl() public view returns (AnchorStateRegistry) { function anchorStateRegistryImpl() public view returns (AnchorStateRegistry) {
DeployUtils.assertValidContractAddress(address(outputs.anchorStateRegistryImpl)); DeployUtils.assertValidContractAddress(address(_anchorStateRegistryImpl));
return outputs.anchorStateRegistryImpl; return _anchorStateRegistryImpl;
} }
function faultDisputeGame() public view returns (FaultDisputeGame) { function faultDisputeGame() public view returns (FaultDisputeGame) {
DeployUtils.assertValidContractAddress(address(outputs.faultDisputeGame)); DeployUtils.assertValidContractAddress(address(_faultDisputeGame));
return outputs.faultDisputeGame; return _faultDisputeGame;
} }
function permissionedDisputeGame() public view returns (PermissionedDisputeGame) { function permissionedDisputeGame() public view returns (PermissionedDisputeGame) {
DeployUtils.assertValidContractAddress(address(outputs.permissionedDisputeGame)); DeployUtils.assertValidContractAddress(address(_permissionedDisputeGame));
return outputs.permissionedDisputeGame; return _permissionedDisputeGame;
} }
function delayedWETHPermissionedGameProxy() public view returns (DelayedWETH) { function delayedWETHPermissionedGameProxy() public view returns (DelayedWETH) {
DeployUtils.assertValidContractAddress(address(outputs.delayedWETHPermissionedGameProxy)); DeployUtils.assertValidContractAddress(address(_delayedWETHPermissionedGameProxy));
return outputs.delayedWETHPermissionedGameProxy; return _delayedWETHPermissionedGameProxy;
} }
function delayedWETHPermissionlessGameProxy() public view returns (DelayedWETH) { function delayedWETHPermissionlessGameProxy() public view returns (DelayedWETH) {
DeployUtils.assertValidContractAddress(address(outputs.delayedWETHPermissionlessGameProxy)); DeployUtils.assertValidContractAddress(address(_delayedWETHPermissionlessGameProxy));
return outputs.delayedWETHPermissionlessGameProxy; return _delayedWETHPermissionlessGameProxy;
} }
} }
...@@ -300,16 +285,7 @@ contract DeployOPChain is Script { ...@@ -300,16 +285,7 @@ contract DeployOPChain is Script {
require(false, "DeployOPChain: run is not implemented"); require(false, "DeployOPChain: run is not implemented");
} }
function run(DeployOPChainInput.Input memory _input) public returns (DeployOPChainOutput.Output memory) {
(DeployOPChainInput doi, DeployOPChainOutput doo) = etchIOContracts();
doi.loadInput(_input);
run(doi, doo);
return doo.output();
}
function run(DeployOPChainInput _doi, DeployOPChainOutput _doo) public { function run(DeployOPChainInput _doi, DeployOPChainOutput _doo) public {
require(_doi.inputSet(), "DeployOPChain: input not set");
OPStackManager opsm = _doi.opsm(); OPStackManager opsm = _doi.opsm();
OPStackManager.Roles memory roles = OPStackManager.Roles({ OPStackManager.Roles memory roles = OPStackManager.Roles({
...@@ -373,7 +349,7 @@ contract DeployOPChain is Script { ...@@ -373,7 +349,7 @@ contract DeployOPChain is Script {
// -------- Utilities -------- // -------- Utilities --------
function etchIOContracts() internal returns (DeployOPChainInput doi_, DeployOPChainOutput doo_) { function etchIOContracts() public returns (DeployOPChainInput doi_, DeployOPChainOutput doo_) {
(doi_, doo_) = getIOContracts(); (doi_, doo_) = getIOContracts();
vm.etch(address(doi_), type(DeployOPChainInput).runtimeCode); vm.etch(address(doi_), type(DeployOPChainInput).runtimeCode);
vm.etch(address(doo_), type(DeployOPChainOutput).runtimeCode); vm.etch(address(doo_), type(DeployOPChainOutput).runtimeCode);
......
...@@ -88,7 +88,7 @@ contract DeploySuperchainInput is CommonBase { ...@@ -88,7 +88,7 @@ contract DeploySuperchainInput is CommonBase {
// These `set` methods let each input be set individually. The selector of an input's getter method // These `set` methods let each input be set individually. The selector of an input's getter method
// is used to determine which field to set. // is used to determine which field to set.
function set(bytes4 _sel, address _address) public { function set(bytes4 _sel, address _address) public {
require(_address != address(0), "DeploySuperchainInput: cannot set null address"); require(_address != address(0), "DeploySuperchainInput: cannot set zero address");
if (_sel == this.guardian.selector) _guardian = _address; if (_sel == this.guardian.selector) _guardian = _address;
else if (_sel == this.protocolVersionsOwner.selector) _protocolVersionsOwner = _address; else if (_sel == this.protocolVersionsOwner.selector) _protocolVersionsOwner = _address;
else if (_sel == this.proxyAdminOwner.selector) _proxyAdminOwner = _address; else if (_sel == this.proxyAdminOwner.selector) _proxyAdminOwner = _address;
...@@ -181,6 +181,7 @@ contract DeploySuperchainOutput is CommonBase { ...@@ -181,6 +181,7 @@ contract DeploySuperchainOutput is CommonBase {
// This method lets each field be set individually. The selector of an output's getter method // This method lets each field be set individually. The selector of an output's getter method
// is used to determine which field to set. // is used to determine which field to set.
function set(bytes4 sel, address _address) public { function set(bytes4 sel, address _address) public {
require(_address != address(0), "DeploySuperchainOutput: cannot set zero address");
if (sel == this.superchainProxyAdmin.selector) _superchainProxyAdmin = ProxyAdmin(_address); if (sel == this.superchainProxyAdmin.selector) _superchainProxyAdmin = ProxyAdmin(_address);
else if (sel == this.superchainConfigImpl.selector) _superchainConfigImpl = SuperchainConfig(_address); else if (sel == this.superchainConfigImpl.selector) _superchainConfigImpl = SuperchainConfig(_address);
else if (sel == this.superchainConfigProxy.selector) _superchainConfigProxy = SuperchainConfig(_address); else if (sel == this.superchainConfigProxy.selector) _superchainConfigProxy = SuperchainConfig(_address);
......
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity 0.8.15; pragma solidity 0.8.15;
import { Test } from "forge-std/Test.sol"; import { Test, stdStorage, StdStorage } from "forge-std/Test.sol";
import { DelayedWETH } from "src/dispute/weth/DelayedWETH.sol"; import { DelayedWETH } from "src/dispute/weth/DelayedWETH.sol";
import { PreimageOracle } from "src/cannon/PreimageOracle.sol"; import { PreimageOracle } from "src/cannon/PreimageOracle.sol";
...@@ -28,54 +28,56 @@ import { ...@@ -28,54 +28,56 @@ import {
contract DeployImplementationsInput_Test is Test { contract DeployImplementationsInput_Test is Test {
DeployImplementationsInput dii; DeployImplementationsInput dii;
DeployImplementationsInput.Input input = DeployImplementationsInput.Input({ uint256 withdrawalDelaySeconds = 100;
withdrawalDelaySeconds: 100, uint256 minProposalSizeBytes = 200;
minProposalSizeBytes: 200, uint256 challengePeriodSeconds = 300;
challengePeriodSeconds: 300, uint256 proofMaturityDelaySeconds = 400;
proofMaturityDelaySeconds: 400, uint256 disputeGameFinalityDelaySeconds = 500;
disputeGameFinalityDelaySeconds: 500, string release = "op-contracts/latest";
release: "op-contracts/latest", SuperchainConfig superchainConfigProxy = SuperchainConfig(makeAddr("superchainConfigProxy"));
superchainConfigProxy: SuperchainConfig(makeAddr("superchainConfigProxy")), ProtocolVersions protocolVersionsProxy = ProtocolVersions(makeAddr("protocolVersionsProxy"));
protocolVersionsProxy: ProtocolVersions(makeAddr("protocolVersionsProxy"))
});
function setUp() public { function setUp() public {
dii = new DeployImplementationsInput(); dii = new DeployImplementationsInput();
} }
function test_loadInput_succeeds() public { function test_loadInputFile_succeeds() public {
dii.loadInput(input); // See `test_loadInputFile_succeeds` in `DeploySuperchain.t.sol` for a reference implementation.
// This test is currently skipped because loadInputFile is not implemented.
assertTrue(dii.inputSet(), "100"); vm.skip(true);
// Compare the test input struct to the getter methods. // Compare the test inputs to the getter methods.
assertEq(input.withdrawalDelaySeconds, dii.withdrawalDelaySeconds(), "200"); // assertEq(withdrawalDelaySeconds, dii.withdrawalDelaySeconds(), "100");
assertEq(input.minProposalSizeBytes, dii.minProposalSizeBytes(), "300"); // assertEq(minProposalSizeBytes, dii.minProposalSizeBytes(), "200");
assertEq(input.challengePeriodSeconds, dii.challengePeriodSeconds(), "400"); // assertEq(challengePeriodSeconds, dii.challengePeriodSeconds(), "300");
assertEq(input.proofMaturityDelaySeconds, dii.proofMaturityDelaySeconds(), "500"); // assertEq(proofMaturityDelaySeconds, dii.proofMaturityDelaySeconds(), "400");
assertEq(input.disputeGameFinalityDelaySeconds, dii.disputeGameFinalityDelaySeconds(), "600"); // assertEq(disputeGameFinalityDelaySeconds, dii.disputeGameFinalityDelaySeconds(), "500");
// Compare the test input struct to the `input` getter method.
assertEq(keccak256(abi.encode(input)), keccak256(abi.encode(dii.input())), "800");
} }
function test_getters_whenNotSet_revert() public { function test_getters_whenNotSet_revert() public {
bytes memory expectedErr = "DeployImplementationsInput: input not set"; vm.expectRevert("DeployImplementationsInput: not set");
vm.expectRevert(expectedErr);
dii.withdrawalDelaySeconds(); dii.withdrawalDelaySeconds();
vm.expectRevert(expectedErr); vm.expectRevert("DeployImplementationsInput: not set");
dii.minProposalSizeBytes(); dii.minProposalSizeBytes();
vm.expectRevert(expectedErr); vm.expectRevert("DeployImplementationsInput: not set");
dii.challengePeriodSeconds(); dii.challengePeriodSeconds();
vm.expectRevert(expectedErr); vm.expectRevert("DeployImplementationsInput: not set");
dii.proofMaturityDelaySeconds(); dii.proofMaturityDelaySeconds();
vm.expectRevert(expectedErr); vm.expectRevert("DeployImplementationsInput: not set");
dii.disputeGameFinalityDelaySeconds(); dii.disputeGameFinalityDelaySeconds();
vm.expectRevert("DeployImplementationsInput: not set");
dii.release();
vm.expectRevert("DeployImplementationsInput: not set");
dii.superchainConfigProxy();
vm.expectRevert("DeployImplementationsInput: not set");
dii.protocolVersionsProxy();
} }
} }
...@@ -87,58 +89,54 @@ contract DeployImplementationsOutput_Test is Test { ...@@ -87,58 +89,54 @@ contract DeployImplementationsOutput_Test is Test {
} }
function test_set_succeeds() public { function test_set_succeeds() public {
DeployImplementationsOutput.Output memory output = DeployImplementationsOutput.Output({ OPStackManager opsm = OPStackManager(makeAddr("opsm"));
opsm: OPStackManager(makeAddr("opsm")), OptimismPortal2 optimismPortalImpl = OptimismPortal2(payable(makeAddr("optimismPortalImpl")));
optimismPortalImpl: OptimismPortal2(payable(makeAddr("optimismPortalImpl"))), DelayedWETH delayedWETHImpl = DelayedWETH(payable(makeAddr("delayedWETHImpl")));
delayedWETHImpl: DelayedWETH(payable(makeAddr("delayedWETHImpl"))), PreimageOracle preimageOracleSingleton = PreimageOracle(makeAddr("preimageOracleSingleton"));
preimageOracleSingleton: PreimageOracle(makeAddr("preimageOracleSingleton")), MIPS mipsSingleton = MIPS(makeAddr("mipsSingleton"));
mipsSingleton: MIPS(makeAddr("mipsSingleton")), SystemConfig systemConfigImpl = SystemConfig(makeAddr("systemConfigImpl"));
systemConfigImpl: SystemConfig(makeAddr("systemConfigImpl")), L1CrossDomainMessenger l1CrossDomainMessengerImpl =
l1CrossDomainMessengerImpl: L1CrossDomainMessenger(makeAddr("l1CrossDomainMessengerImpl")), L1CrossDomainMessenger(makeAddr("l1CrossDomainMessengerImpl"));
l1ERC721BridgeImpl: L1ERC721Bridge(makeAddr("l1ERC721BridgeImpl")), L1ERC721Bridge l1ERC721BridgeImpl = L1ERC721Bridge(makeAddr("l1ERC721BridgeImpl"));
l1StandardBridgeImpl: L1StandardBridge(payable(makeAddr("l1StandardBridgeImpl"))), L1StandardBridge l1StandardBridgeImpl = L1StandardBridge(payable(makeAddr("l1StandardBridgeImpl")));
optimismMintableERC20FactoryImpl: OptimismMintableERC20Factory(makeAddr("optimismMintableERC20FactoryImpl")), OptimismMintableERC20Factory optimismMintableERC20FactoryImpl =
disputeGameFactoryImpl: DisputeGameFactory(makeAddr("disputeGameFactoryImpl")) OptimismMintableERC20Factory(makeAddr("optimismMintableERC20FactoryImpl"));
}); DisputeGameFactory disputeGameFactoryImpl = DisputeGameFactory(makeAddr("disputeGameFactoryImpl"));
vm.etch(address(output.opsm), hex"01"); vm.etch(address(opsm), hex"01");
vm.etch(address(output.optimismPortalImpl), hex"01"); vm.etch(address(optimismPortalImpl), hex"01");
vm.etch(address(output.delayedWETHImpl), hex"01"); vm.etch(address(delayedWETHImpl), hex"01");
vm.etch(address(output.preimageOracleSingleton), hex"01"); vm.etch(address(preimageOracleSingleton), hex"01");
vm.etch(address(output.mipsSingleton), hex"01"); vm.etch(address(mipsSingleton), hex"01");
vm.etch(address(output.systemConfigImpl), hex"01"); vm.etch(address(systemConfigImpl), hex"01");
vm.etch(address(output.l1CrossDomainMessengerImpl), hex"01"); vm.etch(address(l1CrossDomainMessengerImpl), hex"01");
vm.etch(address(output.l1ERC721BridgeImpl), hex"01"); vm.etch(address(l1ERC721BridgeImpl), hex"01");
vm.etch(address(output.l1StandardBridgeImpl), hex"01"); vm.etch(address(l1StandardBridgeImpl), hex"01");
vm.etch(address(output.optimismMintableERC20FactoryImpl), hex"01"); vm.etch(address(optimismMintableERC20FactoryImpl), hex"01");
vm.etch(address(output.disputeGameFactoryImpl), hex"01"); vm.etch(address(disputeGameFactoryImpl), hex"01");
dio.set(dio.opsm.selector, address(output.opsm)); dio.set(dio.opsm.selector, address(opsm));
dio.set(dio.optimismPortalImpl.selector, address(output.optimismPortalImpl)); dio.set(dio.optimismPortalImpl.selector, address(optimismPortalImpl));
dio.set(dio.delayedWETHImpl.selector, address(output.delayedWETHImpl)); dio.set(dio.delayedWETHImpl.selector, address(delayedWETHImpl));
dio.set(dio.preimageOracleSingleton.selector, address(output.preimageOracleSingleton)); dio.set(dio.preimageOracleSingleton.selector, address(preimageOracleSingleton));
dio.set(dio.mipsSingleton.selector, address(output.mipsSingleton)); dio.set(dio.mipsSingleton.selector, address(mipsSingleton));
dio.set(dio.systemConfigImpl.selector, address(output.systemConfigImpl)); dio.set(dio.systemConfigImpl.selector, address(systemConfigImpl));
dio.set(dio.l1CrossDomainMessengerImpl.selector, address(output.l1CrossDomainMessengerImpl)); dio.set(dio.l1CrossDomainMessengerImpl.selector, address(l1CrossDomainMessengerImpl));
dio.set(dio.l1ERC721BridgeImpl.selector, address(output.l1ERC721BridgeImpl)); dio.set(dio.l1ERC721BridgeImpl.selector, address(l1ERC721BridgeImpl));
dio.set(dio.l1StandardBridgeImpl.selector, address(output.l1StandardBridgeImpl)); dio.set(dio.l1StandardBridgeImpl.selector, address(l1StandardBridgeImpl));
dio.set(dio.optimismMintableERC20FactoryImpl.selector, address(output.optimismMintableERC20FactoryImpl)); dio.set(dio.optimismMintableERC20FactoryImpl.selector, address(optimismMintableERC20FactoryImpl));
dio.set(dio.disputeGameFactoryImpl.selector, address(output.disputeGameFactoryImpl)); dio.set(dio.disputeGameFactoryImpl.selector, address(disputeGameFactoryImpl));
assertEq(address(output.opsm), address(dio.opsm()), "50"); assertEq(address(opsm), address(dio.opsm()), "50");
assertEq(address(output.optimismPortalImpl), address(dio.optimismPortalImpl()), "100"); assertEq(address(optimismPortalImpl), address(dio.optimismPortalImpl()), "100");
assertEq(address(output.delayedWETHImpl), address(dio.delayedWETHImpl()), "200"); assertEq(address(delayedWETHImpl), address(dio.delayedWETHImpl()), "200");
assertEq(address(output.preimageOracleSingleton), address(dio.preimageOracleSingleton()), "300"); assertEq(address(preimageOracleSingleton), address(dio.preimageOracleSingleton()), "300");
assertEq(address(output.mipsSingleton), address(dio.mipsSingleton()), "400"); assertEq(address(mipsSingleton), address(dio.mipsSingleton()), "400");
assertEq(address(output.systemConfigImpl), address(dio.systemConfigImpl()), "500"); assertEq(address(systemConfigImpl), address(dio.systemConfigImpl()), "500");
assertEq(address(output.l1CrossDomainMessengerImpl), address(dio.l1CrossDomainMessengerImpl()), "600"); assertEq(address(l1CrossDomainMessengerImpl), address(dio.l1CrossDomainMessengerImpl()), "600");
assertEq(address(output.l1ERC721BridgeImpl), address(dio.l1ERC721BridgeImpl()), "700"); assertEq(address(l1ERC721BridgeImpl), address(dio.l1ERC721BridgeImpl()), "700");
assertEq(address(output.l1StandardBridgeImpl), address(dio.l1StandardBridgeImpl()), "800"); assertEq(address(l1StandardBridgeImpl), address(dio.l1StandardBridgeImpl()), "800");
assertEq( assertEq(address(optimismMintableERC20FactoryImpl), address(dio.optimismMintableERC20FactoryImpl()), "900");
address(output.optimismMintableERC20FactoryImpl), address(dio.optimismMintableERC20FactoryImpl()), "900" assertEq(address(disputeGameFactoryImpl), address(dio.disputeGameFactoryImpl()), "950");
);
assertEq(address(output.disputeGameFactoryImpl), address(dio.disputeGameFactoryImpl()), "950");
assertEq(keccak256(abi.encode(output)), keccak256(abi.encode(dio.output())), "1000");
} }
function test_getters_whenNotSet_revert() public { function test_getters_whenNotSet_revert() public {
...@@ -218,25 +216,25 @@ contract DeployImplementationsOutput_Test is Test { ...@@ -218,25 +216,25 @@ contract DeployImplementationsOutput_Test is Test {
} }
contract DeployImplementations_Test is Test { contract DeployImplementations_Test is Test {
using stdStorage for StdStorage;
DeployImplementations deployImplementations; DeployImplementations deployImplementations;
DeployImplementationsInput dii; DeployImplementationsInput dii;
DeployImplementationsOutput dio; DeployImplementationsOutput dio;
// Define a default input struct for testing. // Define default inputs for testing.
DeployImplementationsInput.Input input = DeployImplementationsInput.Input({ uint256 withdrawalDelaySeconds = 100;
withdrawalDelaySeconds: 100, uint256 minProposalSizeBytes = 200;
minProposalSizeBytes: 200, uint256 challengePeriodSeconds = 300;
challengePeriodSeconds: 300, uint256 proofMaturityDelaySeconds = 400;
proofMaturityDelaySeconds: 400, uint256 disputeGameFinalityDelaySeconds = 500;
disputeGameFinalityDelaySeconds: 500, string release = "op-contracts/latest";
release: "op-contracts/latest", SuperchainConfig superchainConfigProxy = SuperchainConfig(makeAddr("superchainConfigProxy"));
superchainConfigProxy: SuperchainConfig(makeAddr("superchainConfigProxy")), ProtocolVersions protocolVersionsProxy = ProtocolVersions(makeAddr("protocolVersionsProxy"));
protocolVersionsProxy: ProtocolVersions(makeAddr("protocolVersionsProxy"))
});
function setUp() public virtual { function setUp() public virtual {
deployImplementations = new DeployImplementations(); deployImplementations = new DeployImplementations();
(dii, dio) = deployImplementations.getIOContracts(); (dii, dio) = deployImplementations.etchIOContracts();
} }
// By deploying the `DeployImplementations` contract with this virtual function, we provide a // By deploying the `DeployImplementations` contract with this virtual function, we provide a
...@@ -246,50 +244,43 @@ contract DeployImplementations_Test is Test { ...@@ -246,50 +244,43 @@ contract DeployImplementations_Test is Test {
return new DeployImplementations(); return new DeployImplementations();
} }
function testFuzz_run_succeeds(DeployImplementationsInput.Input memory _input) public { function hash(bytes32 _seed, uint256 _i) internal pure returns (bytes32) {
// This is a requirement in the PreimageOracle contract. return keccak256(abi.encode(_seed, _i));
_input.challengePeriodSeconds = bound(_input.challengePeriodSeconds, 0, type(uint64).max); }
DeployImplementationsOutput.Output memory output = deployImplementations.run(_input); function testFuzz_run_memory_succeeds(bytes32 _seed) public {
withdrawalDelaySeconds = uint256(hash(_seed, 0));
// Assert that individual input fields were properly set based on the input struct. minProposalSizeBytes = uint256(hash(_seed, 1));
assertEq(_input.withdrawalDelaySeconds, dii.withdrawalDelaySeconds(), "100"); challengePeriodSeconds = bound(uint256(hash(_seed, 2)), 0, type(uint64).max);
assertEq(_input.minProposalSizeBytes, dii.minProposalSizeBytes(), "200"); proofMaturityDelaySeconds = uint256(hash(_seed, 3));
assertEq(_input.challengePeriodSeconds, dii.challengePeriodSeconds(), "300"); disputeGameFinalityDelaySeconds = uint256(hash(_seed, 4));
assertEq(_input.proofMaturityDelaySeconds, dii.proofMaturityDelaySeconds(), "400"); release = string(bytes.concat(hash(_seed, 5)));
assertEq(_input.disputeGameFinalityDelaySeconds, dii.disputeGameFinalityDelaySeconds(), "500"); superchainConfigProxy = SuperchainConfig(address(uint160(uint256(hash(_seed, 6)))));
protocolVersionsProxy = ProtocolVersions(address(uint160(uint256(hash(_seed, 7)))));
// Assert that individual output fields were properly set based on the output struct.
assertEq(address(output.optimismPortalImpl), address(dio.optimismPortalImpl()), "600"); dii.set(dii.withdrawalDelaySeconds.selector, withdrawalDelaySeconds);
assertEq(address(output.delayedWETHImpl), address(dio.delayedWETHImpl()), "700"); dii.set(dii.minProposalSizeBytes.selector, minProposalSizeBytes);
assertEq(address(output.preimageOracleSingleton), address(dio.preimageOracleSingleton()), "800"); dii.set(dii.challengePeriodSeconds.selector, challengePeriodSeconds);
assertEq(address(output.mipsSingleton), address(dio.mipsSingleton()), "900"); dii.set(dii.proofMaturityDelaySeconds.selector, proofMaturityDelaySeconds);
assertEq(address(output.systemConfigImpl), address(dio.systemConfigImpl()), "1000"); dii.set(dii.disputeGameFinalityDelaySeconds.selector, disputeGameFinalityDelaySeconds);
assertEq(address(output.l1CrossDomainMessengerImpl), address(dio.l1CrossDomainMessengerImpl()), "1100"); dii.set(dii.release.selector, release);
assertEq(address(output.l1ERC721BridgeImpl), address(dio.l1ERC721BridgeImpl()), "1200"); dii.set(dii.superchainConfigProxy.selector, address(superchainConfigProxy));
assertEq(address(output.l1StandardBridgeImpl), address(dio.l1StandardBridgeImpl()), "1300"); dii.set(dii.protocolVersionsProxy.selector, address(protocolVersionsProxy));
assertEq(
address(output.optimismMintableERC20FactoryImpl), address(dio.optimismMintableERC20FactoryImpl()), "1400" deployImplementations.run(dii, dio);
);
assertEq(address(output.disputeGameFactoryImpl), address(dio.disputeGameFactoryImpl()), "1450"); // Assert that individual input fields were properly set based on the inputs.
assertEq(withdrawalDelaySeconds, dii.withdrawalDelaySeconds(), "100");
// Assert that the full input and output structs were properly set. assertEq(minProposalSizeBytes, dii.minProposalSizeBytes(), "200");
assertEq(keccak256(abi.encode(_input)), keccak256(abi.encode(DeployImplementationsInput(dii).input())), "1500"); assertEq(challengePeriodSeconds, dii.challengePeriodSeconds(), "300");
assertEq( assertEq(proofMaturityDelaySeconds, dii.proofMaturityDelaySeconds(), "400");
keccak256(abi.encode(output)), keccak256(abi.encode(DeployImplementationsOutput(dio).output())), "1600" assertEq(disputeGameFinalityDelaySeconds, dii.disputeGameFinalityDelaySeconds(), "500");
); assertEq(release, dii.release(), "525");
assertEq(address(superchainConfigProxy), address(dii.superchainConfigProxy()), "550");
// Assert inputs were properly passed through to the contract initializers. assertEq(address(protocolVersionsProxy), address(dii.protocolVersionsProxy()), "575");
assertEq(output.delayedWETHImpl.delay(), _input.withdrawalDelaySeconds, "1700");
assertEq(output.preimageOracleSingleton.challengePeriod(), _input.challengePeriodSeconds, "1800");
assertEq(output.preimageOracleSingleton.minProposalSize(), _input.minProposalSizeBytes, "1900");
assertEq(output.optimismPortalImpl.proofMaturityDelaySeconds(), _input.proofMaturityDelaySeconds, "2000");
assertEq(
output.optimismPortalImpl.disputeGameFinalityDelaySeconds(), _input.disputeGameFinalityDelaySeconds, "2100"
);
// Architecture assertions. // Architecture assertions.
assertEq(address(output.mipsSingleton.oracle()), address(output.preimageOracleSingleton), "2200"); assertEq(address(dio.mipsSingleton().oracle()), address(dio.preimageOracleSingleton()), "600");
// Ensure that `checkOutput` passes. This is called by the `run` function during execution, // Ensure that `checkOutput` passes. This is called by the `run` function during execution,
// so this just acts as a sanity check. It reverts on failure. // so this just acts as a sanity check. It reverts on failure.
...@@ -297,9 +288,25 @@ contract DeployImplementations_Test is Test { ...@@ -297,9 +288,25 @@ contract DeployImplementations_Test is Test {
} }
function testFuzz_run_largeChallengePeriodSeconds_reverts(uint256 _challengePeriodSeconds) public { function testFuzz_run_largeChallengePeriodSeconds_reverts(uint256 _challengePeriodSeconds) public {
input.challengePeriodSeconds = bound(_challengePeriodSeconds, uint256(type(uint64).max) + 1, type(uint256).max); // Set the defaults.
vm.expectRevert("DeployImplementationsInput: challenge period too large"); dii.set(dii.withdrawalDelaySeconds.selector, withdrawalDelaySeconds);
deployImplementations.run(input); dii.set(dii.minProposalSizeBytes.selector, minProposalSizeBytes);
dii.set(dii.challengePeriodSeconds.selector, challengePeriodSeconds);
dii.set(dii.proofMaturityDelaySeconds.selector, proofMaturityDelaySeconds);
dii.set(dii.disputeGameFinalityDelaySeconds.selector, disputeGameFinalityDelaySeconds);
dii.set(dii.release.selector, release);
dii.set(dii.superchainConfigProxy.selector, address(superchainConfigProxy));
dii.set(dii.protocolVersionsProxy.selector, address(protocolVersionsProxy));
// Set the challenge period to a value that is too large, using vm.store because the setter
// method won't allow it.
challengePeriodSeconds = bound(_challengePeriodSeconds, uint256(type(uint64).max) + 1, type(uint256).max);
uint256 slot =
stdstore.enable_packed_slots().target(address(dii)).sig(dii.challengePeriodSeconds.selector).find();
vm.store(address(dii), bytes32(slot), bytes32(challengePeriodSeconds));
vm.expectRevert("DeployImplementationsInput: challengePeriodSeconds too large");
deployImplementations.run(dii, dio);
} }
} }
......
...@@ -34,48 +34,48 @@ import { OptimismMintableERC20Factory } from "src/universal/OptimismMintableERC2 ...@@ -34,48 +34,48 @@ import { OptimismMintableERC20Factory } from "src/universal/OptimismMintableERC2
contract DeployOPChainInput_Test is Test { contract DeployOPChainInput_Test is Test {
DeployOPChainInput doi; DeployOPChainInput doi;
DeployOPChainInput.Input input = DeployOPChainInput.Input({ // Define defaults.
roles: DeployOPChainInput.Roles({ address opChainProxyAdminOwner = makeAddr("opChainProxyAdminOwner");
opChainProxyAdminOwner: makeAddr("opChainProxyAdminOwner"), address systemConfigOwner = makeAddr("systemConfigOwner");
systemConfigOwner: makeAddr("systemConfigOwner"), address batcher = makeAddr("batcher");
batcher: makeAddr("batcher"), address unsafeBlockSigner = makeAddr("unsafeBlockSigner");
unsafeBlockSigner: makeAddr("unsafeBlockSigner"), address proposer = makeAddr("proposer");
proposer: makeAddr("proposer"), address challenger = makeAddr("challenger");
challenger: makeAddr("challenger") uint32 basefeeScalar = 100;
}), uint32 blobBaseFeeScalar = 200;
basefeeScalar: 100, uint256 l2ChainId = 300;
blobBaseFeeScalar: 200, OPStackManager opsm = OPStackManager(makeAddr("opsm"));
l2ChainId: 300,
opsm: OPStackManager(makeAddr("opsm"))
});
function setUp() public { function setUp() public {
doi = new DeployOPChainInput(); doi = new DeployOPChainInput();
} }
function test_loadInput_succeeds() public { function test_set_succeeds() public {
doi.loadInput(input); doi.set(doi.opChainProxyAdminOwner.selector, opChainProxyAdminOwner);
doi.set(doi.systemConfigOwner.selector, systemConfigOwner);
assertTrue(doi.inputSet(), "100"); doi.set(doi.batcher.selector, batcher);
doi.set(doi.unsafeBlockSigner.selector, unsafeBlockSigner);
// Compare the test input struct to the getter methods. doi.set(doi.proposer.selector, proposer);
assertEq(input.roles.opChainProxyAdminOwner, doi.opChainProxyAdminOwner(), "200"); doi.set(doi.challenger.selector, challenger);
assertEq(input.roles.systemConfigOwner, doi.systemConfigOwner(), "300"); doi.set(doi.basefeeScalar.selector, basefeeScalar);
assertEq(input.roles.batcher, doi.batcher(), "400"); doi.set(doi.blobBaseFeeScalar.selector, blobBaseFeeScalar);
assertEq(input.roles.unsafeBlockSigner, doi.unsafeBlockSigner(), "500"); doi.set(doi.l2ChainId.selector, l2ChainId);
assertEq(input.roles.proposer, doi.proposer(), "600"); doi.set(doi.opsm.selector, address(opsm));
assertEq(input.roles.challenger, doi.challenger(), "700"); // Compare the default inputs to the getter methods.
assertEq(input.basefeeScalar, doi.basefeeScalar(), "800"); assertEq(opChainProxyAdminOwner, doi.opChainProxyAdminOwner(), "200");
assertEq(input.blobBaseFeeScalar, doi.blobBaseFeeScalar(), "900"); assertEq(systemConfigOwner, doi.systemConfigOwner(), "300");
assertEq(input.l2ChainId, doi.l2ChainId(), "1000"); assertEq(batcher, doi.batcher(), "400");
assertEq(address(input.opsm), address(doi.opsm()), "1100"); assertEq(unsafeBlockSigner, doi.unsafeBlockSigner(), "500");
assertEq(proposer, doi.proposer(), "600");
// Compare the test input struct to the `input` getter method. assertEq(challenger, doi.challenger(), "700");
assertEq(keccak256(abi.encode(input)), keccak256(abi.encode(doi.input())), "1200"); assertEq(basefeeScalar, doi.basefeeScalar(), "800");
assertEq(blobBaseFeeScalar, doi.blobBaseFeeScalar(), "900");
assertEq(l2ChainId, doi.l2ChainId(), "1000");
assertEq(address(opsm), address(doi.opsm()), "1100");
} }
function test_getters_whenNotSet_revert() public { function test_getters_whenNotSet_revert() public {
bytes memory expectedErr = "DeployOPChainInput: input not set"; bytes memory expectedErr = "DeployOPChainInput: not set";
vm.expectRevert(expectedErr); vm.expectRevert(expectedErr);
doi.opChainProxyAdminOwner(); doi.opChainProxyAdminOwner();
...@@ -109,90 +109,82 @@ contract DeployOPChainInput_Test is Test { ...@@ -109,90 +109,82 @@ contract DeployOPChainInput_Test is Test {
contract DeployOPChainOutput_Test is Test { contract DeployOPChainOutput_Test is Test {
DeployOPChainOutput doo; DeployOPChainOutput doo;
// Define default outputs to set.
// We set these in storage because doing it locally in test_set_succeeds results in stack too deep.
ProxyAdmin opChainProxyAdmin = ProxyAdmin(makeAddr("optimismPortal2Impl"));
AddressManager addressManager = AddressManager(makeAddr("delayedWETHImpl"));
L1ERC721Bridge l1ERC721BridgeProxy = L1ERC721Bridge(makeAddr("l1ERC721BridgeProxy"));
SystemConfig systemConfigProxy = SystemConfig(makeAddr("systemConfigProxy"));
OptimismMintableERC20Factory optimismMintableERC20FactoryProxy =
OptimismMintableERC20Factory(makeAddr("optimismMintableERC20FactoryProxy"));
L1StandardBridge l1StandardBridgeProxy = L1StandardBridge(payable(makeAddr("l1StandardBridgeProxy")));
L1CrossDomainMessenger l1CrossDomainMessengerProxy = L1CrossDomainMessenger(makeAddr("l1CrossDomainMessengerProxy"));
OptimismPortal2 optimismPortalProxy = OptimismPortal2(payable(makeAddr("optimismPortalProxy")));
DisputeGameFactory disputeGameFactoryProxy = DisputeGameFactory(makeAddr("disputeGameFactoryProxy"));
DisputeGameFactory disputeGameFactoryImpl = DisputeGameFactory(makeAddr("disputeGameFactoryImpl"));
AnchorStateRegistry anchorStateRegistryProxy = AnchorStateRegistry(makeAddr("anchorStateRegistryProxy"));
AnchorStateRegistry anchorStateRegistryImpl = AnchorStateRegistry(makeAddr("anchorStateRegistryImpl"));
FaultDisputeGame faultDisputeGame = FaultDisputeGame(makeAddr("faultDisputeGame"));
PermissionedDisputeGame permissionedDisputeGame = PermissionedDisputeGame(makeAddr("permissionedDisputeGame"));
DelayedWETH delayedWETHPermissionedGameProxy = DelayedWETH(payable(makeAddr("delayedWETHPermissionedGameProxy")));
DelayedWETH delayedWETHPermissionlessGameProxy =
DelayedWETH(payable(makeAddr("delayedWETHPermissionlessGameProxy")));
function setUp() public { function setUp() public {
doo = new DeployOPChainOutput(); doo = new DeployOPChainOutput();
} }
function test_set_succeeds() public { function test_set_succeeds() public {
DeployOPChainOutput.Output memory output = DeployOPChainOutput.Output({ vm.etch(address(opChainProxyAdmin), hex"01");
opChainProxyAdmin: ProxyAdmin(makeAddr("optimismPortal2Impl")), vm.etch(address(addressManager), hex"01");
addressManager: AddressManager(makeAddr("delayedWETHImpl")), vm.etch(address(l1ERC721BridgeProxy), hex"01");
l1ERC721BridgeProxy: L1ERC721Bridge(makeAddr("l1ERC721BridgeProxy")), vm.etch(address(systemConfigProxy), hex"01");
systemConfigProxy: SystemConfig(makeAddr("systemConfigProxy")), vm.etch(address(optimismMintableERC20FactoryProxy), hex"01");
optimismMintableERC20FactoryProxy: OptimismMintableERC20Factory(makeAddr("optimismMintableERC20FactoryProxy")), vm.etch(address(l1StandardBridgeProxy), hex"01");
l1StandardBridgeProxy: L1StandardBridge(payable(makeAddr("l1StandardBridgeProxy"))), vm.etch(address(l1CrossDomainMessengerProxy), hex"01");
l1CrossDomainMessengerProxy: L1CrossDomainMessenger(makeAddr("l1CrossDomainMessengerProxy")), vm.etch(address(optimismPortalProxy), hex"01");
optimismPortalProxy: OptimismPortal2(payable(makeAddr("optimismPortalProxy"))), vm.etch(address(disputeGameFactoryProxy), hex"01");
disputeGameFactoryProxy: DisputeGameFactory(makeAddr("disputeGameFactoryProxy")), vm.etch(address(disputeGameFactoryImpl), hex"01");
disputeGameFactoryImpl: DisputeGameFactory(makeAddr("disputeGameFactoryImpl")), vm.etch(address(anchorStateRegistryProxy), hex"01");
anchorStateRegistryProxy: AnchorStateRegistry(makeAddr("anchorStateRegistryProxy")), vm.etch(address(anchorStateRegistryImpl), hex"01");
anchorStateRegistryImpl: AnchorStateRegistry(makeAddr("anchorStateRegistryImpl")), vm.etch(address(faultDisputeGame), hex"01");
faultDisputeGame: FaultDisputeGame(makeAddr("faultDisputeGame")), vm.etch(address(permissionedDisputeGame), hex"01");
permissionedDisputeGame: PermissionedDisputeGame(makeAddr("permissionedDisputeGame")), vm.etch(address(delayedWETHPermissionedGameProxy), hex"01");
delayedWETHPermissionedGameProxy: DelayedWETH(payable(makeAddr("delayedWETHPermissionedGameProxy"))), vm.etch(address(delayedWETHPermissionlessGameProxy), hex"01");
delayedWETHPermissionlessGameProxy: DelayedWETH(payable(makeAddr("delayedWETHPermissionlessGameProxy")))
}); doo.set(doo.opChainProxyAdmin.selector, address(opChainProxyAdmin));
doo.set(doo.addressManager.selector, address(addressManager));
vm.etch(address(output.opChainProxyAdmin), hex"01"); doo.set(doo.l1ERC721BridgeProxy.selector, address(l1ERC721BridgeProxy));
vm.etch(address(output.addressManager), hex"01"); doo.set(doo.systemConfigProxy.selector, address(systemConfigProxy));
vm.etch(address(output.l1ERC721BridgeProxy), hex"01"); doo.set(doo.optimismMintableERC20FactoryProxy.selector, address(optimismMintableERC20FactoryProxy));
vm.etch(address(output.systemConfigProxy), hex"01"); doo.set(doo.l1StandardBridgeProxy.selector, address(l1StandardBridgeProxy));
vm.etch(address(output.optimismMintableERC20FactoryProxy), hex"01"); doo.set(doo.l1CrossDomainMessengerProxy.selector, address(l1CrossDomainMessengerProxy));
vm.etch(address(output.l1StandardBridgeProxy), hex"01"); doo.set(doo.optimismPortalProxy.selector, address(optimismPortalProxy));
vm.etch(address(output.l1CrossDomainMessengerProxy), hex"01"); doo.set(doo.disputeGameFactoryProxy.selector, address(disputeGameFactoryProxy));
vm.etch(address(output.optimismPortalProxy), hex"01"); doo.set(doo.disputeGameFactoryImpl.selector, address(disputeGameFactoryImpl));
vm.etch(address(output.disputeGameFactoryProxy), hex"01"); doo.set(doo.anchorStateRegistryProxy.selector, address(anchorStateRegistryProxy));
vm.etch(address(output.disputeGameFactoryImpl), hex"01"); doo.set(doo.anchorStateRegistryImpl.selector, address(anchorStateRegistryImpl));
vm.etch(address(output.anchorStateRegistryProxy), hex"01"); doo.set(doo.faultDisputeGame.selector, address(faultDisputeGame));
vm.etch(address(output.anchorStateRegistryImpl), hex"01"); doo.set(doo.permissionedDisputeGame.selector, address(permissionedDisputeGame));
vm.etch(address(output.faultDisputeGame), hex"01"); doo.set(doo.delayedWETHPermissionedGameProxy.selector, address(delayedWETHPermissionedGameProxy));
vm.etch(address(output.permissionedDisputeGame), hex"01"); doo.set(doo.delayedWETHPermissionlessGameProxy.selector, address(delayedWETHPermissionlessGameProxy));
vm.etch(address(output.delayedWETHPermissionedGameProxy), hex"01");
vm.etch(address(output.delayedWETHPermissionlessGameProxy), hex"01"); assertEq(address(opChainProxyAdmin), address(doo.opChainProxyAdmin()), "100");
assertEq(address(addressManager), address(doo.addressManager()), "200");
doo.set(doo.opChainProxyAdmin.selector, address(output.opChainProxyAdmin)); assertEq(address(l1ERC721BridgeProxy), address(doo.l1ERC721BridgeProxy()), "300");
doo.set(doo.addressManager.selector, address(output.addressManager)); assertEq(address(systemConfigProxy), address(doo.systemConfigProxy()), "400");
doo.set(doo.l1ERC721BridgeProxy.selector, address(output.l1ERC721BridgeProxy)); assertEq(address(optimismMintableERC20FactoryProxy), address(doo.optimismMintableERC20FactoryProxy()), "500");
doo.set(doo.systemConfigProxy.selector, address(output.systemConfigProxy)); assertEq(address(l1StandardBridgeProxy), address(doo.l1StandardBridgeProxy()), "600");
doo.set(doo.optimismMintableERC20FactoryProxy.selector, address(output.optimismMintableERC20FactoryProxy)); assertEq(address(l1CrossDomainMessengerProxy), address(doo.l1CrossDomainMessengerProxy()), "700");
doo.set(doo.l1StandardBridgeProxy.selector, address(output.l1StandardBridgeProxy)); assertEq(address(optimismPortalProxy), address(doo.optimismPortalProxy()), "800");
doo.set(doo.l1CrossDomainMessengerProxy.selector, address(output.l1CrossDomainMessengerProxy)); assertEq(address(disputeGameFactoryProxy), address(doo.disputeGameFactoryProxy()), "900");
doo.set(doo.optimismPortalProxy.selector, address(output.optimismPortalProxy)); assertEq(address(disputeGameFactoryImpl), address(doo.disputeGameFactoryImpl()), "1000");
doo.set(doo.disputeGameFactoryProxy.selector, address(output.disputeGameFactoryProxy)); assertEq(address(anchorStateRegistryProxy), address(doo.anchorStateRegistryProxy()), "1100");
doo.set(doo.disputeGameFactoryImpl.selector, address(output.disputeGameFactoryImpl)); assertEq(address(anchorStateRegistryImpl), address(doo.anchorStateRegistryImpl()), "1200");
doo.set(doo.anchorStateRegistryProxy.selector, address(output.anchorStateRegistryProxy)); assertEq(address(faultDisputeGame), address(doo.faultDisputeGame()), "1300");
doo.set(doo.anchorStateRegistryImpl.selector, address(output.anchorStateRegistryImpl)); assertEq(address(permissionedDisputeGame), address(doo.permissionedDisputeGame()), "1400");
doo.set(doo.faultDisputeGame.selector, address(output.faultDisputeGame)); assertEq(address(delayedWETHPermissionedGameProxy), address(doo.delayedWETHPermissionedGameProxy()), "1500");
doo.set(doo.permissionedDisputeGame.selector, address(output.permissionedDisputeGame)); assertEq(address(delayedWETHPermissionlessGameProxy), address(doo.delayedWETHPermissionlessGameProxy()), "1600");
doo.set(doo.delayedWETHPermissionedGameProxy.selector, address(output.delayedWETHPermissionedGameProxy));
doo.set(doo.delayedWETHPermissionlessGameProxy.selector, address(output.delayedWETHPermissionlessGameProxy));
assertEq(address(output.opChainProxyAdmin), address(doo.opChainProxyAdmin()), "100");
assertEq(address(output.addressManager), address(doo.addressManager()), "200");
assertEq(address(output.l1ERC721BridgeProxy), address(doo.l1ERC721BridgeProxy()), "300");
assertEq(address(output.systemConfigProxy), address(doo.systemConfigProxy()), "400");
assertEq(
address(output.optimismMintableERC20FactoryProxy), address(doo.optimismMintableERC20FactoryProxy()), "500"
);
assertEq(address(output.l1StandardBridgeProxy), address(doo.l1StandardBridgeProxy()), "600");
assertEq(address(output.l1CrossDomainMessengerProxy), address(doo.l1CrossDomainMessengerProxy()), "700");
assertEq(address(output.optimismPortalProxy), address(doo.optimismPortalProxy()), "800");
assertEq(address(output.disputeGameFactoryProxy), address(doo.disputeGameFactoryProxy()), "900");
assertEq(address(output.disputeGameFactoryImpl), address(doo.disputeGameFactoryImpl()), "1000");
assertEq(address(output.anchorStateRegistryProxy), address(doo.anchorStateRegistryProxy()), "1100");
assertEq(address(output.anchorStateRegistryImpl), address(doo.anchorStateRegistryImpl()), "1200");
assertEq(address(output.faultDisputeGame), address(doo.faultDisputeGame()), "1300");
assertEq(address(output.permissionedDisputeGame), address(doo.permissionedDisputeGame()), "1400");
assertEq(
address(output.delayedWETHPermissionedGameProxy), address(doo.delayedWETHPermissionedGameProxy()), "1500"
);
assertEq(
address(output.delayedWETHPermissionlessGameProxy),
address(doo.delayedWETHPermissionlessGameProxy()),
"1600"
);
assertEq(keccak256(abi.encode(output)), keccak256(abi.encode(doo.output())), "1700");
} }
function test_getters_whenNotSet_revert() public { function test_getters_whenNotSet_revert() public {
...@@ -324,8 +316,7 @@ contract DeployOPChain_TestBase is Test { ...@@ -324,8 +316,7 @@ contract DeployOPChain_TestBase is Test {
DeployOPChainInput doi; DeployOPChainInput doi;
DeployOPChainOutput doo; DeployOPChainOutput doo;
// We define a default initial input set for DeploySuperchain. The other inputs are dependent // Define default inputs for DeploySuperchain.
// on the outputs of the previous scripts, so we initialize them in the `setUp` method.
address proxyAdminOwner = makeAddr("defaultProxyAdminOwner"); address proxyAdminOwner = makeAddr("defaultProxyAdminOwner");
address protocolVersionsOwner = makeAddr("defaultProtocolVersionsOwner"); address protocolVersionsOwner = makeAddr("defaultProtocolVersionsOwner");
address guardian = makeAddr("defaultGuardian"); address guardian = makeAddr("defaultGuardian");
...@@ -333,38 +324,32 @@ contract DeployOPChain_TestBase is Test { ...@@ -333,38 +324,32 @@ contract DeployOPChain_TestBase is Test {
ProtocolVersion requiredProtocolVersion = ProtocolVersion.wrap(1); ProtocolVersion requiredProtocolVersion = ProtocolVersion.wrap(1);
ProtocolVersion recommendedProtocolVersion = ProtocolVersion.wrap(2); ProtocolVersion recommendedProtocolVersion = ProtocolVersion.wrap(2);
DeployImplementationsInput.Input deployImplementationsInput = DeployImplementationsInput.Input({ // Define default inputs for DeployImplementations.
withdrawalDelaySeconds: 100, // `superchainConfigProxy` and `protocolVersionsProxy` are set during `setUp` since they are
minProposalSizeBytes: 200, // outputs of the previous step.
challengePeriodSeconds: 300, uint256 withdrawalDelaySeconds = 100;
proofMaturityDelaySeconds: 400, uint256 minProposalSizeBytes = 200;
disputeGameFinalityDelaySeconds: 500, uint256 challengePeriodSeconds = 300;
release: "op-contracts/latest", uint256 proofMaturityDelaySeconds = 400;
// These are set during `setUp` since they are outputs of the previous step. uint256 disputeGameFinalityDelaySeconds = 500;
superchainConfigProxy: SuperchainConfig(address(0)), string release = "op-contracts/latest";
protocolVersionsProxy: ProtocolVersions(address(0)) SuperchainConfig superchainConfigProxy;
}); ProtocolVersions protocolVersionsProxy;
DeployOPChainInput.Input deployOPChainInput = DeployOPChainInput.Input({ // Define default inputs for DeployOPChain.
roles: DeployOPChainInput.Roles({ // `opsm` is set during `setUp` since it is an output of the previous step.
opChainProxyAdminOwner: makeAddr("defaultOPChainProxyAdminOwner"), address opChainProxyAdminOwner = makeAddr("defaultOPChainProxyAdminOwner");
systemConfigOwner: makeAddr("defaultSystemConfigOwner"), address systemConfigOwner = makeAddr("defaultSystemConfigOwner");
batcher: makeAddr("defaultBatcher"), address batcher = makeAddr("defaultBatcher");
unsafeBlockSigner: makeAddr("defaultUnsafeBlockSigner"), address unsafeBlockSigner = makeAddr("defaultUnsafeBlockSigner");
proposer: makeAddr("defaultProposer"), address proposer = makeAddr("defaultProposer");
challenger: makeAddr("defaultChallenger") address challenger = makeAddr("defaultChallenger");
}), uint32 basefeeScalar = 100;
basefeeScalar: 100, uint32 blobBaseFeeScalar = 200;
blobBaseFeeScalar: 200, uint256 l2ChainId = 300;
l2ChainId: 300, OPStackManager opsm = OPStackManager(address(0));
// This is set during `setUp` since it is an output of the previous step.
opsm: OPStackManager(address(0)) function setUp() public virtual {
});
// Set during `setUp`.
DeployImplementationsOutput.Output deployImplementationsOutput;
function setUp() public {
// Initialize deploy scripts. // Initialize deploy scripts.
DeploySuperchain deploySuperchain = new DeploySuperchain(); DeploySuperchain deploySuperchain = new DeploySuperchain();
(DeploySuperchainInput dsi, DeploySuperchainOutput dso) = deploySuperchain.etchIOContracts(); (DeploySuperchainInput dsi, DeploySuperchainOutput dso) = deploySuperchain.etchIOContracts();
...@@ -376,21 +361,31 @@ contract DeployOPChain_TestBase is Test { ...@@ -376,21 +361,31 @@ contract DeployOPChain_TestBase is Test {
dsi.set(dsi.recommendedProtocolVersion.selector, recommendedProtocolVersion); dsi.set(dsi.recommendedProtocolVersion.selector, recommendedProtocolVersion);
DeployImplementations deployImplementations = new DeployImplementations(); DeployImplementations deployImplementations = new DeployImplementations();
(DeployImplementationsInput dii, DeployImplementationsOutput dio) = deployImplementations.etchIOContracts();
deployOPChain = new DeployOPChain(); deployOPChain = new DeployOPChain();
(doi, doo) = deployOPChain.getIOContracts(); (doi, doo) = deployOPChain.etchIOContracts();
// Deploy the superchain contracts. // Deploy the superchain contracts.
deploySuperchain.run(dsi, dso); deploySuperchain.run(dsi, dso);
// Populate the input struct for DeployImplementations based on the output of DeploySuperchain. // Populate the inputs for DeployImplementations based on the output of DeploySuperchain.
deployImplementationsInput.superchainConfigProxy = dso.superchainConfigProxy(); superchainConfigProxy = dso.superchainConfigProxy();
deployImplementationsInput.protocolVersionsProxy = dso.protocolVersionsProxy(); protocolVersionsProxy = dso.protocolVersionsProxy();
// Deploy the implementations using the updated DeployImplementations input struct. // Deploy the implementations.
deployImplementationsOutput = deployImplementations.run(deployImplementationsInput); dii.set(dii.withdrawalDelaySeconds.selector, withdrawalDelaySeconds);
dii.set(dii.minProposalSizeBytes.selector, minProposalSizeBytes);
// Set the OPStackManager on the input struct for DeployOPChain. dii.set(dii.challengePeriodSeconds.selector, challengePeriodSeconds);
deployOPChainInput.opsm = deployImplementationsOutput.opsm; dii.set(dii.proofMaturityDelaySeconds.selector, proofMaturityDelaySeconds);
dii.set(dii.disputeGameFinalityDelaySeconds.selector, disputeGameFinalityDelaySeconds);
dii.set(dii.release.selector, release);
dii.set(dii.superchainConfigProxy.selector, address(superchainConfigProxy));
dii.set(dii.protocolVersionsProxy.selector, address(protocolVersionsProxy));
deployImplementations.run(dii, dio);
// Set the OPStackManager input for DeployOPChain.
opsm = dio.opsm();
} }
// See the function of the same name in the `DeployImplementations_Test` contract of // See the function of the same name in the `DeployImplementations_Test` contract of
...@@ -401,56 +396,55 @@ contract DeployOPChain_TestBase is Test { ...@@ -401,56 +396,55 @@ contract DeployOPChain_TestBase is Test {
} }
contract DeployOPChain_Test is DeployOPChain_TestBase { contract DeployOPChain_Test is DeployOPChain_TestBase {
function testFuzz_run_succeeds(DeployOPChainInput.Input memory _input) public { function hash(bytes32 _seed, uint256 _i) internal pure returns (bytes32) {
vm.assume(_input.roles.opChainProxyAdminOwner != address(0)); return keccak256(abi.encode(_seed, _i));
vm.assume(_input.roles.systemConfigOwner != address(0)); }
vm.assume(_input.roles.batcher != address(0));
vm.assume(_input.roles.unsafeBlockSigner != address(0));
vm.assume(_input.roles.proposer != address(0));
vm.assume(_input.roles.challenger != address(0));
vm.assume(_input.l2ChainId != 0 && _input.l2ChainId != block.chainid);
_input.opsm = deployOPChainInput.opsm;
DeployOPChainOutput.Output memory output = deployOPChain.run(_input); function testFuzz_run_memory_succeeds(bytes32 _seed) public {
opChainProxyAdminOwner = address(uint160(uint256(hash(_seed, 0))));
systemConfigOwner = address(uint160(uint256(hash(_seed, 1))));
batcher = address(uint160(uint256(hash(_seed, 2))));
unsafeBlockSigner = address(uint160(uint256(hash(_seed, 3))));
proposer = address(uint160(uint256(hash(_seed, 4))));
challenger = address(uint160(uint256(hash(_seed, 5))));
basefeeScalar = uint32(uint256(hash(_seed, 6)));
blobBaseFeeScalar = uint32(uint256(hash(_seed, 7)));
l2ChainId = uint256(uint256(hash(_seed, 8)));
doi.set(doi.opChainProxyAdminOwner.selector, opChainProxyAdminOwner);
doi.set(doi.systemConfigOwner.selector, systemConfigOwner);
doi.set(doi.batcher.selector, batcher);
doi.set(doi.unsafeBlockSigner.selector, unsafeBlockSigner);
doi.set(doi.proposer.selector, proposer);
doi.set(doi.challenger.selector, challenger);
doi.set(doi.basefeeScalar.selector, basefeeScalar);
doi.set(doi.blobBaseFeeScalar.selector, blobBaseFeeScalar);
doi.set(doi.l2ChainId.selector, l2ChainId);
doi.set(doi.opsm.selector, address(opsm)); // Not fuzzed since it must be an actual instance.
deployOPChain.run(doi, doo);
// TODO Add fault proof contract assertions below once OPSM fully supports them. // TODO Add fault proof contract assertions below once OPSM fully supports them.
// Assert that individual input fields were properly set based on the input struct. // Assert that individual input fields were properly set based on the inputs.
assertEq(_input.roles.opChainProxyAdminOwner, doi.opChainProxyAdminOwner(), "100"); assertEq(opChainProxyAdminOwner, doi.opChainProxyAdminOwner(), "100");
assertEq(_input.roles.systemConfigOwner, doi.systemConfigOwner(), "200"); assertEq(systemConfigOwner, doi.systemConfigOwner(), "200");
assertEq(_input.roles.batcher, doi.batcher(), "300"); assertEq(batcher, doi.batcher(), "300");
assertEq(_input.roles.unsafeBlockSigner, doi.unsafeBlockSigner(), "400"); assertEq(unsafeBlockSigner, doi.unsafeBlockSigner(), "400");
assertEq(_input.roles.proposer, doi.proposer(), "500"); assertEq(proposer, doi.proposer(), "500");
assertEq(_input.roles.challenger, doi.challenger(), "600"); assertEq(challenger, doi.challenger(), "600");
assertEq(_input.basefeeScalar, doi.basefeeScalar(), "700"); assertEq(basefeeScalar, doi.basefeeScalar(), "700");
assertEq(_input.blobBaseFeeScalar, doi.blobBaseFeeScalar(), "800"); assertEq(blobBaseFeeScalar, doi.blobBaseFeeScalar(), "800");
assertEq(_input.l2ChainId, doi.l2ChainId(), "900"); assertEq(l2ChainId, doi.l2ChainId(), "900");
// Assert that individual output fields were properly set based on the output struct.
assertEq(address(output.opChainProxyAdmin), address(doo.opChainProxyAdmin()), "1100");
assertEq(address(output.addressManager), address(doo.addressManager()), "1200");
assertEq(address(output.l1ERC721BridgeProxy), address(doo.l1ERC721BridgeProxy()), "1300");
assertEq(address(output.systemConfigProxy), address(doo.systemConfigProxy()), "1400");
assertEq(
address(output.optimismMintableERC20FactoryProxy), address(doo.optimismMintableERC20FactoryProxy()), "1500"
);
assertEq(address(output.l1StandardBridgeProxy), address(doo.l1StandardBridgeProxy()), "1600");
assertEq(address(output.l1CrossDomainMessengerProxy), address(doo.l1CrossDomainMessengerProxy()), "1700");
assertEq(address(output.optimismPortalProxy), address(doo.optimismPortalProxy()), "1800");
// Assert that the full input and output structs were properly set.
assertEq(keccak256(abi.encode(_input)), keccak256(abi.encode(DeployOPChainInput(doi).input())), "1900");
assertEq(keccak256(abi.encode(output)), keccak256(abi.encode(DeployOPChainOutput(doo).output())), "2000");
// Assert inputs were properly passed through to the contract initializers. // Assert inputs were properly passed through to the contract initializers.
assertEq(address(output.opChainProxyAdmin.owner()), _input.roles.opChainProxyAdminOwner, "2100"); assertEq(address(doo.opChainProxyAdmin().owner()), opChainProxyAdminOwner, "2100");
assertEq(address(output.systemConfigProxy.owner()), _input.roles.systemConfigOwner, "2200"); assertEq(address(doo.systemConfigProxy().owner()), systemConfigOwner, "2200");
address batcher = address(uint160(uint256(output.systemConfigProxy.batcherHash()))); address batcherActual = address(uint160(uint256(doo.systemConfigProxy().batcherHash())));
assertEq(batcher, _input.roles.batcher, "2300"); assertEq(batcherActual, batcher, "2300");
assertEq(address(output.systemConfigProxy.unsafeBlockSigner()), _input.roles.unsafeBlockSigner, "2400"); assertEq(address(doo.systemConfigProxy().unsafeBlockSigner()), unsafeBlockSigner, "2400");
// assertEq(address(...proposer()), _input.roles.proposer, "2500"); // TODO once we deploy dispute games. // assertEq(address(...proposer()), proposer, "2500"); // TODO once we deploy dispute games.
// assertEq(address(...challenger()), _input.roles.challenger, "2600"); // TODO once we deploy dispute games. // assertEq(address(...challenger()), challenger, "2600"); // TODO once we deploy dispute games.
// Most architecture assertions are handled within the OP Stack Manager itself and therefore // Most architecture assertions are handled within the OP Stack Manager itself and therefore
// we only assert on the things that are not visible onchain. // we only assert on the things that are not visible onchain.
......
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity 0.8.15; pragma solidity 0.8.15;
import { Test } from "forge-std/Test.sol"; import { Test, stdStorage, StdStorage } from "forge-std/Test.sol";
import { DeployOPChainInput } from "scripts/DeployOPChain.s.sol"; import { DeployOPChainInput } from "scripts/DeployOPChain.s.sol";
import { DeployOPChain_TestBase } from "test/DeployOPChain.t.sol"; import { DeployOPChain_TestBase } from "test/DeployOPChain.t.sol";
...@@ -32,42 +32,58 @@ contract OPStackManager_Harness is OPStackManager { ...@@ -32,42 +32,58 @@ contract OPStackManager_Harness is OPStackManager {
// we can use its setup to deploy the implementations similarly to how a real deployment would // we can use its setup to deploy the implementations similarly to how a real deployment would
// happen. // happen.
contract OPStackManager_Deploy_Test is DeployOPChain_TestBase { contract OPStackManager_Deploy_Test is DeployOPChain_TestBase {
using stdStorage for StdStorage;
function setUp() public override {
DeployOPChain_TestBase.setUp();
doi.set(doi.opChainProxyAdminOwner.selector, opChainProxyAdminOwner);
doi.set(doi.systemConfigOwner.selector, systemConfigOwner);
doi.set(doi.batcher.selector, batcher);
doi.set(doi.unsafeBlockSigner.selector, unsafeBlockSigner);
doi.set(doi.proposer.selector, proposer);
doi.set(doi.challenger.selector, challenger);
doi.set(doi.basefeeScalar.selector, basefeeScalar);
doi.set(doi.blobBaseFeeScalar.selector, blobBaseFeeScalar);
doi.set(doi.l2ChainId.selector, l2ChainId);
doi.set(doi.opsm.selector, address(opsm));
}
// This helper function is used to convert the input struct type defined in DeployOPChain.s.sol // This helper function is used to convert the input struct type defined in DeployOPChain.s.sol
// to the input struct type defined in OPStackManager.sol. // to the input struct type defined in OPStackManager.sol.
function toOPSMDeployInput(DeployOPChainInput.Input memory input) function toOPSMDeployInput(DeployOPChainInput _doi) internal view returns (OPStackManager.DeployInput memory) {
internal
pure
returns (OPStackManager.DeployInput memory)
{
return OPStackManager.DeployInput({ return OPStackManager.DeployInput({
roles: OPStackManager.Roles({ roles: OPStackManager.Roles({
opChainProxyAdminOwner: input.roles.opChainProxyAdminOwner, opChainProxyAdminOwner: _doi.opChainProxyAdminOwner(),
systemConfigOwner: input.roles.systemConfigOwner, systemConfigOwner: _doi.systemConfigOwner(),
batcher: input.roles.batcher, batcher: _doi.batcher(),
unsafeBlockSigner: input.roles.unsafeBlockSigner, unsafeBlockSigner: _doi.unsafeBlockSigner(),
proposer: input.roles.proposer, proposer: _doi.proposer(),
challenger: input.roles.challenger challenger: _doi.challenger()
}), }),
basefeeScalar: input.basefeeScalar, basefeeScalar: _doi.basefeeScalar(),
blobBasefeeScalar: input.blobBaseFeeScalar, blobBasefeeScalar: _doi.blobBaseFeeScalar(),
l2ChainId: input.l2ChainId l2ChainId: _doi.l2ChainId()
}); });
} }
function test_deploy_l2ChainIdEqualsZero_reverts() public { function test_deploy_l2ChainIdEqualsZero_reverts() public {
deployOPChainInput.l2ChainId = 0; OPStackManager.DeployInput memory deployInput = toOPSMDeployInput(doi);
deployInput.l2ChainId = 0;
vm.expectRevert(OPStackManager.InvalidChainId.selector); vm.expectRevert(OPStackManager.InvalidChainId.selector);
deployImplementationsOutput.opsm.deploy(toOPSMDeployInput(deployOPChainInput)); opsm.deploy(deployInput);
} }
function test_deploy_l2ChainIdEqualsCurrentChainId_reverts() public { function test_deploy_l2ChainIdEqualsCurrentChainId_reverts() public {
deployOPChainInput.l2ChainId = block.chainid; OPStackManager.DeployInput memory deployInput = toOPSMDeployInput(doi);
deployInput.l2ChainId = block.chainid;
vm.expectRevert(OPStackManager.InvalidChainId.selector); vm.expectRevert(OPStackManager.InvalidChainId.selector);
deployImplementationsOutput.opsm.deploy(toOPSMDeployInput(deployOPChainInput)); opsm.deploy(deployInput);
} }
function test_deploy_succeeds() public { function test_deploy_succeeds() public {
deployImplementationsOutput.opsm.deploy(toOPSMDeployInput(deployOPChainInput)); opsm.deploy(toOPSMDeployInput(doi));
} }
} }
......
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