Commit ca293fb4 authored by mergify[bot]'s avatar mergify[bot] Committed by GitHub

Merge pull request #4113 from ethereum-optimism/sc/ctb-single-dictator

maint(ctb): combine Dictator contracts
parents 7b4a0a87 1a0bd871
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import { ProxyAdmin } from "../universal/ProxyAdmin.sol";
import { L2OutputOracle } from "../L1/L2OutputOracle.sol";
import { OptimismPortal } from "../L1/OptimismPortal.sol";
import { L1CrossDomainMessenger } from "../L1/L1CrossDomainMessenger.sol";
import { L1StandardBridge } from "../L1/L1StandardBridge.sol";
import { L1ERC721Bridge } from "../L1/L1ERC721Bridge.sol";
import { SystemConfig } from "../L1/SystemConfig.sol";
import { OptimismMintableERC20Factory } from "../universal/OptimismMintableERC20Factory.sol";
import { AddressManager } from "../legacy/AddressManager.sol";
import { PortalSender } from "./PortalSender.sol";
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
/**
* @title BaseSystemDictator
* @notice The BaseSystemDictator is a base contract for SystemDictator contracts.
*/
contract BaseSystemDictator is Ownable {
/**
* @notice Basic system configuration.
*/
struct GlobalConfig {
AddressManager addressManager;
ProxyAdmin proxyAdmin;
address controller;
address finalOwner;
}
/**
* @notice Set of proxy addresses.
*/
struct ProxyAddressConfig {
address l2OutputOracleProxy;
address optimismPortalProxy;
address l1CrossDomainMessengerProxy;
address l1StandardBridgeProxy;
address optimismMintableERC20FactoryProxy;
address l1ERC721BridgeProxy;
address systemConfigProxy;
}
/**
* @notice Set of implementation addresses.
*/
struct ImplementationAddressConfig {
L2OutputOracle l2OutputOracleImpl;
OptimismPortal optimismPortalImpl;
L1CrossDomainMessenger l1CrossDomainMessengerImpl;
L1StandardBridge l1StandardBridgeImpl;
OptimismMintableERC20Factory optimismMintableERC20FactoryImpl;
L1ERC721Bridge l1ERC721BridgeImpl;
PortalSender portalSenderImpl;
SystemConfig systemConfigImpl;
}
/**
* @notice Dynamic L2OutputOracle config.
*/
struct L2OutputOracleDynamicConfig {
uint256 l2OutputOracleStartingBlockNumber;
uint256 l2OutputOracleStartingTimestamp;
}
/**
* @notice Values for the system config contract.
*/
struct SystemConfigConfig {
address owner;
uint256 overhead;
uint256 scalar;
bytes32 batcherHash;
uint64 gasLimit;
}
/**
* @notice Combined system configuration.
*/
struct DeployConfig {
GlobalConfig globalConfig;
ProxyAddressConfig proxyAddressConfig;
ImplementationAddressConfig implementationAddressConfig;
SystemConfigConfig systemConfigConfig;
}
/**
* @notice System configuration.
*/
DeployConfig public config;
/**
* @notice Dynamic configuration for the L2OutputOracle.
*/
L2OutputOracleDynamicConfig public l2OutputOracleDynamicConfig;
/**
* @notice Current step;
*/
uint8 public currentStep = 1;
/**
* @notice Whether or not dynamic config has been set.
*/
bool public dynamicConfigSet;
/**
* @notice Checks that the current step is the expected step, then bumps the current step.
*
* @param _step Current step.
*/
modifier step(uint8 _step) {
require(currentStep == _step, "BaseSystemDictator: incorrect step");
_;
currentStep++;
}
/**
* @param _config System configuration.
*/
constructor(DeployConfig memory _config) Ownable() {
config = _config;
_transferOwnership(config.globalConfig.controller);
}
/**
* @notice Allows the owner to update dynamic L2OutputOracle config.
*
* @param _l2OutputOracleDynamicConfig Dynamic L2OutputOracle config.
*/
function updateL2OutputOracleDynamicConfig(
L2OutputOracleDynamicConfig memory _l2OutputOracleDynamicConfig
) external onlyOwner {
l2OutputOracleDynamicConfig = _l2OutputOracleDynamicConfig;
dynamicConfigSet = true;
}
}
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { L2OutputOracle } from "../L1/L2OutputOracle.sol";
import { OptimismPortal } from "../L1/OptimismPortal.sol";
import { L1CrossDomainMessenger } from "../L1/L1CrossDomainMessenger.sol";
import { L1ERC721Bridge } from "../L1/L1ERC721Bridge.sol";
import { L1StandardBridge } from "../L1/L1StandardBridge.sol";
import { L1ChugSplashProxy } from "../legacy/L1ChugSplashProxy.sol";
import { AddressManager } from "../legacy/AddressManager.sol";
import { Proxy } from "../universal/Proxy.sol";
import { ProxyAdmin } from "../universal/ProxyAdmin.sol";
import { OptimismMintableERC20Factory } from "../universal/OptimismMintableERC20Factory.sol";
import { PortalSender } from "./PortalSender.sol";
import { SystemConfig } from "../L1/SystemConfig.sol";
import { BaseSystemDictator } from "./BaseSystemDictator.sol";
/**
* @title MigrationSystemDictator
* @notice The MigrationSystemDictator is responsible for coordinating the migration and
* initialization of an existing deployment of the Optimism System. We expect that all
* proxies and implementations already be deployed before this contract is used.
* @title SystemDictator
* @notice The SystemDictator is responsible for coordinating the deployment of a full Bedrock
* system. The SystemDictator is designed to support both fresh network deployments and
* upgrades to existing pre-Bedrock systems.
*/
contract MigrationSystemDictator is BaseSystemDictator {
contract SystemDictator is Ownable {
/**
* @notice Basic system configuration.
*/
struct GlobalConfig {
AddressManager addressManager;
ProxyAdmin proxyAdmin;
address controller;
address finalOwner;
}
/**
* @notice Set of proxy addresses.
*/
struct ProxyAddressConfig {
address l2OutputOracleProxy;
address optimismPortalProxy;
address l1CrossDomainMessengerProxy;
address l1StandardBridgeProxy;
address optimismMintableERC20FactoryProxy;
address l1ERC721BridgeProxy;
address systemConfigProxy;
}
/**
* @notice Set of implementation addresses.
*/
struct ImplementationAddressConfig {
L2OutputOracle l2OutputOracleImpl;
OptimismPortal optimismPortalImpl;
L1CrossDomainMessenger l1CrossDomainMessengerImpl;
L1StandardBridge l1StandardBridgeImpl;
OptimismMintableERC20Factory optimismMintableERC20FactoryImpl;
L1ERC721Bridge l1ERC721BridgeImpl;
PortalSender portalSenderImpl;
SystemConfig systemConfigImpl;
}
/**
* @notice Dynamic L2OutputOracle config.
*/
struct L2OutputOracleDynamicConfig {
uint256 l2OutputOracleStartingBlockNumber;
uint256 l2OutputOracleStartingTimestamp;
}
/**
* @notice Values for the system config contract.
*/
struct SystemConfigConfig {
address owner;
uint256 overhead;
uint256 scalar;
bytes32 batcherHash;
uint64 gasLimit;
}
/**
* @notice Combined system configuration.
*/
struct DeployConfig {
GlobalConfig globalConfig;
ProxyAddressConfig proxyAddressConfig;
ImplementationAddressConfig implementationAddressConfig;
SystemConfigConfig systemConfigConfig;
}
/**
* @notice Step after which exit 1 can no longer be used.
*/
......@@ -28,6 +98,26 @@ contract MigrationSystemDictator is BaseSystemDictator {
*/
uint8 public constant PROXY_TRANSFER_STEP = 4;
/**
* @notice System configuration.
*/
DeployConfig public config;
/**
* @notice Dynamic configuration for the L2OutputOracle.
*/
L2OutputOracleDynamicConfig public l2OutputOracleDynamicConfig;
/**
* @notice Current step;
*/
uint8 public currentStep = 1;
/**
* @notice Whether or not dynamic config has been set.
*/
bool public dynamicConfigSet;
/**
* @notice Whether or not the deployment is finalized.
*/
......@@ -38,10 +128,36 @@ contract MigrationSystemDictator is BaseSystemDictator {
*/
address public oldL1CrossDomainMessenger;
/**
* @notice Checks that the current step is the expected step, then bumps the current step.
*
* @param _step Current step.
*/
modifier step(uint8 _step) {
require(currentStep == _step, "BaseSystemDictator: incorrect step");
_;
currentStep++;
}
/**
* @param _config System configuration.
*/
constructor(DeployConfig memory _config) BaseSystemDictator(_config) {}
constructor(DeployConfig memory _config) Ownable() {
config = _config;
_transferOwnership(config.globalConfig.controller);
}
/**
* @notice Allows the owner to update dynamic L2OutputOracle config.
*
* @param _l2OutputOracleDynamicConfig Dynamic L2OutputOracle config.
*/
function updateL2OutputOracleDynamicConfig(
L2OutputOracleDynamicConfig memory _l2OutputOracleDynamicConfig
) external onlyOwner {
l2OutputOracleDynamicConfig = _l2OutputOracleDynamicConfig;
dynamicConfigSet = true;
}
/**
* @notice Configures the ProxyAdmin contract.
......@@ -150,10 +266,7 @@ contract MigrationSystemDictator is BaseSystemDictator {
*/
function step5() external onlyOwner step(5) {
// Dynamic config must be set before we can initialize the L2OutputOracle.
require(
dynamicConfigSet,
"MigrationSystemDictator: dynamic oracle config is not yet initialized"
);
require(dynamicConfigSet, "SystemDictator: dynamic oracle config is not yet initialized");
// Upgrade and initialize the L2OutputOracle.
config.globalConfig.proxyAdmin.upgradeAndCall(
......@@ -194,13 +307,10 @@ contract MigrationSystemDictator is BaseSystemDictator {
require(
keccak256(abi.encodePacked(reason)) ==
keccak256("Initializable: contract is already initialized"),
string.concat(
"MigrationSystemDictator: unexpected error initializing L1XDM: ",
reason
)
string.concat("SystemDictator: unexpected error initializing L1XDM: ", reason)
);
} catch {
revert("MigrationSystemDictator: unexpected error initializing L1XDM (no reason)");
revert("SystemDictator: unexpected error initializing L1XDM (no reason)");
}
// Transfer ETH from the L1StandardBridge to the OptimismPortal.
......@@ -295,7 +405,7 @@ contract MigrationSystemDictator is BaseSystemDictator {
function exit1() external onlyOwner {
require(
currentStep == EXIT_1_NO_RETURN_STEP,
"MigrationSystemDictator: can only exit1 before step 3 is executed"
"SystemDictator: can only exit1 before step 3 is executed"
);
// Reset the L1CrossDomainMessenger to the old implementation.
......
......@@ -49,7 +49,7 @@ const deployFn: DeployFunction = async (hre) => {
const config = await makeDictatorConfig(hre, controller, finalOwner, false)
await deployAndVerifyAndThen({
hre,
name: 'MigrationSystemDictator',
name: 'SystemDictator',
args: [config],
postDeployAction: async (contract) => {
await assertDictatorConfig(contract, config)
......@@ -57,6 +57,6 @@ const deployFn: DeployFunction = async (hre) => {
})
}
deployFn.tags = ['MigrationSystemDictator']
deployFn.tags = ['SystemDictator']
export default deployFn
......@@ -55,7 +55,7 @@ const deployFn: DeployFunction = async (hre) => {
// Set up required contract references.
const [
MigrationSystemDictator,
SystemDictator,
ProxyAdmin,
AddressManager,
L1CrossDomainMessenger,
......@@ -70,7 +70,7 @@ const deployFn: DeployFunction = async (hre) => {
L1ERC721Bridge,
] = await getContractsFromArtifacts(hre, [
{
name: 'MigrationSystemDictator',
name: 'SystemDictator',
signerOrProvider: deployer,
},
{
......@@ -127,67 +127,65 @@ const deployFn: DeployFunction = async (hre) => {
},
])
// Transfer ownership of the ProxyAdmin to the MigrationSystemDictator.
if ((await ProxyAdmin.owner()) !== MigrationSystemDictator.address) {
// Transfer ownership of the ProxyAdmin to the SystemDictator.
if ((await ProxyAdmin.owner()) !== SystemDictator.address) {
console.log(`Setting ProxyAdmin owner to MSD`)
await ProxyAdmin.transferOwnership(MigrationSystemDictator.address)
await ProxyAdmin.transferOwnership(SystemDictator.address)
} else {
console.log(`Proxy admin already owned by MSD`)
}
// We don't need to transfer proxy addresses if we're already beyond the proxy transfer step.
const needsProxyTransfer =
(await MigrationSystemDictator.currentStep()) <=
(await MigrationSystemDictator.PROXY_TRANSFER_STEP())
(await SystemDictator.currentStep()) <=
(await SystemDictator.PROXY_TRANSFER_STEP())
// Transfer ownership of the AddressManager to MigrationSystemDictator.
// Transfer ownership of the AddressManager to SystemDictator.
if (
needsProxyTransfer &&
(await AddressManager.owner()) !== MigrationSystemDictator.address
(await AddressManager.owner()) !== SystemDictator.address
) {
if (isLiveDeployer) {
console.log(`Setting AddressManager owner to MSD`)
await AddressManager.transferOwnership(MigrationSystemDictator.address)
await AddressManager.transferOwnership(SystemDictator.address)
} else {
console.log(`Please transfer AddressManager owner to MSD`)
console.log(`MSD address: ${MigrationSystemDictator.address}`)
console.log(`MSD address: ${SystemDictator.address}`)
}
// Wait for the ownership transfer to complete.
await awaitCondition(
async () => {
const owner = await AddressManager.owner()
return owner === MigrationSystemDictator.address
return owner === SystemDictator.address
},
30000,
1000
)
} else {
console.log(`AddressManager already owned by the MigrationSystemDictator`)
console.log(`AddressManager already owned by the SystemDictator`)
}
// Transfer ownership of the L1CrossDomainMessenger to MigrationSystemDictator.
// Transfer ownership of the L1CrossDomainMessenger to SystemDictator.
if (
needsProxyTransfer &&
(await AddressManager.getAddress('OVM_L1CrossDomainMessenger')) !==
ethers.constants.AddressZero &&
(await L1CrossDomainMessenger.owner()) !== MigrationSystemDictator.address
(await L1CrossDomainMessenger.owner()) !== SystemDictator.address
) {
if (isLiveDeployer) {
console.log(`Setting L1CrossDomainMessenger owner to MSD`)
await L1CrossDomainMessenger.transferOwnership(
MigrationSystemDictator.address
)
await L1CrossDomainMessenger.transferOwnership(SystemDictator.address)
} else {
console.log(`Please transfer L1CrossDomainMessenger owner to MSD`)
console.log(`MSD address: ${MigrationSystemDictator.address}`)
console.log(`MSD address: ${SystemDictator.address}`)
}
// Wait for the ownership transfer to complete.
await awaitCondition(
async () => {
const owner = await L1CrossDomainMessenger.owner()
return owner === MigrationSystemDictator.address
return owner === SystemDictator.address
},
30000,
1000
......@@ -196,21 +194,19 @@ const deployFn: DeployFunction = async (hre) => {
console.log(`L1CrossDomainMessenger already owned by MSD`)
}
// Transfer ownership of the L1StandardBridge (proxy) to MigrationSystemDictator.
// Transfer ownership of the L1StandardBridge (proxy) to SystemDictator.
if (
needsProxyTransfer &&
(await L1StandardBridgeProxy.callStatic.getOwner({
from: ethers.constants.AddressZero,
})) !== MigrationSystemDictator.address
})) !== SystemDictator.address
) {
if (isLiveDeployer) {
console.log(`Setting L1StandardBridge owner to MSD`)
await L1StandardBridgeProxyWithSigner.setOwner(
MigrationSystemDictator.address
)
await L1StandardBridgeProxyWithSigner.setOwner(SystemDictator.address)
} else {
console.log(`Please transfer L1StandardBridge (proxy) owner to MSD`)
console.log(`MSD address: ${MigrationSystemDictator.address}`)
console.log(`MSD address: ${SystemDictator.address}`)
}
// Wait for the ownership transfer to complete.
......@@ -219,7 +215,7 @@ const deployFn: DeployFunction = async (hre) => {
const owner = await L1StandardBridgeProxy.callStatic.getOwner({
from: ethers.constants.AddressZero,
})
return owner === MigrationSystemDictator.address
return owner === SystemDictator.address
},
30000,
1000
......@@ -228,21 +224,19 @@ const deployFn: DeployFunction = async (hre) => {
console.log(`L1StandardBridge already owned by MSD`)
}
// Transfer ownership of the L1ERC721Bridge (proxy) to MigrationSystemDictator.
// Transfer ownership of the L1ERC721Bridge (proxy) to SystemDictator.
if (
needsProxyTransfer &&
(await L1ERC721BridgeProxy.callStatic.admin({
from: ethers.constants.AddressZero,
})) !== MigrationSystemDictator.address
})) !== SystemDictator.address
) {
if (isLiveDeployer) {
console.log(`Setting L1ERC721Bridge owner to MSD`)
await L1ERC721BridgeProxyWithSigner.changeAdmin(
MigrationSystemDictator.address
)
await L1ERC721BridgeProxyWithSigner.changeAdmin(SystemDictator.address)
} else {
console.log(`Please transfer L1ERC721Bridge (proxy) owner to MSD`)
console.log(`MSD address: ${MigrationSystemDictator.address}`)
console.log(`MSD address: ${SystemDictator.address}`)
}
// Wait for the ownership transfer to complete.
......@@ -251,7 +245,7 @@ const deployFn: DeployFunction = async (hre) => {
const owner = await L1ERC721BridgeProxy.callStatic.admin({
from: ethers.constants.AddressZero,
})
return owner === MigrationSystemDictator.address
return owner === SystemDictator.address
},
30000,
1000
......@@ -366,7 +360,7 @@ const deployFn: DeployFunction = async (hre) => {
await assertContractVariable(
L1CrossDomainMessenger,
'owner',
MigrationSystemDictator.address
SystemDictator.address
)
// Check L1StandardBridge was initialized properly.
......@@ -399,11 +393,11 @@ const deployFn: DeployFunction = async (hre) => {
}
for (let i = 1; i <= 6; i++) {
const currentStep = await MigrationSystemDictator.currentStep()
const currentStep = await SystemDictator.currentStep()
if (currentStep === i) {
if (
currentStep > (await MigrationSystemDictator.PROXY_TRANSFER_STEP()) &&
!(await MigrationSystemDictator.dynamicConfigSet())
currentStep > (await SystemDictator.PROXY_TRANSFER_STEP()) &&
!(await SystemDictator.dynamicConfigSet())
) {
if (isLiveDeployer) {
console.log(`Updating dynamic oracle config...`)
......@@ -423,7 +417,7 @@ const deployFn: DeployFunction = async (hre) => {
deployL2StartingTimestamp = l1StartingBlock.timestamp
}
await MigrationSystemDictator.updateL2OutputOracleDynamicConfig({
await SystemDictator.updateL2OutputOracleDynamicConfig({
l2OutputOracleStartingBlockNumber:
hre.deployConfig.l2OutputOracleStartingBlockNumber,
l2OutputOracleStartingTimestamp: deployL2StartingTimestamp,
......@@ -434,7 +428,7 @@ const deployFn: DeployFunction = async (hre) => {
await awaitCondition(
async () => {
return MigrationSystemDictator.dynamicConfigSet()
return SystemDictator.dynamicConfigSet()
},
30000,
1000
......@@ -443,14 +437,14 @@ const deployFn: DeployFunction = async (hre) => {
if (isLiveDeployer) {
console.log(`Executing step ${i}...`)
await MigrationSystemDictator[`step${i}`]()
await SystemDictator[`step${i}`]()
} else {
console.log(`Please execute step ${i}...`)
}
await awaitCondition(
async () => {
const step = await MigrationSystemDictator.currentStep()
const step = await SystemDictator.currentStep()
return step === i + 1
},
30000,
......@@ -464,17 +458,17 @@ const deployFn: DeployFunction = async (hre) => {
}
}
if ((await MigrationSystemDictator.currentStep()) === 7) {
if ((await SystemDictator.currentStep()) === 7) {
if (isLiveDeployer) {
console.log(`Finalizing deployment...`)
await MigrationSystemDictator.finalize()
await SystemDictator.finalize()
} else {
console.log(`Please finalize deployment...`)
}
await awaitCondition(
async () => {
return MigrationSystemDictator.finalized()
return SystemDictator.finalized()
},
30000,
1000
......@@ -485,6 +479,6 @@ const deployFn: DeployFunction = async (hre) => {
}
}
deployFn.tags = ['MigrationSystemDictatorSteps']
deployFn.tags = ['SystemDictatorSteps']
export default deployFn
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