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

Merge pull request #4141 from ethereum-optimism/sc/ctb-migration-fixes

fix(ctb): various migration fixes
parents 2d0601ca 7bc01454
......@@ -5,6 +5,7 @@ import { L2OutputOracle } from "../L1/L2OutputOracle.sol";
import { OptimismPortal } from "../L1/OptimismPortal.sol";
import { L1CrossDomainMessenger } from "../L1/L1CrossDomainMessenger.sol";
import { L1ChugSplashProxy } from "../legacy/L1ChugSplashProxy.sol";
import { Proxy } from "../universal/Proxy.sol";
import { ProxyAdmin } from "../universal/ProxyAdmin.sol";
import { PortalSender } from "./PortalSender.sol";
import { SystemConfig } from "../L1/SystemConfig.sol";
......@@ -137,6 +138,11 @@ contract MigrationSystemDictator is BaseSystemDictator {
L1ChugSplashProxy(payable(config.proxyAddressConfig.l1StandardBridgeProxy)).setOwner(
address(config.globalConfig.proxyAdmin)
);
// Transfer ownership of the L1ERC721Bridge to the ProxyAdmin.
Proxy(payable(config.proxyAddressConfig.l1ERC721BridgeProxy)).changeAdmin(
address(config.globalConfig.proxyAdmin)
);
}
/**
......@@ -273,6 +279,11 @@ contract MigrationSystemDictator is BaseSystemDictator {
L1ChugSplashProxy(payable(config.proxyAddressConfig.l1StandardBridgeProxy)).setOwner(
address(config.globalConfig.finalOwner)
);
// Transfer ownership of the L1ERC721Bridge to the final owner.
Proxy(payable(config.proxyAddressConfig.l1ERC721BridgeProxy)).changeAdmin(
address(config.globalConfig.finalOwner)
);
}
finalized = true;
......
......@@ -2,40 +2,34 @@
"l1ChainID": 900,
"l2ChainID": 901,
"l2BlockTime": 2,
"maxSequencerDrift": 300,
"sequencerWindowSize": 15,
"channelTimeout": 40,
"p2pSequencerAddress": "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc",
"batchInboxAddress": "0xff00000000000000000000000000000000000000",
"batchSenderAddress": "0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC",
"systemConfigOwner": "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720",
"l2OutputOracleSubmissionInterval": 20,
"l2OutputOracleStartingTimestamp": -1,
"l2OutputOracleProposer": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8",
"l2OutputOracleChallenger": "0x15d34AAf54267DB7D7c367839AAf71A00a2C6A65",
"l2GenesisBlockCoinbase": "0x42000000000000000000000000000000000000f0",
"l2GenesisBlockGasLimit": "0xE4E1C0",
"l1BlockTime": 15,
"cliqueSignerAddress": "0xca062b0fd91172d89bcd4bb084ac4e21972cc467",
"baseFeeVaultRecipient": "0xBcd4042DE499D14e55001CcbB24a551F3b954096",
"l1FeeVaultRecipient": "0x71bE63f3384f5fb98995898A86B02Fb2426c5788",
"sequencerFeeVaultRecipient": "0xfabb0ac9d68b0b445fb7357272ff202c5651694a",
"proxyAdminOwner": "0xBcd4042DE499D14e55001CcbB24a551F3b954096",
"l2CrossDomainMessengerOwner": "0xBcd4042DE499D14e55001CcbB24a551F3b954096",
"finalizationPeriodSeconds": 2,
"deploymentWaitConfirmations": 1,
"fundDevAccounts": true,
"l2GenesisBlockBaseFeePerGas": "0x3B9ACA00",
"gasPriceOracleOverhead": 2100,
"gasPriceOracleScalar": 1000000,
"eip1559Denominator": 8,
"eip1559Elasticity": 2
}
"eip1559Elasticity": 2,
"l1GenesisBlockTimestamp": "0x638a4554",
"l1StartingBlockTag": "earliest"
}
\ No newline at end of file
{
"finalSystemOwner": "0xf80267194936da1E98dB10bcE06F3147D580a62e",
"controller": "0xf80267194936da1E98dB10bcE06F3147D580a62e",
"l1StartingBlockTag": "latest",
"l1ChainID": 5,
"l2ChainID": 111,
"l2BlockTime": 2,
"maxSequencerDrift": 1000,
"sequencerWindowSize": 120,
"channelTimeout": 120,
"p2pSequencerAddress": "0x9965507D1a55bcC2695C58ba16FB37d819B0A4dc",
"batchInboxAddress": "0xff00000000000000000000000000000000000002",
"batchSenderAddress": "0xa11d2b908470e17923fff184d48269bebbd9b2a5",
"systemConfigOwner": "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720",
"l2OutputOracleSubmissionInterval": 6,
"l2OutputOracleStartingTimestamp": -1,
"l2OutputOracleProposer": "0x6c23a0dcdfc44b7a57bed148de598895e398d984",
"l2OutputOracleChallenger": "0x6925b8704ff96dee942623d6fb5e946ef5884b63",
"baseFeeVaultRecipient": "0xf116a24056b647e3211d095c667e951536cdebaa",
"l1FeeVaultRecipient": "0xc731837b696ca3d9720d23336925368ceaa58f83",
"sequencerFeeVaultRecipient": "0xf116a24056b647e3211d095c667e951536cdebaa",
"deploymentWaitConfirmations": 1
}
......@@ -3,18 +3,17 @@ import { DeployFunction } from 'hardhat-deploy/dist/types'
import {
assertContractVariable,
deployAndVerifyAndThen,
getDeploymentAddress,
} from '../src/deploy-utils'
const deployFn: DeployFunction = async (hre) => {
const proxyAdmin = await getDeploymentAddress(hre, 'ProxyAdmin')
const { deployer } = await hre.getNamedAccounts()
await deployAndVerifyAndThen({
hre,
name: 'L1ERC721BridgeProxy',
contract: 'Proxy',
args: [proxyAdmin],
args: [deployer],
postDeployAction: async (contract) => {
await assertContractVariable(contract, 'admin', proxyAdmin)
await assertContractVariable(contract, 'admin', deployer)
},
})
}
......
......@@ -65,6 +65,8 @@ const deployFn: DeployFunction = async (hre) => {
L2OutputOracle,
OptimismPortal,
OptimismMintableERC20Factory,
L1ERC721BridgeProxy,
L1ERC721BridgeProxyWithSigner,
L1ERC721Bridge,
] = await getContractsFromArtifacts(hre, [
{
......@@ -111,6 +113,13 @@ const deployFn: DeployFunction = async (hre) => {
iface: 'OptimismMintableERC20Factory',
signerOrProvider: deployer,
},
{
name: 'L1ERC721BridgeProxy',
},
{
name: 'L1ERC721BridgeProxy',
signerOrProvider: deployer,
},
{
name: 'L1ERC721BridgeProxy',
iface: 'L1ERC721Bridge',
......@@ -126,8 +135,16 @@ const deployFn: DeployFunction = async (hre) => {
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())
// Transfer ownership of the AddressManager to MigrationSystemDictator.
if ((await AddressManager.owner()) !== MigrationSystemDictator.address) {
if (
needsProxyTransfer &&
(await AddressManager.owner()) !== MigrationSystemDictator.address
) {
if (isLiveDeployer) {
console.log(`Setting AddressManager owner to MSD`)
await AddressManager.transferOwnership(MigrationSystemDictator.address)
......@@ -137,16 +154,21 @@ const deployFn: DeployFunction = async (hre) => {
}
// Wait for the ownership transfer to complete.
await awaitCondition(async () => {
const owner = await AddressManager.owner()
return owner === MigrationSystemDictator.address
})
await awaitCondition(
async () => {
const owner = await AddressManager.owner()
return owner === MigrationSystemDictator.address
},
30000,
1000
)
} else {
console.log(`AddressManager already owned by the MigrationSystemDictator`)
}
// Transfer ownership of the L1CrossDomainMessenger to MigrationSystemDictator.
if (
needsProxyTransfer &&
(await AddressManager.getAddress('OVM_L1CrossDomainMessenger')) !==
ethers.constants.AddressZero &&
(await L1CrossDomainMessenger.owner()) !== MigrationSystemDictator.address
......@@ -162,16 +184,21 @@ const deployFn: DeployFunction = async (hre) => {
}
// Wait for the ownership transfer to complete.
await awaitCondition(async () => {
const owner = await L1CrossDomainMessenger.owner()
return owner === MigrationSystemDictator.address
})
await awaitCondition(
async () => {
const owner = await L1CrossDomainMessenger.owner()
return owner === MigrationSystemDictator.address
},
30000,
1000
)
} else {
console.log(`L1CrossDomainMessenger already owned by MSD`)
}
// Transfer ownership of the L1StandardBridge (proxy) to MigrationSystemDictator.
if (
needsProxyTransfer &&
(await L1StandardBridgeProxy.callStatic.getOwner({
from: ethers.constants.AddressZero,
})) !== MigrationSystemDictator.address
......@@ -187,16 +214,52 @@ const deployFn: DeployFunction = async (hre) => {
}
// Wait for the ownership transfer to complete.
await awaitCondition(async () => {
const owner = await L1StandardBridgeProxy.callStatic.getOwner({
from: ethers.constants.AddressZero,
})
return owner === MigrationSystemDictator.address
})
await awaitCondition(
async () => {
const owner = await L1StandardBridgeProxy.callStatic.getOwner({
from: ethers.constants.AddressZero,
})
return owner === MigrationSystemDictator.address
},
30000,
1000
)
} else {
console.log(`L1StandardBridge already owned by MSD`)
}
// Transfer ownership of the L1ERC721Bridge (proxy) to MigrationSystemDictator.
if (
needsProxyTransfer &&
(await L1ERC721BridgeProxy.callStatic.admin({
from: ethers.constants.AddressZero,
})) !== MigrationSystemDictator.address
) {
if (isLiveDeployer) {
console.log(`Setting L1ERC721Bridge owner to MSD`)
await L1ERC721BridgeProxyWithSigner.changeAdmin(
MigrationSystemDictator.address
)
} else {
console.log(`Please transfer L1ERC721Bridge (proxy) owner to MSD`)
console.log(`MSD address: ${MigrationSystemDictator.address}`)
}
// Wait for the ownership transfer to complete.
await awaitCondition(
async () => {
const owner = await L1ERC721BridgeProxy.callStatic.admin({
from: ethers.constants.AddressZero,
})
return owner === MigrationSystemDictator.address
},
30000,
1000
)
} else {
console.log(`L1ERC721Bridge already owned by MSD`)
}
const checks = {
1: async () => {
await assertContractVariable(
......@@ -298,10 +361,7 @@ const deployFn: DeployFunction = async (hre) => {
await L1CrossDomainMessenger.xDomainMessageSender()
assert(false, `L1CrossDomainMessenger was not initialized properly`)
} catch (err) {
assert(
err.message.includes('xDomainMessageSender is not set'),
`L1CrossDomainMessenger was not initialized properly`
)
// Expected.
}
await assertContractVariable(
L1CrossDomainMessenger,
......@@ -371,6 +431,14 @@ const deployFn: DeployFunction = async (hre) => {
} else {
console.log(`Please update dynamic oracle config...`)
}
await awaitCondition(
async () => {
return MigrationSystemDictator.dynamicConfigSet()
},
30000,
1000
)
}
if (isLiveDeployer) {
......@@ -380,10 +448,14 @@ const deployFn: DeployFunction = async (hre) => {
console.log(`Please execute step ${i}...`)
}
await awaitCondition(async () => {
const step = await MigrationSystemDictator.currentStep()
return step === i + 1
})
await awaitCondition(
async () => {
const step = await MigrationSystemDictator.currentStep()
return step === i + 1
},
30000,
1000
)
// Run post step checks
await checks[i]()
......@@ -400,12 +472,15 @@ const deployFn: DeployFunction = async (hre) => {
console.log(`Please finalize deployment...`)
}
await awaitCondition(async () => {
return MigrationSystemDictator.finalized()
})
await awaitCondition(
async () => {
return MigrationSystemDictator.finalized()
},
30000,
1000
)
await assertContractVariable(L1CrossDomainMessenger, 'owner', finalOwner)
await assertContractVariable(ProxyAdmin, 'owner', finalOwner)
}
}
......
import { ethers } from 'ethers'
import { HardhatUserConfig } from 'hardhat/config'
import dotenv from 'dotenv'
// Hardhat plugins
import '@eth-optimism/hardhat-deploy-config'
......@@ -13,10 +14,8 @@ import './tasks'
// Deploy configuration
import { deployConfigSpec } from './src/deploy-config'
let bytecodeHash = 'none'
if (process.env.FOUNDRY_PROFILE === 'echidna') {
bytecodeHash = 'ipfs'
}
// Load environment variables
dotenv.config()
const config: HardhatUserConfig = {
networks: {
......@@ -57,6 +56,12 @@ const config: HardhatUserConfig = {
accounts: [process.env.PRIVATE_KEY_DEPLOYER || ethers.constants.HashZero],
live: false,
},
'goerli-forked': {
chainId: 5,
url: process.env.L1_RPC || '',
accounts: [process.env.PRIVATE_KEY_DEPLOYER || ethers.constants.HashZero],
live: true,
},
},
foundry: {
buildInfo: true,
......@@ -91,6 +96,10 @@ const config: HardhatUserConfig = {
'../contracts/deployments/mainnet',
'../contracts-periphery/deployments/mainnet',
],
'goerli-forked': [
'../contracts/deployments/goerli',
'../contracts-periphery/deployments/goerli',
],
},
},
solidity: {
......@@ -110,7 +119,8 @@ const config: HardhatUserConfig = {
],
settings: {
metadata: {
bytecodeHash,
bytecodeHash:
process.env.FOUNDRY_PROFILE === 'echidna' ? 'ipfs' : 'none',
},
outputSelection: {
'*': {
......
......@@ -4,6 +4,10 @@ import { ethers, Contract } from 'ethers'
import { Provider } from '@ethersproject/abstract-provider'
import { Signer } from '@ethersproject/abstract-signer'
import { sleep, getChainId } from '@eth-optimism/core-utils'
import { HardhatRuntimeEnvironment } from 'hardhat/types'
import 'hardhat-deploy'
import '@eth-optimism/hardhat-deploy-config'
import '@nomiclabs/hardhat-ethers'
export interface DictatorConfig {
globalConfig: {
......@@ -48,7 +52,7 @@ export const deployAndVerifyAndThen = async ({
iface,
postDeployAction,
}: {
hre: any
hre: HardhatRuntimeEnvironment
name: string
args: any[]
contract?: string
......@@ -58,6 +62,17 @@ export const deployAndVerifyAndThen = async ({
const { deploy } = hre.deployments
const { deployer } = await hre.getNamedAccounts()
// Hardhat deploy will usually do this check for us, but currently doesn't also consider
// external deployments when doing this check. By doing the check ourselves, we also get to
// consider external deployments. If we already have the deployment, return early.
const existing = await hre.deployments.getOrNull(name)
if (existing) {
console.log(
`skipping ${name} deployment, using existing at ${existing.address}`
)
return
}
const result = await deploy(name, {
contract,
from: deployer,
......@@ -69,38 +84,14 @@ export const deployAndVerifyAndThen = async ({
await hre.ethers.provider.waitForTransaction(result.transactionHash)
if (result.newlyDeployed) {
if (!(await isHardhatNode(hre)) && hre.network.config.live !== false) {
// Verification sometimes fails, even when the contract is correctly deployed and eventually
// verified. Possibly due to a race condition. We don't want to halt the whole deployment
// process just because that happens.
try {
console.log('Verifying on Etherscan...')
await hre.run('verify:verify', {
address: result.address,
constructorArguments: args,
})
console.log('Successfully verified on Etherscan')
} catch (error) {
console.log('Error when verifying bytecode on Etherscan:')
console.log(error)
}
try {
console.log('Verifying on Sourcify...')
await hre.run('sourcify')
console.log('Successfully verified on Sourcify')
} catch (error) {
console.log('Error when verifying bytecode on Sourcify:')
console.log(error)
}
}
if (postDeployAction) {
const signer = hre.ethers.provider.getSigner(deployer)
let abi = result.abi
if (iface !== undefined) {
const factory = await hre.ethers.getContractFactory(iface)
abi = factory.interface
abi = factory.interface as any
}
await postDeployAction(
getAdvancedContract({
hre,
......
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