Commit 09e49577 authored by smartcontracts's avatar smartcontracts Committed by GitHub

feat(ctb): put dictator behind Proxy (#4206)

Puts the SystemDictator behind a standard Proxy contract. By putting the
SystemDictator behind a proxy, we can work our way out of pretty much
any error type. The owner of the proxy will be the controller as defined
in the deploy config.
parent 79a57977
// SPDX-License-Identifier: MIT
pragma solidity 0.8.15;
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import {
OwnableUpgradeable
} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import { L2OutputOracle } from "../L1/L2OutputOracle.sol";
import { OptimismPortal } from "../L1/OptimismPortal.sol";
import { L1CrossDomainMessenger } from "../L1/L1CrossDomainMessenger.sol";
......@@ -21,7 +23,7 @@ import { SystemConfig } from "../L1/SystemConfig.sol";
* system. The SystemDictator is designed to support both fresh network deployments and
* upgrades to existing pre-Bedrock systems.
*/
contract SystemDictator is Ownable {
contract SystemDictator is OwnableUpgradeable {
/**
* @notice Basic system configuration.
*/
......@@ -111,7 +113,7 @@ contract SystemDictator is Ownable {
/**
* @notice Current step;
*/
uint8 public currentStep = 1;
uint8 public currentStep;
/**
* @notice Whether or not dynamic config has been set.
......@@ -142,8 +144,10 @@ contract SystemDictator is Ownable {
/**
* @param _config System configuration.
*/
constructor(DeployConfig memory _config) Ownable() {
function initialize(DeployConfig memory _config) public initializer {
config = _config;
currentStep = 1;
__Ownable_init();
_transferOwnership(config.globalConfig.controller);
}
......
import { DeployFunction } from 'hardhat-deploy/dist/types'
import {
assertContractVariable,
deployAndVerifyAndThen,
} from '../src/deploy-utils'
const deployFn: DeployFunction = async (hre) => {
const { deployer } = await hre.getNamedAccounts()
await deployAndVerifyAndThen({
hre,
name: 'SystemDictatorProxy',
contract: 'Proxy',
args: [deployer],
postDeployAction: async (contract) => {
await assertContractVariable(contract, 'admin', deployer)
},
})
}
deployFn.tags = ['SystemDictatorProxy']
export default deployFn
import { DeployFunction } from 'hardhat-deploy/dist/types'
import '@eth-optimism/hardhat-deploy-config'
import 'hardhat-deploy'
import { deployAndVerifyAndThen } from '../src/deploy-utils'
const deployFn: DeployFunction = async (hre) => {
await deployAndVerifyAndThen({
hre,
name: 'SystemDictator',
args: [],
})
}
deployFn.tags = ['SystemDictatorImpl']
export default deployFn
import { ethers } from 'ethers'
import { DeployFunction } from 'hardhat-deploy/dist/types'
import { awaitCondition } from '@eth-optimism/core-utils'
import '@eth-optimism/hardhat-deploy-config'
import 'hardhat-deploy'
import {
deployAndVerifyAndThen,
assertDictatorConfig,
makeDictatorConfig,
getContractsFromArtifacts,
} from '../src/deploy-utils'
const deployFn: DeployFunction = async (hre) => {
......@@ -46,17 +47,91 @@ const deployFn: DeployFunction = async (hre) => {
}
}
const config = await makeDictatorConfig(hre, controller, finalOwner, false)
await deployAndVerifyAndThen({
hre,
// Load the contracts we need to interact with.
const [
SystemDictator,
SystemDictatorProxy,
SystemDictatorProxyWithSigner,
SystemDictatorImpl,
] = await getContractsFromArtifacts(hre, [
{
name: 'SystemDictatorProxy',
iface: 'SystemDictator',
signerOrProvider: deployer,
},
{
name: 'SystemDictatorProxy',
},
{
name: 'SystemDictatorProxy',
signerOrProvider: deployer,
},
{
name: 'SystemDictator',
args: [config],
postDeployAction: async (contract) => {
await assertDictatorConfig(contract, config)
signerOrProvider: deployer,
},
])
// Load the dictator configuration.
const config = await makeDictatorConfig(hre, controller, finalOwner, false)
// Update the implementation if necessary.
if (
(await SystemDictatorProxy.callStatic.implementation({
from: ethers.constants.AddressZero,
})) !== SystemDictatorImpl.address
) {
console.log('Upgrading the SystemDictator proxy...')
// Upgrade and initialize the proxy.
await SystemDictatorProxyWithSigner.upgradeToAndCall(
SystemDictatorImpl.address,
SystemDictatorImpl.interface.encodeFunctionData('initialize', [config])
)
// Wait for the transaction to execute properly.
await awaitCondition(
async () => {
return (
(await SystemDictatorProxy.callStatic.implementation({
from: ethers.constants.AddressZero,
})) === SystemDictatorImpl.address
)
},
})
30000,
1000
)
// Verify that the contract was initialized correctly.
await assertDictatorConfig(SystemDictator, config)
}
// Update the owner if necessary.
if (
(await SystemDictatorProxy.callStatic.admin({
from: ethers.constants.AddressZero,
})) !== controller
) {
console.log('Transferring ownership of the SystemDictator proxy...')
// Transfer ownership to the controller address.
await SystemDictatorProxyWithSigner.transferOwnership(controller)
// Wait for the transaction to execute properly.
await awaitCondition(
async () => {
return (
(await SystemDictatorProxy.callStatic.admin({
from: ethers.constants.AddressZero,
})) === controller
)
},
30000,
1000
)
}
}
deployFn.tags = ['SystemDictator']
deployFn.tags = ['SystemDictatorImpl']
export default deployFn
......@@ -70,7 +70,8 @@ const deployFn: DeployFunction = async (hre) => {
L1ERC721Bridge,
] = await getContractsFromArtifacts(hre, [
{
name: 'SystemDictator',
name: 'SystemDictatorProxy',
iface: 'SystemDictator',
signerOrProvider: deployer,
},
{
......
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