Skip to content

Commit

Permalink
contracts: clean up deploy script abstractions (#12336)
Browse files Browse the repository at this point in the history
* contracts: clean up deploy script abstractions

Move the implementation deployments into `deployImplementations`
and the initializations into the initizer function so that things
are grouped more logically. Even though we use OPSM for modern
deployments, the legacy code is still in the repo. This change
makes it easier to implement Standard L2 Genesis, where we depend
on the `OptimismPortal` being initialized before the `SystemConfig`,
since the `SystemConfig` makes calls to the portal during its
`initialize` call.

* op-e2e: remove dependency on contracts existing

Modularizes the functionality more

* lint: fix
  • Loading branch information
tynes authored Oct 5, 2024
1 parent e9b5eeb commit e165a7e
Show file tree
Hide file tree
Showing 3 changed files with 123 additions and 98 deletions.
28 changes: 15 additions & 13 deletions op-e2e/system/bridge/validity_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -327,18 +327,21 @@ func testMixedWithdrawalValidity(t *testing.T, allocType config.AllocType) {
_ = depositContract
require.NoError(t, err)

l2OutputOracle, err := bindings.NewL2OutputOracleCaller(cfg.L1Deployments.L2OutputOracleProxy, l1Client)
require.NoError(t, err)

finalizationPeriod, err := l2OutputOracle.FINALIZATIONPERIODSECONDS(nil)
require.NoError(t, err)
require.Equal(t, cfg.DeployConfig.FinalizationPeriodSeconds, finalizationPeriod.Uint64())

disputeGameFactory, err := bindings.NewDisputeGameFactoryCaller(cfg.L1Deployments.DisputeGameFactoryProxy, l1Client)
require.NoError(t, err)

optimismPortal2, err := bindingspreview.NewOptimismPortal2Caller(cfg.L1Deployments.OptimismPortalProxy, l1Client)
require.NoError(t, err)
var l2OutputOracle *bindings.L2OutputOracleCaller
var disputeGameFactory *bindings.DisputeGameFactoryCaller
var optimismPortal2 *bindingspreview.OptimismPortal2Caller
if allocType.UsesProofs() {
disputeGameFactory, err = bindings.NewDisputeGameFactoryCaller(cfg.L1Deployments.DisputeGameFactoryProxy, l1Client)
require.NoError(t, err)
optimismPortal2, err = bindingspreview.NewOptimismPortal2Caller(cfg.L1Deployments.OptimismPortalProxy, l1Client)
require.NoError(t, err)
} else {
l2OutputOracle, err = bindings.NewL2OutputOracleCaller(cfg.L1Deployments.L2OutputOracleProxy, l1Client)
require.NoError(t, err)
finalizationPeriod, err := l2OutputOracle.FINALIZATIONPERIODSECONDS(nil)
require.NoError(t, err)
require.Equal(t, cfg.DeployConfig.FinalizationPeriodSeconds, finalizationPeriod.Uint64())
}

// Create a struct used to track our transactors and their transactions sent.
type TestAccountState struct {
Expand Down Expand Up @@ -429,7 +432,6 @@ func testMixedWithdrawalValidity(t *testing.T, allocType config.AllocType) {
transactor.ExpectedL2Nonce = transactor.ExpectedL2Nonce + 1

// Wait for the finalization period, then we can finalize this withdrawal.
require.NotEqual(t, cfg.L1Deployments.L2OutputOracleProxy, common.Address{})
var blockNumber uint64
if allocType.UsesProofs() {
blockNumber, err = wait.ForGamePublished(ctx, l1Client, cfg.L1Deployments.OptimismPortalProxy, cfg.L1Deployments.DisputeGameFactoryProxy, receipt.BlockNumber)
Expand Down
184 changes: 102 additions & 82 deletions packages/contracts-bedrock/scripts/deploy/Deploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -288,19 +288,6 @@ contract Deploy is Deployer {
// Deploy Current OPChain Contracts
deployOpChain();

// Deploy and setup the legacy (pre-faultproofs) contracts
deployERC1967Proxy("L2OutputOracleProxy");
deployL2OutputOracle();
initializeL2OutputOracle();

// The OptimismPortalProxy contract is used both with and without Fault Proofs enabled, and is deployed by
// deployOPChain. So we only need to deploy the legacy OptimismPortal implementation and initialize with it
// when Fault Proofs are disabled.
if (!cfg.useFaultProofs()) {
deployOptimismPortal();
initializeOptimismPortal();
}

if (cfg.useAltDA()) {
bytes32 typeHash = keccak256(bytes(cfg.daCommitmentType()));
bytes32 keccakHash = keccak256(bytes("KeccakCommitment"));
Expand Down Expand Up @@ -384,6 +371,12 @@ contract Deploy is Deployer {
}
di.run(dii, dio);

// Temporary patch for legacy system
if (!cfg.useFaultProofs()) {
deployOptimismPortal();
deployL2OutputOracle();
}

save("L1CrossDomainMessenger", address(dio.l1CrossDomainMessengerImpl()));
save("OptimismMintableERC20Factory", address(dio.optimismMintableERC20FactoryImpl()));
save("SystemConfig", address(dio.systemConfigImpl()));
Expand Down Expand Up @@ -456,6 +449,11 @@ contract Deploy is Deployer {

deployAnchorStateRegistry();

// Deploy and setup the legacy (pre-faultproofs) contracts
if (!cfg.useFaultProofs()) {
deployERC1967Proxy("L2OutputOracleProxy");
}

initializeOpChain();

setAlphabetFaultGameImplementation({ _allowUpgrade: false });
Expand All @@ -471,13 +469,8 @@ contract Deploy is Deployer {
/// initialize function
function initializeOpChain() public {
console.log("Initializing Op Chain proxies");
// The OptimismPortal Proxy is shared between the legacy and current deployment path, so we should initialize
// the OptimismPortal2 only if using FaultProofs.
if (cfg.useFaultProofs()) {
console.log("Fault proofs enabled. Initializing the OptimismPortal proxy with the OptimismPortal2.");
initializeOptimismPortal2();
}

initializeOptimismPortal();
initializeSystemConfig();
initializeL1StandardBridge();
initializeL1ERC721Bridge();
Expand All @@ -487,6 +480,10 @@ contract Deploy is Deployer {
initializeDelayedWETH();
initializePermissionedDelayedWETH();
initializeAnchorStateRegistry();

if (!cfg.useFaultProofs()) {
initializeL2OutputOracle();
}
}

/// @notice Add AltDA setup to the OP chain
Expand Down Expand Up @@ -643,23 +640,50 @@ contract Deploy is Deployer {

/// @notice Deploy the OptimismPortal
function deployOptimismPortal() public broadcast returns (address addr_) {
if (cfg.useInterop()) {
console.log("Attempting to deploy OptimismPortal with interop, this config is a noop");
}
if (cfg.useFaultProofs()) {
// Could also verify this inside DeployConfig but doing it here is a bit more reliable.
require(
uint32(cfg.respectedGameType()) == cfg.respectedGameType(),
"Deploy: respectedGameType must fit into uint32"
);

addr_ = DeployUtils.create2AndSave({
_save: this,
_salt: _implSalt(),
_name: "OptimismPortal",
_args: DeployUtils.encodeConstructor(abi.encodeCall(IOptimismPortal.__constructor__, ()))
});
addr_ = DeployUtils.create2AndSave({
_save: this,
_salt: _implSalt(),
_name: "OptimismPortal2",
_args: DeployUtils.encodeConstructor(
abi.encodeCall(
IOptimismPortal2.__constructor__,
(cfg.proofMaturityDelaySeconds(), cfg.disputeGameFinalityDelaySeconds())
)
)
});

// Override the `OptimismPortal2` contract to the deployed implementation. This is necessary
// to check the `OptimismPortal2` implementation alongside dependent contracts, which
// are always proxies.
Types.ContractSet memory contracts = _proxies();
contracts.OptimismPortal2 = addr_;
ChainAssertions.checkOptimismPortal2({ _contracts: contracts, _cfg: cfg, _isProxy: false });
} else {
if (cfg.useInterop()) {
console.log("Attempting to deploy OptimismPortal with interop, this config is a noop");
}

// Override the `OptimismPortal` contract to the deployed implementation. This is necessary
// to check the `OptimismPortal` implementation alongside dependent contracts, which
// are always proxies.
Types.ContractSet memory contracts = _proxies();
contracts.OptimismPortal = addr_;
ChainAssertions.checkOptimismPortal({ _contracts: contracts, _cfg: cfg, _isProxy: false });
addr_ = DeployUtils.create2AndSave({
_save: this,
_salt: _implSalt(),
_name: "OptimismPortal",
_args: DeployUtils.encodeConstructor(abi.encodeCall(IOptimismPortal.__constructor__, ()))
});

// Override the `OptimismPortal` contract to the deployed implementation. This is necessary
// to check the `OptimismPortal` implementation alongside dependent contracts, which
// are always proxies.
Types.ContractSet memory contracts = _proxies();
contracts.OptimismPortal = addr_;
ChainAssertions.checkOptimismPortal({ _contracts: contracts, _cfg: cfg, _isProxy: false });
}
}

/// @notice Deploy the L2OutputOracle
Expand Down Expand Up @@ -1128,63 +1152,59 @@ contract Deploy is Deployer {

/// @notice Initialize the OptimismPortal
function initializeOptimismPortal() public broadcast {
console.log("Upgrading and initializing OptimismPortal proxy");
address optimismPortalProxy = mustGetAddress("OptimismPortalProxy");
address optimismPortal = mustGetAddress("OptimismPortal");
address l2OutputOracleProxy = mustGetAddress("L2OutputOracleProxy");
address systemConfigProxy = mustGetAddress("SystemConfigProxy");
address superchainConfigProxy = mustGetAddress("SuperchainConfigProxy");

IProxyAdmin proxyAdmin = IProxyAdmin(payable(mustGetAddress("ProxyAdmin")));
proxyAdmin.upgradeAndCall({
_proxy: payable(optimismPortalProxy),
_implementation: optimismPortal,
_data: abi.encodeCall(
IOptimismPortal.initialize,
(
IL2OutputOracle(l2OutputOracleProxy),
ISystemConfig(systemConfigProxy),
ISuperchainConfig(superchainConfigProxy)
if (cfg.useFaultProofs()) {
console.log("Upgrading and initializing OptimismPortal2 proxy");
address optimismPortal2 = mustGetAddress("OptimismPortal2");
address disputeGameFactoryProxy = mustGetAddress("DisputeGameFactoryProxy");

IProxyAdmin proxyAdmin = IProxyAdmin(payable(mustGetAddress("ProxyAdmin")));
proxyAdmin.upgradeAndCall({
_proxy: payable(optimismPortalProxy),
_implementation: optimismPortal2,
_data: abi.encodeCall(
IOptimismPortal2.initialize,
(
IDisputeGameFactory(disputeGameFactoryProxy),
ISystemConfig(systemConfigProxy),
ISuperchainConfig(superchainConfigProxy),
GameType.wrap(uint32(cfg.respectedGameType()))
)
)
)
});
});

IOptimismPortal portal = IOptimismPortal(payable(optimismPortalProxy));
string memory version = portal.version();
console.log("OptimismPortal version: %s", version);
IOptimismPortal2 portal = IOptimismPortal2(payable(optimismPortalProxy));
string memory version = portal.version();
console.log("OptimismPortal2 version: %s", version);

ChainAssertions.checkOptimismPortal({ _contracts: _proxies(), _cfg: cfg, _isProxy: true });
}

/// @notice Initialize the OptimismPortal2
function initializeOptimismPortal2() public broadcast {
console.log("Upgrading and initializing OptimismPortal2 proxy");
address optimismPortalProxy = mustGetAddress("OptimismPortalProxy");
address optimismPortal2 = mustGetAddress("OptimismPortal2");
address disputeGameFactoryProxy = mustGetAddress("DisputeGameFactoryProxy");
address systemConfigProxy = mustGetAddress("SystemConfigProxy");
address superchainConfigProxy = mustGetAddress("SuperchainConfigProxy");

IProxyAdmin proxyAdmin = IProxyAdmin(payable(mustGetAddress("ProxyAdmin")));
proxyAdmin.upgradeAndCall({
_proxy: payable(optimismPortalProxy),
_implementation: optimismPortal2,
_data: abi.encodeCall(
IOptimismPortal2.initialize,
(
IDisputeGameFactory(disputeGameFactoryProxy),
ISystemConfig(systemConfigProxy),
ISuperchainConfig(superchainConfigProxy),
GameType.wrap(uint32(cfg.respectedGameType()))
ChainAssertions.checkOptimismPortal2({ _contracts: _proxies(), _cfg: cfg, _isProxy: true });
} else {
console.log("Upgrading and initializing OptimismPortal proxy");
address optimismPortal = mustGetAddress("OptimismPortal");
address l2OutputOracleProxy = mustGetAddress("L2OutputOracleProxy");

IProxyAdmin proxyAdmin = IProxyAdmin(payable(mustGetAddress("ProxyAdmin")));
proxyAdmin.upgradeAndCall({
_proxy: payable(optimismPortalProxy),
_implementation: optimismPortal,
_data: abi.encodeCall(
IOptimismPortal.initialize,
(
IL2OutputOracle(l2OutputOracleProxy),
ISystemConfig(systemConfigProxy),
ISuperchainConfig(superchainConfigProxy)
)
)
)
});
});

IOptimismPortal2 portal = IOptimismPortal2(payable(optimismPortalProxy));
string memory version = portal.version();
console.log("OptimismPortal2 version: %s", version);
IOptimismPortal portal = IOptimismPortal(payable(optimismPortalProxy));
string memory version = portal.version();
console.log("OptimismPortal version: %s", version);

ChainAssertions.checkOptimismPortal2({ _contracts: _proxies(), _cfg: cfg, _isProxy: true });
ChainAssertions.checkOptimismPortal({ _contracts: _proxies(), _cfg: cfg, _isProxy: true });
}
}

/// @notice Transfer ownership of the DisputeGameFactory contract to the final system owner
Expand Down
9 changes: 6 additions & 3 deletions packages/contracts-bedrock/test/setup/Setup.sol
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,6 @@ contract Setup {
optimismPortal2 = IOptimismPortal2(deploy.mustGetAddress("OptimismPortalProxy"));
disputeGameFactory = IDisputeGameFactory(deploy.mustGetAddress("DisputeGameFactoryProxy"));
delayedWeth = IDelayedWETH(deploy.mustGetAddress("DelayedWETHProxy"));
l2OutputOracle = IL2OutputOracle(deploy.mustGetAddress("L2OutputOracleProxy"));
systemConfig = ISystemConfig(deploy.mustGetAddress("SystemConfigProxy"));
l1StandardBridge = IL1StandardBridge(deploy.mustGetAddress("L1StandardBridgeProxy"));
l1CrossDomainMessenger = IL1CrossDomainMessenger(deploy.mustGetAddress("L1CrossDomainMessengerProxy"));
Expand All @@ -159,8 +158,6 @@ contract Setup {
superchainConfig = ISuperchainConfig(deploy.mustGetAddress("SuperchainConfigProxy"));
anchorStateRegistry = IAnchorStateRegistry(deploy.mustGetAddress("AnchorStateRegistryProxy"));

vm.label(address(l2OutputOracle), "L2OutputOracle");
vm.label(deploy.mustGetAddress("L2OutputOracleProxy"), "L2OutputOracleProxy");
vm.label(address(optimismPortal), "OptimismPortal");
vm.label(deploy.mustGetAddress("OptimismPortalProxy"), "OptimismPortalProxy");
vm.label(address(disputeGameFactory), "DisputeGameFactory");
Expand All @@ -184,6 +181,12 @@ contract Setup {
vm.label(deploy.mustGetAddress("SuperchainConfigProxy"), "SuperchainConfigProxy");
vm.label(AddressAliasHelper.applyL1ToL2Alias(address(l1CrossDomainMessenger)), "L1CrossDomainMessenger_aliased");

if (!deploy.cfg().useFaultProofs()) {
l2OutputOracle = IL2OutputOracle(deploy.mustGetAddress("L2OutputOracleProxy"));
vm.label(address(l2OutputOracle), "L2OutputOracle");
vm.label(deploy.mustGetAddress("L2OutputOracleProxy"), "L2OutputOracleProxy");
}

if (deploy.cfg().useAltDA()) {
dataAvailabilityChallenge =
IDataAvailabilityChallenge(deploy.mustGetAddress("DataAvailabilityChallengeProxy"));
Expand Down

0 comments on commit e165a7e

Please sign in to comment.