diff --git a/packages/contracts/deploy/001-OVM_ChainStorageContainer_ctc_batches.deploy.ts b/packages/contracts/deploy/001-OVM_ChainStorageContainer_ctc_batches.deploy.ts index 31699ed3228f981b54df847978e9482c4dd88052..c5696e98af11b9c5f62c34beb2e8dc734db7f4cc 100644 --- a/packages/contracts/deploy/001-OVM_ChainStorageContainer_ctc_batches.deploy.ts +++ b/packages/contracts/deploy/001-OVM_ChainStorageContainer_ctc_batches.deploy.ts @@ -3,17 +3,15 @@ import { DeployFunction } from 'hardhat-deploy/dist/types' /* Imports: Internal */ import { - deployAndRegister, + deployAndPostDeploy, getDeployedContract, + getLibAddressManager, } from '../src/hardhat-deploy-ethers' const deployFn: DeployFunction = async (hre) => { - const Lib_AddressManager = await getDeployedContract( - hre, - 'Lib_AddressManager' - ) + const Lib_AddressManager = await getLibAddressManager(hre) - await deployAndRegister({ + await deployAndPostDeploy({ hre, name: 'ChainStorageContainer-CTC-batches', contract: 'ChainStorageContainer', diff --git a/packages/contracts/deploy/002-OVM_ChainStorageContainer_scc_batches.deploy.ts b/packages/contracts/deploy/002-OVM_ChainStorageContainer_scc_batches.deploy.ts index 13b8a7adcbf759415fc270bea4994b3d73968615..226ccfabad97b67d8cd3523662f12a3c71ce3f17 100644 --- a/packages/contracts/deploy/002-OVM_ChainStorageContainer_scc_batches.deploy.ts +++ b/packages/contracts/deploy/002-OVM_ChainStorageContainer_scc_batches.deploy.ts @@ -3,17 +3,15 @@ import { DeployFunction } from 'hardhat-deploy/dist/types' /* Imports: Internal */ import { - deployAndRegister, + deployAndPostDeploy, getDeployedContract, + getLibAddressManager, } from '../src/hardhat-deploy-ethers' const deployFn: DeployFunction = async (hre) => { - const Lib_AddressManager = await getDeployedContract( - hre, - 'Lib_AddressManager' - ) + const Lib_AddressManager = await getLibAddressManager(hre) - await deployAndRegister({ + await deployAndPostDeploy({ hre, name: 'ChainStorageContainer-SCC-batches', contract: 'ChainStorageContainer', diff --git a/packages/contracts/deploy/003-OVM_CanonicalTransactionChain.deploy.ts b/packages/contracts/deploy/003-OVM_CanonicalTransactionChain.deploy.ts index 9891ce358e7cd62f2572e4f80f8afc1343dfd96d..2023bb42420b095b1e1529a9970ca37e3df80f99 100644 --- a/packages/contracts/deploy/003-OVM_CanonicalTransactionChain.deploy.ts +++ b/packages/contracts/deploy/003-OVM_CanonicalTransactionChain.deploy.ts @@ -3,17 +3,15 @@ import { DeployFunction } from 'hardhat-deploy/dist/types' /* Imports: Internal */ import { - deployAndRegister, + deployAndPostDeploy, getDeployedContract, + getLibAddressManager, } from '../src/hardhat-deploy-ethers' const deployFn: DeployFunction = async (hre) => { - const Lib_AddressManager = await getDeployedContract( - hre, - 'Lib_AddressManager' - ) + const Lib_AddressManager = await getLibAddressManager(hre) - await deployAndRegister({ + await deployAndPostDeploy({ hre, name: 'CanonicalTransactionChain', args: [ diff --git a/packages/contracts/deploy/004-OVM_StateCommitmentChain.deploy.ts b/packages/contracts/deploy/004-OVM_StateCommitmentChain.deploy.ts index 8b0f0b63a14cff0611af5701147a2869c4b50439..55f8c59c06c17f02a1a3ec4246e3df391f8671a8 100644 --- a/packages/contracts/deploy/004-OVM_StateCommitmentChain.deploy.ts +++ b/packages/contracts/deploy/004-OVM_StateCommitmentChain.deploy.ts @@ -3,17 +3,15 @@ import { DeployFunction } from 'hardhat-deploy/dist/types' /* Imports: Internal */ import { - deployAndRegister, + deployAndPostDeploy, getDeployedContract, + getLibAddressManager, } from '../src/hardhat-deploy-ethers' const deployFn: DeployFunction = async (hre) => { - const Lib_AddressManager = await getDeployedContract( - hre, - 'Lib_AddressManager' - ) + const Lib_AddressManager = await getLibAddressManager(hre) - await deployAndRegister({ + await deployAndPostDeploy({ hre, name: 'StateCommitmentChain', args: [ diff --git a/packages/contracts/deploy/005-OVM_BondManager.deploy.ts b/packages/contracts/deploy/005-OVM_BondManager.deploy.ts index 010d2ba0177ae359632772a5e74a68661d854a46..d535cbf5b0a414b9f9d2af6c118b739623d0e572 100644 --- a/packages/contracts/deploy/005-OVM_BondManager.deploy.ts +++ b/packages/contracts/deploy/005-OVM_BondManager.deploy.ts @@ -3,17 +3,15 @@ import { DeployFunction } from 'hardhat-deploy/dist/types' /* Imports: Internal */ import { - deployAndRegister, + deployAndPostDeploy, getDeployedContract, + getLibAddressManager, } from '../src/hardhat-deploy-ethers' const deployFn: DeployFunction = async (hre) => { - const Lib_AddressManager = await getDeployedContract( - hre, - 'Lib_AddressManager' - ) + const Lib_AddressManager = await getLibAddressManager(hre) - await deployAndRegister({ + await deployAndPostDeploy({ hre, name: 'BondManager', args: [Lib_AddressManager.address], diff --git a/packages/contracts/deploy/006-OVM_L1CrossDomainMessenger.deploy.ts b/packages/contracts/deploy/006-OVM_L1CrossDomainMessenger.deploy.ts index 80988265637e9a8651ffde87a705f718a42c8ff5..4402b159ed656481f9fcbacbe9046ac14d870d95 100644 --- a/packages/contracts/deploy/006-OVM_L1CrossDomainMessenger.deploy.ts +++ b/packages/contracts/deploy/006-OVM_L1CrossDomainMessenger.deploy.ts @@ -4,19 +4,16 @@ import { hexStringEquals } from '@eth-optimism/core-utils' /* Imports: Internal */ import { - getDeployedContract, - deployAndRegister, + deployAndPostDeploy, + getLibAddressManager, waitUntilTrue, } from '../src/hardhat-deploy-ethers' // todo: this implementation needs to also have a chugsplash proxy in front of it. const deployFn: DeployFunction = async (hre) => { - const Lib_AddressManager = await getDeployedContract( - hre, - 'Lib_AddressManager' - ) + const Lib_AddressManager = await getLibAddressManager(hre) - await deployAndRegister({ + await deployAndPostDeploy({ hre, name: 'OVM_L1CrossDomainMessenger', contract: 'L1CrossDomainMessenger', diff --git a/packages/contracts/deploy/007-Proxy__OVM_L1CrossDomainMessenger.deploy.ts b/packages/contracts/deploy/007-Proxy__OVM_L1CrossDomainMessenger.deploy.ts index cc4332b0de0e0dae29fc99547e57206b20f437e7..46f9ff6936f91cb79c7dd961e5954d9b323b682a 100644 --- a/packages/contracts/deploy/007-Proxy__OVM_L1CrossDomainMessenger.deploy.ts +++ b/packages/contracts/deploy/007-Proxy__OVM_L1CrossDomainMessenger.deploy.ts @@ -4,19 +4,16 @@ import { hexStringEquals } from '@eth-optimism/core-utils' /* Imports: Internal */ import { - getDeployedContract, - deployAndRegister, + deployAndPostDeploy, + getLibAddressManager, waitUntilTrue, } from '../src/hardhat-deploy-ethers' // We need to skip this step, because we're keeping the existing proxy. const deployFn: DeployFunction = async (hre) => { - const Lib_AddressManager = await getDeployedContract( - hre, - 'Lib_AddressManager' - ) + const Lib_AddressManager = await getLibAddressManager(hre) - await deployAndRegister({ + await deployAndPostDeploy({ hre, name: 'Proxy__OVM_L1CrossDomainMessenger', contract: 'Lib_ResolvedDelegateProxy', diff --git a/packages/contracts/deploy/008-Proxy__OVM_L1StandardBridge.deploy.ts b/packages/contracts/deploy/008-Proxy__OVM_L1StandardBridge.deploy.ts index 0fd6a5961831fb74009aa02c313ab19bd0a235ec..58451eb1085897c49e5975071be816878a32b6f1 100644 --- a/packages/contracts/deploy/008-Proxy__OVM_L1StandardBridge.deploy.ts +++ b/packages/contracts/deploy/008-Proxy__OVM_L1StandardBridge.deploy.ts @@ -2,12 +2,12 @@ import { DeployFunction } from 'hardhat-deploy/dist/types' /* Imports: Internal */ -import { deployAndRegister } from '../src/hardhat-deploy-ethers' +import { deployAndPostDeploy } from '../src/hardhat-deploy-ethers' const deployFn: DeployFunction = async (hre) => { const { deployer } = await hre.getNamedAccounts() - await deployAndRegister({ + await deployAndPostDeploy({ hre, name: 'Proxy__OVM_L1StandardBridge', contract: 'L1ChugSplashProxy', diff --git a/packages/contracts/deploy/009-OVM_L1StandardBridge.deploy.ts b/packages/contracts/deploy/009-OVM_L1StandardBridge.deploy.ts index b2d5d68766db34f81e0b8693614df9baac1593c4..4fbe6fd118c8fdcb3b5077396debea0a141271f3 100644 --- a/packages/contracts/deploy/009-OVM_L1StandardBridge.deploy.ts +++ b/packages/contracts/deploy/009-OVM_L1StandardBridge.deploy.ts @@ -11,6 +11,7 @@ import { } from '../src/contract-defs' import { getDeployedContract, + getLibAddressManager, waitUntilTrue, getAdvancedContract, deployAndRegister, @@ -18,10 +19,7 @@ import { const deployFn: DeployFunction = async (hre) => { const { deployer } = await hre.getNamedAccounts() - const Lib_AddressManager = await getDeployedContract( - hre, - 'Lib_AddressManager' - ) + const Lib_AddressManager = await getLibAddressManager(hre) // Set up a reference to the proxy as if it were the L1StandardBridge contract. const contract = await getDeployedContract( diff --git a/packages/contracts/deploy/010-AddressSetter.deploy.ts b/packages/contracts/deploy/010-AddressSetter.deploy.ts new file mode 100644 index 0000000000000000000000000000000000000000..56c8abc3f02dd70985c8757e95d008f49273c3cd --- /dev/null +++ b/packages/contracts/deploy/010-AddressSetter.deploy.ts @@ -0,0 +1,46 @@ +/* Imports: External */ +import { DeployFunction, DeploymentsExtension } from 'hardhat-deploy/dist/types' + +/* Imports: Internal */ +import { + deployAndPostDeploy, + getDeployedContract, + getLibAddressManager, +} from '../src/hardhat-deploy-ethers' + +const deployFn: DeployFunction = async (hre) => { + const Lib_AddressManager = await getLibAddressManager(hre) + + const names = [ + 'ChainStorageContainer-CTC-batches', + 'ChainStorageContainer-SCC-batches', + 'CanonicalTransactionChain', + 'StateCommitmentChain', + 'BondManager', + 'OVM_L1CrossDomainMessenger', + 'Proxy__L1CrossDomainMessenger', + 'Proxy__L1StandardBridge', + 'OVM_Proposer', + ] + + const addresses = await Promise.all( + names.map(async (n) => { + return (await getDeployedContract(hre, n)).address + }) + ) + + await deployAndPostDeploy({ + hre, + name: 'AddressSetter', + args: [ + Lib_AddressManager.address, + (hre as any).deployConfig.ovmAddressManagerOwner, + names, + addresses, + ], + }) +} + +deployFn.tags = ['AddressSetter', 'upgrade'] + +export default deployFn diff --git a/packages/contracts/deploy/010-set-addresses.ts b/packages/contracts/deploy/011-set-addresses.ts similarity index 100% rename from packages/contracts/deploy/010-set-addresses.ts rename to packages/contracts/deploy/011-set-addresses.ts diff --git a/packages/contracts/deploy/014-fund-accounts.ts b/packages/contracts/deploy/014-fund-accounts.ts new file mode 100644 index 0000000000000000000000000000000000000000..81093b9394b956c09eee1c5774c1f8c0927b88e3 --- /dev/null +++ b/packages/contracts/deploy/014-fund-accounts.ts @@ -0,0 +1,63 @@ +/* Imports: External */ +import { sleep } from '@eth-optimism/core-utils' +import { DeployFunction } from 'hardhat-deploy/dist/types' +import { + defaultHardhatNetworkHdAccountsConfigParams, + defaultHardhatNetworkParams, +} from 'hardhat/internal/core/config/default-config' +import { normalizeHardhatNetworkAccountsConfig } from 'hardhat/internal/core/providers/util' + +/* Imports: Internal */ +import { getDeployedContract } from '../src/hardhat-deploy-ethers' + +// This is a TEMPORARY way to fund the default hardhat accounts on L2. The better way to do this is +// to make a modification to hardhat-ovm. However, I don't have the time right now to figure the +// details of how to make that work cleanly. This is fine in the meantime. +const deployFn: DeployFunction = async (hre) => { + // Only execute this step if we're on the hardhat chain ID. + const { chainId } = await hre.ethers.provider.getNetwork() + if (chainId === defaultHardhatNetworkParams.chainId) { + const L1StandardBridge = await getDeployedContract( + hre, + 'Proxy__L1StandardBridge', + { + iface: 'L1StandardBridge', + } + ) + + // Default has 20 accounts but we restrict to 20 accounts manually as well just to prevent + // future problems if the number of default accounts increases for whatever reason. + const accounts = normalizeHardhatNetworkAccountsConfig( + defaultHardhatNetworkHdAccountsConfigParams + ).slice(0, 20) + + // Fund the accounts in parallel to speed things up. + await Promise.all( + accounts.map(async (account, index) => { + // Add a sleep here to avoid any potential issues with spamming hardhat. Not sure if this + // is strictly necessary but it can't hurt. + await sleep(200 * index) + + const wallet = new hre.ethers.Wallet( + account.privateKey, + hre.ethers.provider + ) + const balance = await wallet.getBalance() + const depositAmount = balance.div(2) // Deposit half of the wallet's balance into L2. + await L1StandardBridge.connect(wallet).depositETH(8_000_000, '0x', { + value: depositAmount, + gasLimit: 2_000_000, // Idk, gas estimation was broken and this fixes it. + }) + console.log( + `✓ Funded ${wallet.address} on L2 with ${hre.ethers.utils.formatEther( + depositAmount + )} ETH` + ) + }) + ) + } +} + +deployFn.tags = ['fund-accounts'] + +export default deployFn diff --git a/packages/contracts/src/hardhat-deploy-ethers.ts b/packages/contracts/src/hardhat-deploy-ethers.ts index 54241a542d395c608c67f2a225cdcaf91d98e778..92c608acac8a39c4bdf8432b35d19f8265e2bf9c 100644 --- a/packages/contracts/src/hardhat-deploy-ethers.ts +++ b/packages/contracts/src/hardhat-deploy-ethers.ts @@ -25,41 +25,7 @@ export const waitUntilTrue = async ( } } -export const registerAddress = async ({ - hre, - name, - address, -}): Promise<void> => { - // TODO: Cache these 2 across calls? - const { deployer } = await hre.getNamedAccounts() - const Lib_AddressManager = await getDeployedContract( - hre, - 'Lib_AddressManager', - { - signerOrProvider: deployer, - } - ) - - const currentAddress = await Lib_AddressManager.getAddress(name) - if (address === currentAddress) { - console.log( - `✓ Not registering address for ${name} because it's already been correctly registered` - ) - return - } - - console.log(`Registering address for ${name} to ${address}...`) - await Lib_AddressManager.setAddress(name, address) - - console.log(`Waiting for registration to reflect on-chain...`) - await waitUntilTrue(async () => { - return hexStringEquals(await Lib_AddressManager.getAddress(name), address) - }) - - console.log(`✓ Registered address for ${name}`) -} - -export const deployAndRegister = async ({ +export const deployAndPostDeploy = async ({ hre, name, args, @@ -102,12 +68,6 @@ export const deployAndRegister = async ({ }) ) } - - await registerAddress({ - hre, - name, - address: result.address, - }) } } @@ -288,3 +248,15 @@ export const getContractFromArtifact = async ( // Large balance to fund accounts with. export const BIG_BALANCE = ethers.BigNumber.from(`0xFFFFFFFFFFFFFFFFFFFF`) +export const getLibAddressManager = async (hre: any): Promise<Contract> => { + const factory = await hre.ethers.getContractFactory('Lib_AddressManager') + const iface = factory.interface + // try to get the address from the config options + const addr = (hre as any).deployConfig.libAddressManager + if (hre.ethers.utils.isAddress(addr)) { + return new Contract(addr, iface) + } else { + // if an address was not provided, a new manager must have been deployed + return getDeployedContract(hre, 'Lib_AddressManager') + } +} diff --git a/packages/contracts/tasks/deploy.ts b/packages/contracts/tasks/deploy.ts index 476d560db09cf6e2dcac2e6c8528734083ed527d..f8056d32c7ef82a586952e3d9907d1c1a1e0ec21 100644 --- a/packages/contracts/tasks/deploy.ts +++ b/packages/contracts/tasks/deploy.ts @@ -60,6 +60,12 @@ task('deploy') undefined, types.string ) + .addOptionalParam( + 'libAddressManager', + 'Address of the Lib_AddressManager, for use in a deployment which is keeping the existing contract.', + undefined, + types.string + ) .addOptionalParam( 'ovmAddressManagerOwner', 'Address that will own the Lib_AddressManager. Must be provided or this deployment will fail.', @@ -97,6 +103,24 @@ task('deploy') validateAddressArg('ovmProposerAddress') validateAddressArg('ovmAddressManagerOwner') + const hasAddressManagerTag = args.tags + .split(',') + .includes('Lib_AddressManager') + try { + validateAddressArg('libAddressManager') + if (hasAddressManagerTag) { + throw new Error( + 'cannot deploy a new Lib_AddressManager if the address of an existing one is provided' + ) + } + } catch (error) { + if (!hasAddressManagerTag) { + throw new Error( + 'must either deploy a new Lib_AddressManager, or provide the address for an existing one' + ) + } + } + hre.deployConfig = args return runSuper(args) })