Commit 483ed20a authored by kf's avatar kf Committed by Kelvin Fichter

fix(contracts): various cleanup tasks in deploy process

parent 2d2aed15
...@@ -5,6 +5,7 @@ import { Lib_AddressManager } from "../resolver/Lib_AddressManager.sol"; ...@@ -5,6 +5,7 @@ import { Lib_AddressManager } from "../resolver/Lib_AddressManager.sol";
/** /**
* @title AddressDictator * @title AddressDictator
* @dev (glory to Arstotzka)
*/ */
contract AddressDictator { contract AddressDictator {
/********* /*********
......
...@@ -21,6 +21,6 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -21,6 +21,6 @@ const deployFn: DeployFunction = async (hre) => {
}) })
} }
deployFn.tags = ['upgrade', 'ChainStorageContainer_ctc_batches'] deployFn.tags = ['ChainStorageContainer_ctc_batches', 'upgrade']
export default deployFn export default deployFn
...@@ -21,6 +21,6 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -21,6 +21,6 @@ const deployFn: DeployFunction = async (hre) => {
}) })
} }
deployFn.tags = ['upgrade', 'ChainStorageContainer_scc_batches'] deployFn.tags = ['ChainStorageContainer_scc_batches', 'upgrade']
export default deployFn export default deployFn
...@@ -25,6 +25,6 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -25,6 +25,6 @@ const deployFn: DeployFunction = async (hre) => {
}) })
} }
deployFn.tags = ['upgrade', 'CanonicalTransactionChain'] deployFn.tags = ['CanonicalTransactionChain', 'upgrade']
export default deployFn export default deployFn
...@@ -24,6 +24,6 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -24,6 +24,6 @@ const deployFn: DeployFunction = async (hre) => {
}) })
} }
deployFn.tags = ['upgrade', 'StateCommitmentChain'] deployFn.tags = ['StateCommitmentChain', 'upgrade']
export default deployFn export default deployFn
...@@ -20,6 +20,6 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -20,6 +20,6 @@ const deployFn: DeployFunction = async (hre) => {
}) })
} }
deployFn.tags = ['upgrade', 'BondManager'] deployFn.tags = ['BondManager', 'upgrade']
export default deployFn export default deployFn
...@@ -39,6 +39,6 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -39,6 +39,6 @@ const deployFn: DeployFunction = async (hre) => {
}) })
} }
deployFn.tags = ['upgrade', 'L1CrossDomainMessenger'] deployFn.tags = ['L1CrossDomainMessenger', 'upgrade']
export default deployFn export default deployFn
...@@ -15,9 +15,6 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -15,9 +15,6 @@ const deployFn: DeployFunction = async (hre) => {
'Lib_AddressManager' 'Lib_AddressManager'
) )
// todo: this fails when trying to do a fresh deploy, because Lib_ResolvedDelegateProxy
// requires that the implementation has already been set in the Address Manager.
// The revert message is: 'Target address must be initialized'
await deployAndPostDeploy({ await deployAndPostDeploy({
hre, hre,
name: 'Proxy__OVM_L1CrossDomainMessenger', name: 'Proxy__OVM_L1CrossDomainMessenger',
......
...@@ -135,6 +135,6 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -135,6 +135,6 @@ const deployFn: DeployFunction = async (hre) => {
}) })
} }
deployFn.tags = ['upgrade', 'L1StandardBridge'] deployFn.tags = ['L1StandardBridge', 'upgrade']
export default deployFn export default deployFn
...@@ -64,9 +64,14 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -64,9 +64,14 @@ const deployFn: DeployFunction = async (hre) => {
// Filter out all addresses that will not change, so that the log statement is maximally // Filter out all addresses that will not change, so that the log statement is maximally
// verifiable and readable. // verifiable and readable.
namesAndAddresses = namesAndAddresses.filter(async ({ name, address }) => { const existingAddresses = {}
const existingAddress = await Lib_AddressManager.getAddress(name) for (const pair of namesAndAddresses) {
return !hexStringEquals(existingAddress, address) existingAddresses[pair.name] = await Lib_AddressManager.getAddress(
pair.name
)
}
namesAndAddresses = namesAndAddresses.filter(({ name, address }) => {
return !hexStringEquals(existingAddresses[name], address)
}) })
await deployAndPostDeploy({ await deployAndPostDeploy({
......
...@@ -11,65 +11,75 @@ import { ...@@ -11,65 +11,75 @@ import {
const deployFn: DeployFunction = async (hre) => { const deployFn: DeployFunction = async (hre) => {
const { deployer } = await hre.getNamedAccounts() const { deployer } = await hre.getNamedAccounts()
const addressDictator = await getContractFromArtifact(
// We use this task to print out the list of addresses that will be updated by the
// AddressDictator contract. The idea here is that the owner of the AddressManager will then
// review these names and addresses before transferring ownership to the AddressDictator.
// Once ownership has been transferred to the AddressDictator, we execute `setAddresses` which
// triggers a series of setAddress calls on the AddressManager and then transfers ownership back
// to the original owner.
// First get relevant contract references.
const AddressDictator = await getContractFromArtifact(
hre, hre,
'AddressDictator', 'AddressDictator',
{ {
signerOrProvider: deployer, signerOrProvider: deployer,
} }
) )
const libAddressManager = await getContractFromArtifact( const Lib_AddressManager = await getContractFromArtifact(
hre, hre,
'Lib_AddressManager' 'Lib_AddressManager'
) )
const namedAddresses = await addressDictator.getNamedAddresses() const namedAddresses: Array<{ name: string; addr: string }> =
const finalOwner = await addressDictator.finalOwner() await AddressDictator.getNamedAddresses()
let currentOwner = await libAddressManager.owner() const finalOwner = await AddressDictator.finalOwner()
const currentOwner = await Lib_AddressManager.owner()
console.log(
'\n',
'An Address Dictator contract has been deployed, with the following name/address pairs:'
)
for (const namedAddress of namedAddresses) {
// Set alignment for readability
const padding = ' '.repeat(40 - namedAddress.name.length)
console.log(`${namedAddress.name}${padding} ${namedAddress.addr}`)
}
console.log(
'\n',
'Please verify the values above, and the deployment steps up to this point,'
)
console.log(
` then transfer ownership of the Address Manager at (${libAddressManager.address})`
)
console.log(
` to the Address Dictator contract at ${addressDictator.address}.`
)
// Check if the hardhat runtime environment has the owner of the AddressManager. This will only
// happen in CI. If this is the case, we can skip directly to transferring ownership over to the
// AddressDictator contract.
const hreSigners = await hre.ethers.getSigners() const hreSigners = await hre.ethers.getSigners()
const hreSignerAddresses = hreSigners.map((signer) => { const hreHasOwner = hreSigners.some((signer) => {
return signer.address return hexStringEquals(signer.address, currentOwner)
}) })
if (
hreSignerAddresses.some((addr) => { if (hreHasOwner) {
return hexStringEquals(addr, currentOwner) // Hardhat has the owner loaded into it, we can skip directly to transferOwnership.
})
) {
console.log(
'Deploy script owns the address manager, this must be CI. Setting addresses...'
)
const owner = await hre.ethers.getSigner(currentOwner) const owner = await hre.ethers.getSigner(currentOwner)
await libAddressManager await Lib_AddressManager.connect(owner).transferOwnership(
.connect(owner) AddressDictator.address
.transferOwnership(addressDictator.address) )
} else {
console.log(`
The AddressDictator contract (glory to Arstotzka) has been deployed.
Name/Address pairs:
${namedAddresses.map((namedAddress) => {
const padding = ' '.repeat(40 - namedAddress.name.length)
return `
${namedAddress.name}${padding} ${namedAddress.addr}
`
})}
Current AddressManager owner: ${currentOwner}
Final AddressManager owner: ${finalOwner}
Please verify the values above, and the deployment steps up to this point,
then transfer ownership of the AddressManager at ${
Lib_AddressManager.address
}
to the AddressDictator contract at ${AddressDictator.address}.
`)
} }
// Wait for ownership to be transferred to the AddressDictator contract.
await waitUntilTrue( await waitUntilTrue(
async () => { async () => {
console.log('Checking ownership of Lib_AddressManager... ') return hexStringEquals(
currentOwner = await libAddressManager.owner() await Lib_AddressManager.owner(),
console.log('Lib_AddressManager owner is now set to AddressDictator.') AddressDictator.address
return hexStringEquals(currentOwner, addressDictator.address) )
}, },
{ {
// Try every 30 seconds for 500 minutes. // Try every 30 seconds for 500 minutes.
...@@ -80,22 +90,15 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -80,22 +90,15 @@ const deployFn: DeployFunction = async (hre) => {
// Set the addresses! // Set the addresses!
console.log('Ownership successfully transferred. Invoking setAddresses...') console.log('Ownership successfully transferred. Invoking setAddresses...')
await addressDictator.setAddresses() await AddressDictator.setAddresses()
await waitUntilTrue( // Make sure ownership has been correctly sent back to the original owner.
async () => { console.log('Verifying final ownership of Lib_AddressManager...')
console.log('Verifying final ownership of Lib_AddressManager') await waitUntilTrue(async () => {
currentOwner = await libAddressManager.owner() return hexStringEquals(await Lib_AddressManager.owner(), finalOwner)
return hexStringEquals(currentOwner, finalOwner) })
},
{
// Try every 10 seconds
delay: 10_000,
retries: 1000,
}
)
} }
deployFn.tags = ['upgrade', 'set-addresses'] deployFn.tags = ['set-addresses', 'upgrade']
export default deployFn export default deployFn
...@@ -11,10 +11,13 @@ import { ...@@ -11,10 +11,13 @@ import {
const deployFn: DeployFunction = async (hre) => { const deployFn: DeployFunction = async (hre) => {
const { deployer } = await hre.getNamedAccounts() const { deployer } = await hre.getNamedAccounts()
// There is a risk that on a fresh deployment we could get front-run,
// and the Proxy would be bricked. But that feels unlikely, and we can recover from it.
console.log(`Initializing Proxy__L1CrossDomainMessenger...`) console.log(`Initializing Proxy__L1CrossDomainMessenger...`)
const proxy = await getContractFromArtifact(
// There's a risk that we could get front-run during a fresh deployment, which would brick this
// contract and require that the proxy be re-deployed. We will not have this risk once we move
// entirely to chugsplash-style deployments. It's unlikely to happen and relatively easy to
// recover from so let's just ignore it for now.
const Proxy__OVM_L1CrossDomainMessenger = await getContractFromArtifact(
hre, hre,
'Proxy__OVM_L1CrossDomainMessenger', 'Proxy__OVM_L1CrossDomainMessenger',
{ {
...@@ -22,17 +25,19 @@ const deployFn: DeployFunction = async (hre) => { ...@@ -22,17 +25,19 @@ const deployFn: DeployFunction = async (hre) => {
signerOrProvider: deployer, signerOrProvider: deployer,
} }
) )
const libAddressManager = await getContractFromArtifact(
const Lib_AddressManager = await getContractFromArtifact(
hre, hre,
'Lib_AddressManager' 'Lib_AddressManager'
) )
await proxy.initialize(libAddressManager.address)
await Proxy__OVM_L1CrossDomainMessenger.initialize(Lib_AddressManager.address)
console.log(`Checking that contract was correctly initialized...`) console.log(`Checking that contract was correctly initialized...`)
await waitUntilTrue(async () => { await waitUntilTrue(async () => {
return hexStringEquals( return hexStringEquals(
await proxy.libAddressManager(), await Proxy__OVM_L1CrossDomainMessenger.libAddressManager(),
libAddressManager.address Lib_AddressManager.address
) )
}) })
} }
......
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