From 3e2700d1718a6d17291282d60c85cb9763e4d456 Mon Sep 17 00:00:00 2001 From: Georgios Konstantopoulos Date: Mon, 12 Apr 2021 04:14:07 +0300 Subject: [PATCH] feat: hardhat-deploy (#418) * chore(hardhat-ovm): yarn lint:fix * install hardhat-deploy * refactor: move predeploys to own file * feat: enable hardhat-deploy on hardhat config * feat(contracts): add deployment steps * feat(ops): copy over any additional build files * ops: make scripts wait for more retries hardhat-deploy is slower and requires re-compiling --- .gitignore | 2 +- ops/docker/Dockerfile.deployer | 20 ++- ops/scripts/batches.sh | 4 +- ops/scripts/deployer.sh | 7 +- ops/scripts/dtl.sh | 4 +- ops/scripts/geth.sh | 4 +- ops/scripts/relayer.sh | 4 +- packages/contracts/bin/deploy.js | 114 --------------- packages/contracts/bin/deploy.ts | 76 ++++++++++ .../deploy/000-Lib_AddressManager.deploy.ts | 51 +++++++ ...hainStorageContainer_ctc_batches.deploy.ts | 27 ++++ ..._ChainStorageContainer_ctc_queue.deploy.ts | 27 ++++ ...hainStorageContainer_scc_batches.deploy.ts | 27 ++++ ...04-OVM_CanonicalTransactionChain.deploy.ts | 31 ++++ .../005-OVM_StateCommitmentChain.deploy.ts | 30 ++++ .../deploy/006-mockOVM_BondManager.deploy.ts | 35 +++++ .../007-OVM_L1CrossDomainMessenger.deploy.ts | 62 ++++++++ ...roxy__OVM_L1CrossDomainMessenger.deploy.ts | 61 ++++++++ .../deploy/009-OVM_ExecutionManager.deploy.ts | 40 ++++++ .../deploy/010-OVM_FraudVerifer.deploy.ts | 26 ++++ .../011-OVM_StateManagerFactory.deploy.ts | 17 +++ ...012-OVM_StateTransitionerFactory.deploy.ts | 26 ++++ .../deploy/013-OVM_SafetyChecker.deploy.ts | 17 +++ .../014-OVM_L1MultiMessageRelayer.deploy.ts | 26 ++++ .../deploy/015-OVM_L1ETHGateway.deploy.ts | 59 ++++++++ .../016-Proxy__OVM_L1ETHGateway.deploy.ts | 62 ++++++++ packages/contracts/deploy/017-finalize.ts | 47 +++++++ packages/contracts/hardhat.config.ts | 33 +++++ packages/contracts/package.json | 6 +- packages/contracts/src/contract-dumps.ts | 14 +- .../contracts/src/hardhat-deploy-ethers.ts | 132 ++++++++++++++++++ packages/contracts/src/predeploys.ts | 12 ++ packages/contracts/tasks/deploy.ts | 128 +++++++++++++++++ packages/hardhat-ovm/src/index.ts | 42 +++--- packages/hardhat-ovm/src/type-extensions.ts | 22 ++- yarn.lock | 86 ++++++++++-- 36 files changed, 1198 insertions(+), 183 deletions(-) delete mode 100755 packages/contracts/bin/deploy.js create mode 100755 packages/contracts/bin/deploy.ts create mode 100644 packages/contracts/deploy/000-Lib_AddressManager.deploy.ts create mode 100644 packages/contracts/deploy/001-OVM_ChainStorageContainer_ctc_batches.deploy.ts create mode 100644 packages/contracts/deploy/002-OVM_ChainStorageContainer_ctc_queue.deploy.ts create mode 100644 packages/contracts/deploy/003-OVM_ChainStorageContainer_scc_batches.deploy.ts create mode 100644 packages/contracts/deploy/004-OVM_CanonicalTransactionChain.deploy.ts create mode 100644 packages/contracts/deploy/005-OVM_StateCommitmentChain.deploy.ts create mode 100644 packages/contracts/deploy/006-mockOVM_BondManager.deploy.ts create mode 100644 packages/contracts/deploy/007-OVM_L1CrossDomainMessenger.deploy.ts create mode 100644 packages/contracts/deploy/008-Proxy__OVM_L1CrossDomainMessenger.deploy.ts create mode 100644 packages/contracts/deploy/009-OVM_ExecutionManager.deploy.ts create mode 100644 packages/contracts/deploy/010-OVM_FraudVerifer.deploy.ts create mode 100644 packages/contracts/deploy/011-OVM_StateManagerFactory.deploy.ts create mode 100644 packages/contracts/deploy/012-OVM_StateTransitionerFactory.deploy.ts create mode 100644 packages/contracts/deploy/013-OVM_SafetyChecker.deploy.ts create mode 100644 packages/contracts/deploy/014-OVM_L1MultiMessageRelayer.deploy.ts create mode 100644 packages/contracts/deploy/015-OVM_L1ETHGateway.deploy.ts create mode 100644 packages/contracts/deploy/016-Proxy__OVM_L1ETHGateway.deploy.ts create mode 100644 packages/contracts/deploy/017-finalize.ts create mode 100644 packages/contracts/src/hardhat-deploy-ethers.ts create mode 100644 packages/contracts/src/predeploys.ts create mode 100644 packages/contracts/tasks/deploy.ts diff --git a/.gitignore b/.gitignore index 256512262028..1ad7a61af530 100644 --- a/.gitignore +++ b/.gitignore @@ -11,4 +11,4 @@ cache cache-ovm l2geth/build/bin - +packages/contracts/deployments/custom diff --git a/ops/docker/Dockerfile.deployer b/ops/docker/Dockerfile.deployer index dd2580cbbe34..18db4aa4d316 100644 --- a/ops/docker/Dockerfile.deployer +++ b/ops/docker/Dockerfile.deployer @@ -13,14 +13,30 @@ COPY --from=builder /optimism/node_modules ./node_modules COPY --from=builder /optimism/packages/core-utils/package.json ./packages/core-utils/package.json COPY --from=builder /optimism/packages/core-utils/dist ./packages/core-utils/dist -# get the items +COPY --from=builder /optimism/packages/hardhat-ovm/package.json ./packages/hardhat-ovm/package.json +COPY --from=builder /optimism/packages/hardhat-ovm/dist ./packages/hardhat-ovm/dist + +# get the needed built artifacts WORKDIR /opt/optimism/packages/contracts COPY --from=builder /optimism/packages/contracts/dist ./dist COPY --from=builder /optimism/packages/contracts/bin ./bin -COPY --from=builder /optimism/packages/contracts/package.json ./ +COPY --from=builder /optimism/packages/contracts/*.json ./ COPY --from=builder /optimism/packages/contracts/node_modules ./node_modules COPY --from=builder /optimism/packages/contracts/artifacts ./artifacts COPY --from=builder /optimism/packages/contracts/artifacts-ovm ./artifacts-ovm +# copy over the cache so that hardhat-deploy does not recompile +COPY --from=builder /optimism/packages/contracts/cache ./cache +COPY --from=builder /optimism/packages/contracts/cache-ovm ./cache-ovm + +# get the files for hardhat-deploy +COPY --from=builder /optimism/packages/contracts/contracts ./contracts +COPY --from=builder /optimism/packages/contracts/hardhat.config.ts ./ +COPY --from=builder /optimism/packages/contracts/deploy ./deploy +COPY --from=builder /optimism/packages/contracts/tasks ./tasks +COPY --from=builder /optimism/packages/contracts/src ./src +COPY --from=builder /optimism/packages/contracts/test/helpers/constants.ts ./test/helpers/constants.ts +COPY --from=builder /optimism/packages/contracts/scripts ./scripts + COPY ./ops/scripts/deployer.sh . ENTRYPOINT yarn run deploy diff --git a/ops/scripts/batches.sh b/ops/scripts/batches.sh index 50b52a2bbaf2..bfd5828eb7b5 100755 --- a/ops/scripts/batches.sh +++ b/ops/scripts/batches.sh @@ -1,8 +1,8 @@ #!/bin/bash -RETRIES=${RETRIES:-20} +RETRIES=${RETRIES:-40} # get the addrs from the URL provided -ADDRESSES=$(curl --retry-connrefused --retry $RETRIES --retry-delay 3 $URL) +ADDRESSES=$(curl --retry-connrefused --retry $RETRIES --retry-delay 5 $URL) # set the env export ADDRESS_MANAGER_ADDRESS=$(echo $ADDRESSES | jq -r '.AddressManager') diff --git a/ops/scripts/deployer.sh b/ops/scripts/deployer.sh index 343feba49705..ca06abf24aec 100755 --- a/ops/scripts/deployer.sh +++ b/ops/scripts/deployer.sh @@ -5,9 +5,8 @@ JSON='{"jsonrpc":"2.0","id":0,"method":"net_version","params":[]}' # wait for the base layer to be up curl -H "Content-Type: application/json" --retry-connrefused --retry $RETRIES --retry-delay 1 -d $JSON $L1_NODE_WEB3_URL -# get the addrs to a var -ADDRESSES=$(yarn run --silent deploy) -# sent them to the file -echo $ADDRESSES > dist/dumps/addresses.json + +yarn run deploy + # serve the addrs and the state dump ./bin/serve_dump.sh diff --git a/ops/scripts/dtl.sh b/ops/scripts/dtl.sh index e40d54b8607d..644f00cb450b 100755 --- a/ops/scripts/dtl.sh +++ b/ops/scripts/dtl.sh @@ -1,8 +1,8 @@ #!/bin/bash -RETRIES=${RETRIES:-20} +RETRIES=${RETRIES:-40} # get the addrs from the URL provided -ADDRESSES=$(curl --retry-connrefused --retry $RETRIES --retry-delay 2 $URL) +ADDRESSES=$(curl --retry-connrefused --retry $RETRIES --retry-delay 5 $URL) # set the env export DATA_TRANSPORT_LAYER__ADDRESS_MANAGER=$(echo $ADDRESSES | jq -r '.AddressManager') diff --git a/ops/scripts/geth.sh b/ops/scripts/geth.sh index efd3736f9e0c..9a2fdbf2c34e 100755 --- a/ops/scripts/geth.sh +++ b/ops/scripts/geth.sh @@ -1,7 +1,7 @@ #!/bin/bash -RETRIES=${RETRIES:-20} +RETRIES=${RETRIES:-40} # get the addrs from the URL provided -ADDRESSES=$(curl --retry-connrefused --retry $RETRIES --retry-delay 1 $URL) +ADDRESSES=$(curl --retry-connrefused --retry $RETRIES --retry-delay 5 $URL) function envSet() { VAR=$1 diff --git a/ops/scripts/relayer.sh b/ops/scripts/relayer.sh index d247f469a1ba..9a1caecd6d02 100755 --- a/ops/scripts/relayer.sh +++ b/ops/scripts/relayer.sh @@ -1,8 +1,8 @@ #!/bin/bash -RETRIES=${RETRIES:-20} +RETRIES=${RETRIES:-40} # get the addrs from the URL provided -ADDRESSES=$(curl --retry-connrefused --retry $RETRIES --retry-delay 3 $URL) +ADDRESSES=$(curl --retry-connrefused --retry $RETRIES --retry-delay 5 $URL) # set the env export ADDRESS_MANAGER_ADDRESS=$(echo $ADDRESSES | jq -r '.AddressManager') diff --git a/packages/contracts/bin/deploy.js b/packages/contracts/bin/deploy.js deleted file mode 100755 index 4bee2df25d6c..000000000000 --- a/packages/contracts/bin/deploy.js +++ /dev/null @@ -1,114 +0,0 @@ -#!/usr/bin/env node - -const contracts = require('../dist/contract-deployment/deploy'); -const { providers, Wallet, utils, ethers } = require('ethers'); -const { JsonRpcProvider } = providers; -const fs = require('fs') - -const env = process.env; -const key = env.DEPLOYER_PRIVATE_KEY; -const sequencerKey = env.SEQUENCER_PRIVATE_KEY; -let SEQUENCER_ADDRESS = env.SEQUENCER_ADDRESS; -const web3Url = env.L1_NODE_WEB3_URL || 'http://127.0.0.1:8545'; -const DEPLOY_TX_GAS_LIMIT = env.DEPLOY_TX_GAS_LIMIT || 5000000; -const MIN_TRANSACTION_GAS_LIMIT = env.MIN_TRANSACTION_GAS_LIMIT || 50000; -const MAX_TRANSACTION_GAS_LIMIT = env.MAX_TRANSACTION_GAS_LIMIT || 9000000; -const MAX_GAS_PER_QUEUE_PER_EPOCH = env.MAX_GAS_PER_QUEUE_PER_EPOCH || 250000000; -const SECONDS_PER_EPOCH = env.SECONDS_PER_EPOCH || 0; -const WAIT_FOR_RECEIPTS = env.WAIT_FOR_RECEIPTS === 'true'; -let WHITELIST_OWNER = env.WHITELIST_OWNER; -const WHITELIST_ALLOW_ARBITRARY_CONTRACT_DEPLOYMENT = env.WHITELIST_ALLOW_ARBITRARY_CONTRACT_DEPLOYMENT || true; -const FORCE_INCLUSION_PERIOD_SECONDS = env.FORCE_INCLUSION_PERIOD_SECONDS || 2592000; // 30 days -const FRAUD_PROOF_WINDOW_SECONDS = env.FRAUD_PROOF_WINDOW_SECONDS || (60 * 60 * 24 * 7); // 7 days -const SEQUENCER_PUBLISH_WINDOW_SECONDS = env.SEQUENCER_PUBLISH_WINDOW_SECONDS || (60 * 30); // 30 min -const CHAIN_ID = env.CHAIN_ID || 420; // layer 2 chainid -const ADDRESS_MANAGER_ADDRESS = env.ADDRESS_MANAGER_ADDRESS || undefined; -const BLOCK_TIME_SECONDS = env.BLOCK_TIME_SECONDS || 15; -const L2_CROSS_DOMAIN_MESSENGER_ADDRESS = - env.L2_CROSS_DOMAIN_MESSENGER_ADDRESS || '0x4200000000000000000000000000000000000007'; -let RELAYER_ADDRESS = env.RELAYER_ADDRESS || '0x0000000000000000000000000000000000000000'; -const RELAYER_PRIVATE_KEY = env.RELAYER_PRIVATE_KEY; - -(async () => { - const provider = new JsonRpcProvider(web3Url); - if (typeof key === 'undefined') { - throw new Error('Must pass deployer key as DEPLOYER_PRIVATE_KEY'); - } - const signer = new Wallet(key, provider); - - if (SEQUENCER_ADDRESS) { - if (!utils.isAddress(SEQUENCER_ADDRESS)) - throw new Error(`Invalid Sequencer Address: ${SEQUENCER_ADDRESS}`); - } else { - if (!sequencerKey) - throw new Error('Must pass sequencer key as SEQUENCER_PRIVATE_KEY'); - const sequencer = new Wallet(sequencerKey, provider); - SEQUENCER_ADDRESS = await sequencer.getAddress(); - } - - if (typeof WHITELIST_OWNER === 'undefined') - WHITELIST_OWNER = signer; - - // Use the address derived from RELAYER_PRIVATE_KEY if a private key - // is passed. Using the zero address as the relayer address will mean - // there is no relayer authentication. - if (RELAYER_PRIVATE_KEY) { - if (!utils.isAddress(RELAYER_ADDRESS)) - throw new Error(`Invalid Relayer Address: ${RELAYER_ADDRESS}`); - const relayer = new Wallet(RELAYER_PRIVATE_KEY, provider); - RELAYER_ADDRESS = await relayer.getAddress(); - } - - const result = await contracts.deploy({ - deploymentSigner: signer, - transactionChainConfig: { - forceInclusionPeriodSeconds: FORCE_INCLUSION_PERIOD_SECONDS, - sequencer: SEQUENCER_ADDRESS, - forceInclusionPeriodBlocks: Math.ceil(FORCE_INCLUSION_PERIOD_SECONDS/BLOCK_TIME_SECONDS), - }, - stateChainConfig: { - fraudProofWindowSeconds: FRAUD_PROOF_WINDOW_SECONDS, - sequencerPublishWindowSeconds: SEQUENCER_PUBLISH_WINDOW_SECONDS, - }, - ovmGlobalContext: { - ovmCHAINID: CHAIN_ID, - L2CrossDomainMessengerAddress: L2_CROSS_DOMAIN_MESSENGER_ADDRESS - }, - l1CrossDomainMessengerConfig: { - relayerAddress: RELAYER_ADDRESS, - }, - ovmGasMeteringConfig: { - minTransactionGasLimit: MIN_TRANSACTION_GAS_LIMIT, - maxTransactionGasLimit: MAX_TRANSACTION_GAS_LIMIT, - maxGasPerQueuePerEpoch: MAX_GAS_PER_QUEUE_PER_EPOCH, - secondsPerEpoch: SECONDS_PER_EPOCH - }, - whitelistConfig: { - owner: WHITELIST_OWNER, - allowArbitraryContractDeployment: WHITELIST_ALLOW_ARBITRARY_CONTRACT_DEPLOYMENT - }, - deployOverrides: { - gasLimit: DEPLOY_TX_GAS_LIMIT - }, - waitForReceipts: WAIT_FOR_RECEIPTS, - addressManager: ADDRESS_MANAGER_ADDRESS, - }); - - const { failedDeployments, AddressManager } = result; - if (failedDeployments.length !== 0) - throw new Error(`Contract deployment failed: ${failedDeployments.join(',')}`); - - const out = {}; - out.AddressManager = AddressManager.address; - out.OVM_Sequencer = SEQUENCER_ADDRESS; - out.Deployer = await signer.getAddress() - for (const [name, contract] of Object.entries(result.contracts)) { - out[name] = contract.address; - } - const addresses = JSON.stringify(out, null, 2) - fs.writeFileSync(__dirname + "/addresses.json", addresses) - console.log(JSON.stringify(out, null, 2)); -})().catch(err => { - console.log(JSON.stringify({error: err.message, stack: err.stack}, null, 2)); - process.exit(1); -}); diff --git a/packages/contracts/bin/deploy.ts b/packages/contracts/bin/deploy.ts new file mode 100755 index 000000000000..d3375caa6507 --- /dev/null +++ b/packages/contracts/bin/deploy.ts @@ -0,0 +1,76 @@ +#!/usr/bin/env ts-node-script + +import { Wallet } from 'ethers' +import path from 'path' +import dirtree from 'directory-tree' +import fs from 'fs' + +// Ensures that all relevant environment vars are properly set. These lines *must* come before the +// hardhat import because importing will load the config (which relies on these vars). Necessary +// because CI currently uses different var names than the ones we've chosen here. +// TODO: Update CI so that we don't have to do this anymore. +process.env.HARDHAT_NETWORK = 'custom' // "custom" here is an arbitrary name. only used for CI. +process.env.CONTRACTS_TARGET_NETWORK = 'custom' +process.env.CONTRACTS_DEPLOYER_KEY = process.env.DEPLOYER_PRIVATE_KEY +process.env.CONTRACTS_RPC_URL = + process.env.L1_NODE_WEB3_URL || 'http://127.0.0.1:8545' + +import hre from 'hardhat' + +const main = async () => { + const sequencer = new Wallet(process.env.SEQUENCER_PRIVATE_KEY) + const deployer = new Wallet(process.env.DEPLOYER_PRIVATE_KEY) + + await hre.run('deploy', { + l1BlockTimeSeconds: process.env.BLOCK_TIME_SECONDS, + ctcForceInclusionPeriodSeconds: process.env.FORCE_INCLUSION_PERIOD_SECONDS, + ctcMaxTransactionGasLimit: process.env.MAX_TRANSACTION_GAS_LIMIT, + emMinTransactionGasLimit: process.env.MIN_TRANSACTION_GAS_LIMIT, + emMaxtransactionGasLimit: process.env.MAX_TRANSACTION_GAS_LIMIT, + emMaxGasPerQueuePerEpoch: process.env.MAX_GAS_PER_QUEUE_PER_EPOCH, + emSecondsPerEpoch: process.env.SECONDS_PER_EPOCH, + emOvmChainId: process.env.CHAIN_ID, + sccFraudProofWindow: parseInt(process.env.FRAUD_PROOF_WINDOW_SECONDS, 10), + sccSequencerPublishWindow: process.env.SEQUENCER_PUBLISH_WINDOW_SECONDS, + ovmSequencerAddress: sequencer.address, + ovmProposerAddress: sequencer.address, + ovmRelayerAddress: sequencer.address, + ovmAddressManagerOwner: deployer.address, + }) + + // Stuff below this line is currently required for CI to work properly. We probably want to + // update our CI so this is no longer necessary. But I'm adding it for backwards compat so we can + // get the hardhat-deploy stuff merged. Woot. + const nicknames = { + 'Lib_AddressManager': 'AddressManager', + 'mockOVM_BondManager': 'OVM_BondManager' + } + + const contracts = dirtree( + path.resolve(__dirname, `../deployments/custom`) + ).children.filter((child) => { + return child.extension === '.json' + }).reduce((contracts, child) => { + const contractName = child.name.replace('.json', '') + const artifact = require(path.resolve(__dirname, `../deployments/custom/${child.name}`)) + contracts[nicknames[contractName] || contractName] = artifact.address + return contracts + }, {}) + + const addresses = JSON.stringify(contracts, null, 2) + const dumpsPath = path.resolve(__dirname, "../dist/dumps") + if (!fs.existsSync(dumpsPath)) { + fs.mkdirSync(dumpsPath) + } + const addrsPath = path.resolve(dumpsPath, 'addresses.json') + fs.writeFileSync(addrsPath, addresses) +} + +main() + .then(() => process.exit(0)) + .catch((error) => { + console.log( + JSON.stringify({ error: error.message, stack: error.stack }, null, 2) + ) + process.exit(1) + }) diff --git a/packages/contracts/deploy/000-Lib_AddressManager.deploy.ts b/packages/contracts/deploy/000-Lib_AddressManager.deploy.ts new file mode 100644 index 000000000000..620e9f1aa05d --- /dev/null +++ b/packages/contracts/deploy/000-Lib_AddressManager.deploy.ts @@ -0,0 +1,51 @@ +/* Imports: External */ +import { DeployFunction } from 'hardhat-deploy/dist/types' + +/* Imports: Internal */ +import { registerAddress } from '../src/hardhat-deploy-ethers' +import { predeploys } from '../src/predeploys' + +const deployFn: DeployFunction = async (hre) => { + const { deploy } = hre.deployments + const { deployer } = await hre.getNamedAccounts() + + await deploy('Lib_AddressManager', { + from: deployer, + args: [], + log: true, + }) + + await registerAddress({ + hre, + name: 'OVM_L2CrossDomainMessenger', + address: predeploys.OVM_L2CrossDomainMessenger, + }) + + await registerAddress({ + hre, + name: 'OVM_DecompressionPrecompileAddress', + address: predeploys.OVM_SequencerEntrypoint, + }) + + await registerAddress({ + hre, + name: 'OVM_Sequencer', + address: (hre as any).deployConfig.ovmSequencerAddress, + }) + + await registerAddress({ + hre, + name: 'OVM_Proposer', + address: (hre as any).deployConfig.ovmProposerAddress, + }) + + await registerAddress({ + hre, + name: 'OVM_L2BatchMessageRelayer', + address: (hre as any).deployConfig.ovmRelayerAddress, + }) +} + +deployFn.tags = ['Lib_AddressManager', 'required'] + +export default deployFn diff --git a/packages/contracts/deploy/001-OVM_ChainStorageContainer_ctc_batches.deploy.ts b/packages/contracts/deploy/001-OVM_ChainStorageContainer_ctc_batches.deploy.ts new file mode 100644 index 000000000000..95f88e754dc7 --- /dev/null +++ b/packages/contracts/deploy/001-OVM_ChainStorageContainer_ctc_batches.deploy.ts @@ -0,0 +1,27 @@ +/* Imports: External */ +import { DeployFunction } from 'hardhat-deploy/dist/types' + +/* Imports: Internal */ +import { + deployAndRegister, + getDeployedContract, +} from '../src/hardhat-deploy-ethers' + +const deployFn: DeployFunction = async (hre) => { + const Lib_AddressManager = await getDeployedContract( + hre, + 'Lib_AddressManager' + ) + + await deployAndRegister({ + hre, + name: 'OVM_ChainStorageContainer:CTC:batches', + contract: 'OVM_ChainStorageContainer', + args: [Lib_AddressManager.address, 'OVM_CanonicalTransactionChain'], + }) +} + +deployFn.dependencies = ['Lib_AddressManager'] +deployFn.tags = ['OVM_ChainStorageContainer_ctc_batches'] + +export default deployFn diff --git a/packages/contracts/deploy/002-OVM_ChainStorageContainer_ctc_queue.deploy.ts b/packages/contracts/deploy/002-OVM_ChainStorageContainer_ctc_queue.deploy.ts new file mode 100644 index 000000000000..02dd9918f00a --- /dev/null +++ b/packages/contracts/deploy/002-OVM_ChainStorageContainer_ctc_queue.deploy.ts @@ -0,0 +1,27 @@ +/* Imports: External */ +import { DeployFunction } from 'hardhat-deploy/dist/types' + +/* Imports: Internal */ +import { + deployAndRegister, + getDeployedContract, +} from '../src/hardhat-deploy-ethers' + +const deployFn: DeployFunction = async (hre) => { + const Lib_AddressManager = await getDeployedContract( + hre, + 'Lib_AddressManager' + ) + + await deployAndRegister({ + hre, + name: 'OVM_ChainStorageContainer:CTC:queue', + contract: 'OVM_ChainStorageContainer', + args: [Lib_AddressManager.address, 'OVM_CanonicalTransactionChain'], + }) +} + +deployFn.dependencies = ['Lib_AddressManager'] +deployFn.tags = ['OVM_ChainStorageContainer_ctc_queue'] + +export default deployFn diff --git a/packages/contracts/deploy/003-OVM_ChainStorageContainer_scc_batches.deploy.ts b/packages/contracts/deploy/003-OVM_ChainStorageContainer_scc_batches.deploy.ts new file mode 100644 index 000000000000..a3123ae62a5d --- /dev/null +++ b/packages/contracts/deploy/003-OVM_ChainStorageContainer_scc_batches.deploy.ts @@ -0,0 +1,27 @@ +/* Imports: External */ +import { DeployFunction } from 'hardhat-deploy/dist/types' + +/* Imports: Internal */ +import { + deployAndRegister, + getDeployedContract, +} from '../src/hardhat-deploy-ethers' + +const deployFn: DeployFunction = async (hre) => { + const Lib_AddressManager = await getDeployedContract( + hre, + 'Lib_AddressManager' + ) + + await deployAndRegister({ + hre, + name: 'OVM_ChainStorageContainer:SCC:batches', + contract: 'OVM_ChainStorageContainer', + args: [Lib_AddressManager.address, 'OVM_StateCommitmentChain'], + }) +} + +deployFn.dependencies = ['Lib_AddressManager'] +deployFn.tags = ['OVM_ChainStorageContainer_scc_batches'] + +export default deployFn diff --git a/packages/contracts/deploy/004-OVM_CanonicalTransactionChain.deploy.ts b/packages/contracts/deploy/004-OVM_CanonicalTransactionChain.deploy.ts new file mode 100644 index 000000000000..a663f4398aad --- /dev/null +++ b/packages/contracts/deploy/004-OVM_CanonicalTransactionChain.deploy.ts @@ -0,0 +1,31 @@ +/* Imports: External */ +import { DeployFunction } from 'hardhat-deploy/dist/types' + +/* Imports: Internal */ +import { + deployAndRegister, + getDeployedContract, +} from '../src/hardhat-deploy-ethers' + +const deployFn: DeployFunction = async (hre) => { + const Lib_AddressManager = await getDeployedContract( + hre, + 'Lib_AddressManager' + ) + + await deployAndRegister({ + hre, + name: 'OVM_CanonicalTransactionChain', + args: [ + Lib_AddressManager.address, + (hre as any).deployConfig.ctcForceInclusionPeriodSeconds, + (hre as any).deployConfig.ctcForceInclusionPeriodBlocks, + (hre as any).deployConfig.ctcMaxTransactionGasLimit, + ], + }) +} + +deployFn.dependencies = ['Lib_AddressManager'] +deployFn.tags = ['OVM_CanonicalTransactionChain'] + +export default deployFn diff --git a/packages/contracts/deploy/005-OVM_StateCommitmentChain.deploy.ts b/packages/contracts/deploy/005-OVM_StateCommitmentChain.deploy.ts new file mode 100644 index 000000000000..f84c41ea9942 --- /dev/null +++ b/packages/contracts/deploy/005-OVM_StateCommitmentChain.deploy.ts @@ -0,0 +1,30 @@ +/* Imports: External */ +import { DeployFunction } from 'hardhat-deploy/dist/types' + +/* Imports: Internal */ +import { + deployAndRegister, + getDeployedContract, +} from '../src/hardhat-deploy-ethers' + +const deployFn: DeployFunction = async (hre) => { + const Lib_AddressManager = await getDeployedContract( + hre, + 'Lib_AddressManager' + ) + + await deployAndRegister({ + hre, + name: 'OVM_StateCommitmentChain', + args: [ + Lib_AddressManager.address, + (hre as any).deployConfig.sccFraudProofWindow, + (hre as any).deployConfig.sccSequencerPublishWindow, + ], + }) +} + +deployFn.dependencies = ['Lib_AddressManager'] +deployFn.tags = ['OVM_StateCommitmentChain'] + +export default deployFn diff --git a/packages/contracts/deploy/006-mockOVM_BondManager.deploy.ts b/packages/contracts/deploy/006-mockOVM_BondManager.deploy.ts new file mode 100644 index 000000000000..f584f5589299 --- /dev/null +++ b/packages/contracts/deploy/006-mockOVM_BondManager.deploy.ts @@ -0,0 +1,35 @@ +/* Imports: External */ +import { DeployFunction } from 'hardhat-deploy/dist/types' + +/* Imports: Internal */ +import { getDeployedContract } from '../src/hardhat-deploy-ethers' + +const deployFn: DeployFunction = async (hre) => { + const { deploy } = hre.deployments + const { deployer } = await hre.getNamedAccounts() + + const Lib_AddressManager = await getDeployedContract( + hre, + 'Lib_AddressManager', + { + signerOrProvider: deployer, + } + ) + + const result = await deploy('mockOVM_BondManager', { + from: deployer, + args: [Lib_AddressManager.address], + log: true, + }) + + if (!result.newlyDeployed) { + return + } + + await Lib_AddressManager.setAddress('OVM_BondManager', result.address) +} + +deployFn.dependencies = ['Lib_AddressManager'] +deployFn.tags = ['mockOVM_BondManager'] + +export default deployFn diff --git a/packages/contracts/deploy/007-OVM_L1CrossDomainMessenger.deploy.ts b/packages/contracts/deploy/007-OVM_L1CrossDomainMessenger.deploy.ts new file mode 100644 index 000000000000..5ab6678dc22b --- /dev/null +++ b/packages/contracts/deploy/007-OVM_L1CrossDomainMessenger.deploy.ts @@ -0,0 +1,62 @@ +/* Imports: External */ +import { DeployFunction } from 'hardhat-deploy/dist/types' + +/* Imports: Internal */ +import { getDeployedContract } from '../src/hardhat-deploy-ethers' + +const deployFn: DeployFunction = async (hre) => { + const { deploy } = hre.deployments + const { deployer } = await hre.getNamedAccounts() + + const Lib_AddressManager = await getDeployedContract( + hre, + 'Lib_AddressManager', + { + signerOrProvider: deployer, + } + ) + + const result = await deploy('OVM_L1CrossDomainMessenger', { + from: deployer, + args: [], + log: true, + }) + + if (!result.newlyDeployed) { + return + } + + const OVM_L1CrossDomainMessenger = await getDeployedContract( + hre, + 'OVM_L1CrossDomainMessenger', + { + signerOrProvider: deployer, + } + ) + + // NOTE: this initialization is *not* technically required (we only need to initialize the proxy) + // but it feels safer to initialize this anyway. Otherwise someone else could come along and + // initialize this. + await OVM_L1CrossDomainMessenger.initialize(Lib_AddressManager.address) + + const libAddressManager = await OVM_L1CrossDomainMessenger.libAddressManager() + if (libAddressManager !== Lib_AddressManager.address) { + throw new Error( + `\n**FATAL ERROR. THIS SHOULD NEVER HAPPEN. CHECK YOUR DEPLOYMENT.**:\n` + + `OVM_L1CrossDomainMessenger could not be succesfully initialized.\n` + + `Attempted to set Lib_AddressManager to: ${Lib_AddressManager.address}\n` + + `Actual address after initialization: ${libAddressManager}\n` + + `This could indicate a compromised deployment.` + ) + } + + await Lib_AddressManager.setAddress( + 'OVM_L1CrossDomainMessenger', + result.address + ) +} + +deployFn.dependencies = ['Lib_AddressManager'] +deployFn.tags = ['OVM_L1CrossDomainMessenger'] + +export default deployFn diff --git a/packages/contracts/deploy/008-Proxy__OVM_L1CrossDomainMessenger.deploy.ts b/packages/contracts/deploy/008-Proxy__OVM_L1CrossDomainMessenger.deploy.ts new file mode 100644 index 000000000000..51a02a75e326 --- /dev/null +++ b/packages/contracts/deploy/008-Proxy__OVM_L1CrossDomainMessenger.deploy.ts @@ -0,0 +1,61 @@ +/* Imports: External */ +import { DeployFunction } from 'hardhat-deploy/dist/types' + +/* Imports: Internal */ +import { getDeployedContract } from '../src/hardhat-deploy-ethers' + +const deployFn: DeployFunction = async (hre) => { + const { deploy } = hre.deployments + const { deployer } = await hre.getNamedAccounts() + + const Lib_AddressManager = await getDeployedContract( + hre, + 'Lib_AddressManager', + { + signerOrProvider: deployer, + } + ) + + const result = await deploy('Proxy__OVM_L1CrossDomainMessenger', { + contract: 'Lib_ResolvedDelegateProxy', + from: deployer, + args: [Lib_AddressManager.address, 'OVM_L1CrossDomainMessenger'], + log: true, + }) + + if (!result.newlyDeployed) { + return + } + + const Proxy__OVM_L1CrossDomainMessenger = await getDeployedContract( + hre, + 'Proxy__OVM_L1CrossDomainMessenger', + { + signerOrProvider: deployer, + iface: 'OVM_L1CrossDomainMessenger', + } + ) + + await Proxy__OVM_L1CrossDomainMessenger.initialize(Lib_AddressManager.address) + + const libAddressManager = await Proxy__OVM_L1CrossDomainMessenger.libAddressManager() + if (libAddressManager !== Lib_AddressManager.address) { + throw new Error( + `\n**FATAL ERROR. THIS SHOULD NEVER HAPPEN. CHECK YOUR DEPLOYMENT.**:\n` + + `Proxy__OVM_L1CrossDomainMessenger could not be succesfully initialized.\n` + + `Attempted to set Lib_AddressManager to: ${Lib_AddressManager.address}\n` + + `Actual address after initialization: ${libAddressManager}\n` + + `This could indicate a compromised deployment.` + ) + } + + await Lib_AddressManager.setAddress( + 'Proxy__OVM_L1CrossDomainMessenger', + result.address + ) +} + +deployFn.dependencies = ['Lib_AddressManager', 'OVM_L1CrossDomainMessenger'] +deployFn.tags = ['Proxy__OVM_L1CrossDomainMessenger'] + +export default deployFn diff --git a/packages/contracts/deploy/009-OVM_ExecutionManager.deploy.ts b/packages/contracts/deploy/009-OVM_ExecutionManager.deploy.ts new file mode 100644 index 000000000000..c1e62aeb3c86 --- /dev/null +++ b/packages/contracts/deploy/009-OVM_ExecutionManager.deploy.ts @@ -0,0 +1,40 @@ +/* Imports: External */ +import { DeployFunction } from 'hardhat-deploy/dist/types' + +/* Imports: Internal */ +import { + deployAndRegister, + getDeployedContract, +} from '../src/hardhat-deploy-ethers' + +const deployFn: DeployFunction = async (hre) => { + const Lib_AddressManager = await getDeployedContract( + hre, + 'Lib_AddressManager' + ) + + await deployAndRegister({ + hre, + name: 'OVM_ExecutionManager', + args: [ + Lib_AddressManager.address, + { + minTransactionGasLimit: (hre as any).deployConfig + .emMinTransactionGasLimit, + maxTransactionGasLimit: (hre as any).deployConfig + .emMaxTransactionGasLimit, + maxGasPerQueuePerEpoch: (hre as any).deployConfig + .emMaxGasPerQueuePerEpoch, + secondsPerEpoch: (hre as any).deployConfig.emSecondsPerEpoch, + }, + { + ovmCHAINID: (hre as any).deployConfig.emOvmChainId, + }, + ], + }) +} + +deployFn.dependencies = ['Lib_AddressManager'] +deployFn.tags = ['OVM_ExecutionManager'] + +export default deployFn diff --git a/packages/contracts/deploy/010-OVM_FraudVerifer.deploy.ts b/packages/contracts/deploy/010-OVM_FraudVerifer.deploy.ts new file mode 100644 index 000000000000..a6c77f5e7e2d --- /dev/null +++ b/packages/contracts/deploy/010-OVM_FraudVerifer.deploy.ts @@ -0,0 +1,26 @@ +/* Imports: External */ +import { DeployFunction } from 'hardhat-deploy/dist/types' + +/* Imports: Internal */ +import { + deployAndRegister, + getDeployedContract, +} from '../src/hardhat-deploy-ethers' + +const deployFn: DeployFunction = async (hre) => { + const Lib_AddressManager = await getDeployedContract( + hre, + 'Lib_AddressManager' + ) + + await deployAndRegister({ + hre, + name: 'OVM_FraudVerifier', + args: [Lib_AddressManager.address], + }) +} + +deployFn.dependencies = ['Lib_AddressManager'] +deployFn.tags = ['OVM_FraudVerifier'] + +export default deployFn diff --git a/packages/contracts/deploy/011-OVM_StateManagerFactory.deploy.ts b/packages/contracts/deploy/011-OVM_StateManagerFactory.deploy.ts new file mode 100644 index 000000000000..dde5f88abb03 --- /dev/null +++ b/packages/contracts/deploy/011-OVM_StateManagerFactory.deploy.ts @@ -0,0 +1,17 @@ +/* Imports: External */ +import { DeployFunction } from 'hardhat-deploy/dist/types' + +/* Imports: Internal */ +import { deployAndRegister } from '../src/hardhat-deploy-ethers' + +const deployFn: DeployFunction = async (hre) => { + await deployAndRegister({ + hre, + name: 'OVM_StateManagerFactory', + args: [], + }) +} + +deployFn.tags = ['OVM_FraudVerifier'] + +export default deployFn diff --git a/packages/contracts/deploy/012-OVM_StateTransitionerFactory.deploy.ts b/packages/contracts/deploy/012-OVM_StateTransitionerFactory.deploy.ts new file mode 100644 index 000000000000..2611f359ecdd --- /dev/null +++ b/packages/contracts/deploy/012-OVM_StateTransitionerFactory.deploy.ts @@ -0,0 +1,26 @@ +/* Imports: External */ +import { DeployFunction } from 'hardhat-deploy/dist/types' + +/* Imports: Internal */ +import { + deployAndRegister, + getDeployedContract, +} from '../src/hardhat-deploy-ethers' + +const deployFn: DeployFunction = async (hre) => { + const Lib_AddressManager = await getDeployedContract( + hre, + 'Lib_AddressManager' + ) + + await deployAndRegister({ + hre, + name: 'OVM_StateTransitionerFactory', + args: [Lib_AddressManager.address], + }) +} + +deployFn.dependencies = ['Lib_AddressManager'] +deployFn.tags = ['OVM_StateTransitionerFactory'] + +export default deployFn diff --git a/packages/contracts/deploy/013-OVM_SafetyChecker.deploy.ts b/packages/contracts/deploy/013-OVM_SafetyChecker.deploy.ts new file mode 100644 index 000000000000..24223dbaaf28 --- /dev/null +++ b/packages/contracts/deploy/013-OVM_SafetyChecker.deploy.ts @@ -0,0 +1,17 @@ +/* Imports: External */ +import { DeployFunction } from 'hardhat-deploy/dist/types' + +/* Imports: Internal */ +import { deployAndRegister } from '../src/hardhat-deploy-ethers' + +const deployFn: DeployFunction = async (hre) => { + await deployAndRegister({ + hre, + name: 'OVM_SafetyChecker', + args: [], + }) +} + +deployFn.tags = ['OVM_SafetyChecker'] + +export default deployFn diff --git a/packages/contracts/deploy/014-OVM_L1MultiMessageRelayer.deploy.ts b/packages/contracts/deploy/014-OVM_L1MultiMessageRelayer.deploy.ts new file mode 100644 index 000000000000..8b74aefa3fdf --- /dev/null +++ b/packages/contracts/deploy/014-OVM_L1MultiMessageRelayer.deploy.ts @@ -0,0 +1,26 @@ +/* Imports: External */ +import { DeployFunction } from 'hardhat-deploy/dist/types' + +/* Imports: Internal */ +import { + deployAndRegister, + getDeployedContract, +} from '../src/hardhat-deploy-ethers' + +const deployFn: DeployFunction = async (hre) => { + const Lib_AddressManager = await getDeployedContract( + hre, + 'Lib_AddressManager' + ) + + await deployAndRegister({ + hre, + name: 'OVM_L1MultiMessageRelayer', + args: [Lib_AddressManager.address], + }) +} + +deployFn.dependencies = ['Lib_AddressManager'] +deployFn.tags = ['OVM_L1MultiMessageRelayer'] + +export default deployFn diff --git a/packages/contracts/deploy/015-OVM_L1ETHGateway.deploy.ts b/packages/contracts/deploy/015-OVM_L1ETHGateway.deploy.ts new file mode 100644 index 000000000000..85aa3cc151e0 --- /dev/null +++ b/packages/contracts/deploy/015-OVM_L1ETHGateway.deploy.ts @@ -0,0 +1,59 @@ +/* Imports: External */ +import { DeployFunction } from 'hardhat-deploy/dist/types' + +/* Imports: Internal */ +import { getDeployedContract } from '../src/hardhat-deploy-ethers' +import { predeploys } from '../src/predeploys' + +const deployFn: DeployFunction = async (hre) => { + const { deploy } = hre.deployments + const { deployer } = await hre.getNamedAccounts() + + const Lib_AddressManager = await getDeployedContract( + hre, + 'Lib_AddressManager', + { + signerOrProvider: deployer, + } + ) + + const result = await deploy('OVM_L1ETHGateway', { + from: deployer, + args: [], + log: true, + }) + + if (!result.newlyDeployed) { + return + } + + const OVM_L1ETHGateway = await getDeployedContract(hre, 'OVM_L1ETHGateway', { + signerOrProvider: deployer, + }) + + // NOTE: this initialization is *not* technically required (we only need to initialize the proxy) + // but it feels safer to initialize this anyway. Otherwise someone else could come along and + // initialize this. + await OVM_L1ETHGateway.initialize( + Lib_AddressManager.address, + predeploys.OVM_ETH + ) + + const libAddressManager = await OVM_L1ETHGateway.libAddressManager() + if (libAddressManager !== Lib_AddressManager.address) { + throw new Error( + `\n**FATAL ERROR. THIS SHOULD NEVER HAPPEN. CHECK YOUR DEPLOYMENT.**:\n` + + `OVM_L1ETHGateway could not be succesfully initialized.\n` + + `Attempted to set Lib_AddressManager to: ${Lib_AddressManager.address}\n` + + `Actual address after initialization: ${libAddressManager}\n` + + `This could indicate a compromised deployment.` + ) + } + + await Lib_AddressManager.setAddress('OVM_L1ETHGateway', result.address) +} + +deployFn.dependencies = ['Lib_AddressManager'] +deployFn.tags = ['OVM_L1ETHGateway'] + +export default deployFn diff --git a/packages/contracts/deploy/016-Proxy__OVM_L1ETHGateway.deploy.ts b/packages/contracts/deploy/016-Proxy__OVM_L1ETHGateway.deploy.ts new file mode 100644 index 000000000000..2c57e94b43a3 --- /dev/null +++ b/packages/contracts/deploy/016-Proxy__OVM_L1ETHGateway.deploy.ts @@ -0,0 +1,62 @@ +/* Imports: External */ +import { DeployFunction } from 'hardhat-deploy/dist/types' + +/* Imports: Internal */ +import { getDeployedContract } from '../src/hardhat-deploy-ethers' +import { predeploys } from '../src/predeploys' + +const deployFn: DeployFunction = async (hre) => { + const { deploy } = hre.deployments + const { deployer } = await hre.getNamedAccounts() + + const Lib_AddressManager = await getDeployedContract( + hre, + 'Lib_AddressManager', + { + signerOrProvider: deployer, + } + ) + + const result = await deploy('Proxy__OVM_L1ETHGateway', { + contract: 'Lib_ResolvedDelegateProxy', + from: deployer, + args: [Lib_AddressManager.address, 'OVM_L1ETHGateway'], + log: true, + }) + + if (!result.newlyDeployed) { + return + } + + const Proxy__OVM_L1ETHGateway = await getDeployedContract( + hre, + 'Proxy__OVM_L1ETHGateway', + { + signerOrProvider: deployer, + iface: 'OVM_L1ETHGateway', + } + ) + + await Proxy__OVM_L1ETHGateway.initialize( + Lib_AddressManager.address, + predeploys.OVM_ETH + ) + + const libAddressManager = await Proxy__OVM_L1ETHGateway.libAddressManager() + if (libAddressManager !== Lib_AddressManager.address) { + throw new Error( + `\n**FATAL ERROR. THIS SHOULD NEVER HAPPEN. CHECK YOUR DEPLOYMENT.**:\n` + + `Proxy__OVM_L1ETHGateway could not be succesfully initialized.\n` + + `Attempted to set Lib_AddressManager to: ${Lib_AddressManager.address}\n` + + `Actual address after initialization: ${libAddressManager}\n` + + `This could indicate a compromised deployment.` + ) + } + + await Lib_AddressManager.setAddress('Proxy__OVM_L1ETHGateway', result.address) +} + +deployFn.dependencies = ['Lib_AddressManager', 'OVM_L1ETHGateway'] +deployFn.tags = ['Proxy__OVM_L1ETHGateway'] + +export default deployFn diff --git a/packages/contracts/deploy/017-finalize.ts b/packages/contracts/deploy/017-finalize.ts new file mode 100644 index 000000000000..6a47302f1982 --- /dev/null +++ b/packages/contracts/deploy/017-finalize.ts @@ -0,0 +1,47 @@ +/* Imports: External */ +import { DeployFunction } from 'hardhat-deploy/dist/types' + +/* Imports: Internal */ +import { getDeployedContract } from '../src/hardhat-deploy-ethers' + +const deployFn: DeployFunction = async (hre) => { + const { deployer } = await hre.getNamedAccounts() + const Lib_AddressManager = await getDeployedContract( + hre, + 'Lib_AddressManager', + { + signerOrProvider: deployer, + } + ) + + const owner = (hre as any).deployConfig.ovmAddressManagerOwner + const remoteOwner = await Lib_AddressManager.owner() + if (remoteOwner === owner) { + console.log( + `✓ Not changing owner of Lib_AddressManager because it's already correctly set` + ) + return + } + + console.log(`Transferring ownership of Lib_AddressManager to ${owner}...`) + const tx = await Lib_AddressManager.transferOwnership(owner) + await tx.wait() + + const newRemoteOwner = await Lib_AddressManager.owner() + if (newRemoteOwner !== owner) { + throw new Error( + `\n**FATAL ERROR. THIS SHOULD NEVER HAPPEN. CHECK YOUR DEPLOYMENT.**:\n` + + `Could not transfer ownership of Lib_AddressManager.\n` + + `Attempted to set owner of Lib_AddressManager to: ${owner}\n` + + `Actual owner after transaction: ${newRemoteOwner}\n` + + `This could indicate a compromised deployment.` + ) + } + + console.log(`✓ Set owner of Lib_AddressManager to: ${owner}`) +} + +deployFn.dependencies = ['Lib_AddressManager'] +deployFn.tags = ['finalize'] + +export default deployFn diff --git a/packages/contracts/hardhat.config.ts b/packages/contracts/hardhat.config.ts index c1936751437d..c13241a43516 100644 --- a/packages/contracts/hardhat.config.ts +++ b/packages/contracts/hardhat.config.ts @@ -1,5 +1,6 @@ import { HardhatUserConfig } from 'hardhat/types' import 'solidity-coverage' +import * as dotenv from 'dotenv' import { DEFAULT_ACCOUNTS_HARDHAT, @@ -9,19 +10,28 @@ import { // Hardhat plugins import '@nomiclabs/hardhat-ethers' import '@nomiclabs/hardhat-waffle' +import 'hardhat-deploy' import '@typechain/hardhat' import '@eth-optimism/hardhat-ovm' +import './tasks/deploy' + +// Load environment variables from .env +dotenv.config() const config: HardhatUserConfig = { networks: { hardhat: { accounts: DEFAULT_ACCOUNTS_HARDHAT, blockGasLimit: RUN_OVM_TEST_GAS * 2, + live: false, + saveDeployments: false, + tags: ['local'], }, // Add this network to your config! optimism: { url: 'http://127.0.0.1:8545', ovm: true, + saveDeployments: false, }, }, mocha: { @@ -42,6 +52,29 @@ const config: HardhatUserConfig = { outDir: 'dist/types', target: 'ethers-v5', }, + paths: { + deploy: './deploy', + deployments: './deployments', + }, + namedAccounts: { + deployer: { + default: 0, + }, + }, +} + +if ( + process.env.CONTRACTS_TARGET_NETWORK && + process.env.CONTRACTS_DEPLOYER_KEY && + process.env.CONTRACTS_RPC_URL +) { + config.networks[process.env.CONTRACTS_TARGET_NETWORK] = { + accounts: [process.env.CONTRACTS_DEPLOYER_KEY], + url: process.env.CONTRACTS_RPC_URL, + live: true, + saveDeployments: true, + tags: [process.env.CONTRACTS_TARGET_NETWORK], + } } export default config diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 8a5775799afc..4981c64d72d4 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -29,7 +29,7 @@ "lint:fix": "yarn run lint:fix:typescript", "lint:fix:typescript": "prettier --config prettier-config.json --write \"hardhat.config.ts\" \"{src,test}/**/*.ts\"", "clean": "rm -rf ./dist ./artifacts ./artifacts-ovm ./cache ./cache-ovm ./tsconfig.build.tsbuildinfo", - "deploy": "./bin/deploy.js", + "deploy": "./bin/deploy.ts", "serve": "./bin/serve_dump.sh" }, "dependencies": { @@ -53,9 +53,12 @@ "buffer-xor": "^2.0.2", "chai": "^4.3.1", "copyfiles": "^2.3.0", + "directory-tree": "^2.2.7", + "dotenv": "^8.2.0", "ethereum-waffle": "^3.3.0", "ethers": "^5.0.31", "hardhat": "^2.0.8", + "hardhat-deploy": "^0.7.4", "lodash": "^4.17.20", "merkle-patricia-tree": "^4.0.0", "merkletreejs": "^0.2.12", @@ -65,6 +68,7 @@ "rlp": "^2.2.6", "solidity-coverage": "^0.7.16", "ts-generator": "0.0.8", + "ts-node": "^9.1.1", "typechain": "2.0.0" }, "peerDependencies": { diff --git a/packages/contracts/src/contract-dumps.ts b/packages/contracts/src/contract-dumps.ts index 04a10c978118..697f35f1206d 100644 --- a/packages/contracts/src/contract-dumps.ts +++ b/packages/contracts/src/contract-dumps.ts @@ -8,6 +8,7 @@ import { fromHexString, toHexString, remove0x } from '@eth-optimism/core-utils' /* Internal Imports */ import { deploy, RollupDeployConfig } from './contract-deployment' import { getContractDefinition } from './contract-defs' +import { predeploys } from './predeploys' interface StorageDump { [key: string]: string @@ -160,19 +161,6 @@ export const makeStateDump = async (cfg: RollupDeployConfig): Promise => { config = { ...config, ...cfg } - const predeploys = { - OVM_L2ToL1MessagePasser: '0x4200000000000000000000000000000000000000', - OVM_L1MessageSender: '0x4200000000000000000000000000000000000001', - OVM_DeployerWhitelist: '0x4200000000000000000000000000000000000002', - OVM_ECDSAContractAccount: '0x4200000000000000000000000000000000000003', - OVM_ProxySequencerEntrypoint: '0x4200000000000000000000000000000000000004', - OVM_SequencerEntrypoint: '0x4200000000000000000000000000000000000005', - OVM_ETH: '0x4200000000000000000000000000000000000006', - OVM_L2CrossDomainMessenger: '0x4200000000000000000000000000000000000007', - Lib_AddressManager: '0x4200000000000000000000000000000000000008', - ERC1820Registry: '0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24', - } - const ovmCompiled = [ 'OVM_L2ToL1MessagePasser', 'OVM_L2CrossDomainMessenger', diff --git a/packages/contracts/src/hardhat-deploy-ethers.ts b/packages/contracts/src/hardhat-deploy-ethers.ts new file mode 100644 index 000000000000..9c2509fe0557 --- /dev/null +++ b/packages/contracts/src/hardhat-deploy-ethers.ts @@ -0,0 +1,132 @@ +/* Imports: External */ +import { Contract } from 'ethers' +import { Provider } from '@ethersproject/abstract-provider' +import { Signer } from '@ethersproject/abstract-signer' + +export const registerAddress = async ({ + hre, + name, + address, +}): Promise => { + // 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}...`) + const tx = await Lib_AddressManager.setAddress(name, address) + await tx.wait() + + const remoteAddress = await Lib_AddressManager.getAddress(name) + if (remoteAddress !== address) { + throw new Error( + `\n**FATAL ERROR. THIS SHOULD NEVER HAPPEN. CHECK YOUR DEPLOYMENT.**:\n` + + `Call to Lib_AddressManager.setAddress(${name}) was unsuccessful.\n` + + `Attempted to set address to: ${address}\n` + + `Actual address was set to: ${remoteAddress}\n` + + `This could indicate a compromised deployment.` + ) + } + + console.log(`✓ Registered address for ${name}`) +} + +export const deployAndRegister = async ({ + hre, + name, + args, + contract, +}: { + hre: any + name: string + args: any[] + contract?: string +}) => { + const { deploy } = hre.deployments + const { deployer } = await hre.getNamedAccounts() + + const result = await deploy(name, { + contract, + from: deployer, + args, + log: true, + }) + + await hre.ethers.provider.waitForTransaction(result.transactionHash) + + if (result.newlyDeployed) { + await registerAddress({ + hre, + name, + address: result.address, + }) + } +} + +export const getDeployedContract = async ( + hre: any, + name: string, + options: { + iface?: string + signerOrProvider?: Signer | Provider | string + } = {} +): Promise => { + const deployed = await hre.deployments.get(name) + + await hre.ethers.provider.waitForTransaction(deployed.receipt.transactionHash) + + // Get the correct interface. + let iface = new hre.ethers.utils.Interface(deployed.abi) + if (options.iface) { + const factory = await hre.ethers.getContractFactory(options.iface) + iface = factory.interface + } + + let signerOrProvider: Signer | Provider = hre.ethers.provider + if (options.signerOrProvider) { + if (typeof options.signerOrProvider === 'string') { + signerOrProvider = hre.ethers.provider.getSigner(options.signerOrProvider) + } else { + signerOrProvider = options.signerOrProvider + } + } + + // Temporarily override Object.defineProperty to bypass ether's object protection. + const def = Object.defineProperty + Object.defineProperty = (obj, propName, prop) => { + prop.writable = true + return def(obj, propName, prop) + } + + const contract = new Contract(deployed.address, iface, signerOrProvider) + + // Now reset Object.defineProperty + Object.defineProperty = def + + // Override each function call to also `.wait()` so as to simplify the deploy scripts' syntax. + for (const fnName of Object.keys(contract.functions)) { + const fn = contract[fnName].bind(contract) + ;(contract as any)[fnName] = async (...args: any) => { + const result = await fn(...args) + if (typeof result === 'object' && typeof result.wait === 'function') { + await result.wait() + } + return result + } + } + + return contract +} diff --git a/packages/contracts/src/predeploys.ts b/packages/contracts/src/predeploys.ts new file mode 100644 index 000000000000..a442cf02c54f --- /dev/null +++ b/packages/contracts/src/predeploys.ts @@ -0,0 +1,12 @@ +export const predeploys = { + OVM_L2ToL1MessagePasser: '0x4200000000000000000000000000000000000000', + OVM_L1MessageSender: '0x4200000000000000000000000000000000000001', + OVM_DeployerWhitelist: '0x4200000000000000000000000000000000000002', + OVM_ECDSAContractAccount: '0x4200000000000000000000000000000000000003', + OVM_ProxySequencerEntrypoint: '0x4200000000000000000000000000000000000004', + OVM_SequencerEntrypoint: '0x4200000000000000000000000000000000000005', + OVM_ETH: '0x4200000000000000000000000000000000000006', + OVM_L2CrossDomainMessenger: '0x4200000000000000000000000000000000000007', + Lib_AddressManager: '0x4200000000000000000000000000000000000008', + ERC1820Registry: '0x1820a4B7618BdE71Dce8cdc73aAB6C95905faD24', +} diff --git a/packages/contracts/tasks/deploy.ts b/packages/contracts/tasks/deploy.ts new file mode 100644 index 000000000000..35d2e041b692 --- /dev/null +++ b/packages/contracts/tasks/deploy.ts @@ -0,0 +1,128 @@ +/* Imports: External */ +import { ethers } from 'ethers' +import { task } from 'hardhat/config' +import * as types from 'hardhat/internal/core/params/argumentTypes' + +const DEFAULT_L1_BLOCK_TIME_SECONDS = 15 +const DEFAULT_CTC_FORCE_INCLUSION_PERIOD_SECONDS = 60 * 60 * 24 * 30 // 30 days +const DEFAULT_CTC_MAX_TRANSACTION_GAS_LIMIT = 9_000_000 +const DEFAULT_EM_MIN_TRANSACTION_GAS_LIMIT = 50_000 +const DEFAULT_EM_MAX_TRANSACTION_GAS_LIMIT = 9_000_000 +const DEFAULT_EM_MAX_GAS_PER_QUEUE_PER_EPOCH = 250_000_000 +const DEFAULT_EM_SECONDS_PER_EPOCH = 0 +const DEFAULT_EM_OVM_CHAIN_ID = 420 +const DEFAULT_SCC_FRAUD_PROOF_WINDOW = 60 * 60 * 24 * 7 // 7 days +const DEFAULT_SCC_SEQUENCER_PUBLISH_WINDOW = 60 * 30 // 30 minutes + +task('deploy') + .addOptionalParam( + 'l1BlockTimeSeconds', + 'Number of seconds on average between every L1 block.', + DEFAULT_L1_BLOCK_TIME_SECONDS, + types.int + ) + .addOptionalParam( + 'ctcForceInclusionPeriodSeconds', + 'Number of seconds that the sequencer has to include transactions before the L1 queue.', + DEFAULT_CTC_FORCE_INCLUSION_PERIOD_SECONDS, + types.int + ) + .addOptionalParam( + 'ctcMaxTransactionGasLimit', + 'Max gas limit for L1 queue transactions.', + DEFAULT_CTC_MAX_TRANSACTION_GAS_LIMIT, + types.int + ) + .addOptionalParam( + 'emMinTransactionGasLimit', + 'Minimum allowed transaction gas limit.', + DEFAULT_EM_MIN_TRANSACTION_GAS_LIMIT, + types.int + ) + .addOptionalParam( + 'emMaxTransactionGasLimit', + 'Maximum allowed transaction gas limit.', + DEFAULT_EM_MAX_TRANSACTION_GAS_LIMIT, + types.int + ) + .addOptionalParam( + 'emMaxGasPerQueuePerEpoch', + 'Maximum gas allowed in a given queue for each epoch.', + DEFAULT_EM_MAX_GAS_PER_QUEUE_PER_EPOCH, + types.int + ) + .addOptionalParam( + 'emSecondsPerEpoch', + 'Number of seconds in each epoch.', + DEFAULT_EM_SECONDS_PER_EPOCH, + types.int + ) + .addOptionalParam( + 'emOvmChainId', + 'Chain ID for the L2 network.', + DEFAULT_EM_OVM_CHAIN_ID, + types.int + ) + .addOptionalParam( + 'sccFraudProofWindow', + 'Number of seconds until a transaction is considered finalized.', + DEFAULT_SCC_FRAUD_PROOF_WINDOW, + types.int + ) + .addOptionalParam( + 'sccSequencerPublishWindow', + 'Number of seconds that the sequencer is exclusively allowed to post state roots.', + DEFAULT_SCC_SEQUENCER_PUBLISH_WINDOW, + types.int + ) + .addOptionalParam( + 'ovmSequencerAddress', + 'Address of the sequencer. Must be provided or this deployment will fail.', + undefined, + types.string + ) + .addOptionalParam( + 'ovmProposerAddress', + 'Address of the account that will propose state roots. Must be provided or this deployment will fail.', + undefined, + types.string + ) + .addOptionalParam( + 'ovmRelayerAddress', + 'Address of the message relayer. Must be provided or this deployment will fail.', + undefined, + types.string + ) + .addOptionalParam( + 'ovmAddressManagerOwner', + 'Address that will own the Lib_AddressManager. Must be provided or this deployment will fail.', + undefined, + types.string + ) + .setAction(async (args, hre: any, runSuper) => { + // Necessary because hardhat doesn't let us attach non-optional parameters to existing tasks. + const validateAddressArg = (argName: string) => { + if (args[argName] === undefined) { + throw new Error( + `argument for ${argName} is required but was not provided` + ) + } + if (!ethers.utils.isAddress(args[argName])) { + throw new Error( + `argument for ${argName} is not a valid address: ${args[argName]}` + ) + } + } + + validateAddressArg('ovmSequencerAddress') + validateAddressArg('ovmProposerAddress') + validateAddressArg('ovmRelayerAddress') + validateAddressArg('ovmAddressManagerOwner') + + args.ctcForceInclusionPeriodBlocks = Math.floor( + args.ctcForceInclusionPeriodSeconds / args.l1BlockTimeSeconds + ) + + hre.deployConfig = args + return runSuper(args) + }) diff --git a/packages/hardhat-ovm/src/index.ts b/packages/hardhat-ovm/src/index.ts index f87da86b63de..40d721283905 100644 --- a/packages/hardhat-ovm/src/index.ts +++ b/packages/hardhat-ovm/src/index.ts @@ -75,20 +75,27 @@ const getOvmSolcPath = async (version: string): Promise => { subtask( TASK_COMPILE_SOLIDITY_RUN_SOLC, async (args: { input: any; solcPath: string }, hre, runSuper) => { - const ignoreRxList = hre.network.config.ignoreRxList || []; - const ignore = (filename: string) => ignoreRxList.reduce((ignored: boolean, rx: string | RegExp) => ignored || new RegExp(rx).test(filename), false); + const ignoreRxList = hre.network.config.ignoreRxList || [] + const ignore = (filename: string) => + ignoreRxList.reduce( + (ignored: boolean, rx: string | RegExp) => + ignored || new RegExp(rx).test(filename), + false + ) if (hre.network.ovm !== true) { - // Separate the EVM and OVM inputs. - for (const file of Object.keys(args.input.sources)) { - // Ignore any contract that has this tag or in ignore list - if (args.input.sources[file].content.includes('// @unsupported: evm') || ignore(file)) { - delete args.input.sources[file]; - } - else { - //console.log(file + ' included'); - } + // Separate the EVM and OVM inputs. + for (const file of Object.keys(args.input.sources)) { + // Ignore any contract that has this tag or in ignore list + if ( + args.input.sources[file].content.includes('// @unsupported: evm') || + ignore(file) + ) { + delete args.input.sources[file] + } else { + //console.log(file + ' included'); } - return runSuper(args) + } + return runSuper(args) } // Just some silly sanity checks, make sure we have a solc version to download. Our format is @@ -114,7 +121,10 @@ subtask( // Separate the EVM and OVM inputs. for (const file of Object.keys(args.input.sources)) { // Ignore any contract that has this tag or in ignore list - if (!args.input.sources[file].content.includes('// @unsupported: ovm') && !ignore(file)) { + if ( + !args.input.sources[file].content.includes('// @unsupported: ovm') && + !ignore(file) + ) { ovmInput.sources[file] = args.input.sources[file] } } @@ -153,8 +163,8 @@ extendEnvironment((hre) => { } // Forcibly update the artifacts object. - hre.config.paths.artifacts = artifactsPath; - hre.config.paths.cache = cachePath; - (hre as any).artifacts = new Artifacts(artifactsPath); + hre.config.paths.artifacts = artifactsPath + hre.config.paths.cache = cachePath + ;(hre as any).artifacts = new Artifacts(artifactsPath) } }) diff --git a/packages/hardhat-ovm/src/type-extensions.ts b/packages/hardhat-ovm/src/type-extensions.ts index dd28c766e992..2d6758ca6adc 100644 --- a/packages/hardhat-ovm/src/type-extensions.ts +++ b/packages/hardhat-ovm/src/type-extensions.ts @@ -14,31 +14,29 @@ declare module 'hardhat/types/config' { } interface HardhatNetworkUserConfig { - ovm?: boolean; - ignoreRxList?: string[]; + ovm?: boolean + ignoreRxList?: string[] } interface HttpNetworkUserConfig { - ovm?: boolean; - ignoreRxList?: string[]; + ovm?: boolean + ignoreRxList?: string[] } - interface HardhatNetworkConfig { - ovm: boolean; - ignoreRxList: string[]; + ovm: boolean + ignoreRxList: string[] } interface HttpNetworkConfig { - ovm: boolean; - ignoreRxList: string[]; + ovm: boolean + ignoreRxList: string[] } } - declare module 'hardhat/types/runtime' { interface Network { - ovm: boolean; - ignoreRxList: string[]; + ovm: boolean + ignoreRxList: string[] } } diff --git a/yarn.lock b/yarn.lock index 3fb3cac2bcdc..57793871cfbf 100644 --- a/yarn.lock +++ b/yarn.lock @@ -171,7 +171,7 @@ "@ethersproject/properties" ">=5.0.0-beta.131" "@ethersproject/strings" ">=5.0.0-beta.130" -"@ethersproject/abi@5.1.0", "@ethersproject/abi@^5.0.0", "@ethersproject/abi@^5.0.1", "@ethersproject/abi@^5.0.13", "@ethersproject/abi@^5.1.0": +"@ethersproject/abi@5.1.0", "@ethersproject/abi@^5.0.0", "@ethersproject/abi@^5.0.1", "@ethersproject/abi@^5.0.13", "@ethersproject/abi@^5.0.2", "@ethersproject/abi@^5.1.0": version "5.1.0" resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.1.0.tgz#d582c9f6a8e8192778b5f2c991ce19d7b336b0c5" integrity sha512-N/W9Sbn1/C6Kh2kuHRjf/hX6euMK4+9zdJRBB8sDWmihVntjUAfxbusGZKzDQD8i3szAHhTz8K7XADV5iFNfJw== @@ -199,7 +199,7 @@ "@ethersproject/transactions" "^5.1.0" "@ethersproject/web" "^5.1.0" -"@ethersproject/abstract-signer@5.1.0", "@ethersproject/abstract-signer@^5.0.0", "@ethersproject/abstract-signer@^5.1.0": +"@ethersproject/abstract-signer@5.1.0", "@ethersproject/abstract-signer@^5.0.0", "@ethersproject/abstract-signer@^5.0.2", "@ethersproject/abstract-signer@^5.1.0": version "5.1.0" resolved "https://registry.yarnpkg.com/@ethersproject/abstract-signer/-/abstract-signer-5.1.0.tgz#744c7a2d0ebe3cc0bc38294d0f53d5ca3f4e49e3" integrity sha512-qQDMkjGZSSJSKl6AnfTgmz9FSnzq3iEoEbHTYwjDlEAv+LNP7zd4ixCcVWlWyk+2siud856M5CRhAmPdupeN9w== @@ -210,7 +210,7 @@ "@ethersproject/logger" "^5.1.0" "@ethersproject/properties" "^5.1.0" -"@ethersproject/address@5.1.0", "@ethersproject/address@>=5.0.0-beta.128", "@ethersproject/address@^5.0.0", "@ethersproject/address@^5.1.0": +"@ethersproject/address@5.1.0", "@ethersproject/address@>=5.0.0-beta.128", "@ethersproject/address@^5.0.0", "@ethersproject/address@^5.0.2", "@ethersproject/address@^5.1.0": version "5.1.0" resolved "https://registry.yarnpkg.com/@ethersproject/address/-/address-5.1.0.tgz#3854fd7ebcb6af7597de66f847c3345dae735b58" integrity sha512-rfWQR12eHn2cpstCFS4RF7oGjfbkZb0oqep+BfrT+gWEGWG2IowJvIsacPOvzyS1jhNF4MQ4BS59B04Mbovteg== @@ -236,7 +236,7 @@ "@ethersproject/bytes" "^5.1.0" "@ethersproject/properties" "^5.1.0" -"@ethersproject/bignumber@5.1.0", "@ethersproject/bignumber@>=5.0.0-beta.130", "@ethersproject/bignumber@^5.0.0", "@ethersproject/bignumber@^5.1.0": +"@ethersproject/bignumber@5.1.0", "@ethersproject/bignumber@>=5.0.0-beta.130", "@ethersproject/bignumber@^5.0.0", "@ethersproject/bignumber@^5.0.5", "@ethersproject/bignumber@^5.1.0": version "5.1.0" resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.1.0.tgz#966a013a5d871fc03fc67bf33cd8aadae627f0fd" integrity sha512-wUvQlhTjPjFXIdLPOuTrFeQmSa6Wvls1bGXQNQWvB/SEn1NsTCE8PmumIEZxmOPjSHl1eV2uyHP5jBm5Cgj92Q== @@ -245,7 +245,7 @@ "@ethersproject/logger" "^5.1.0" bn.js "^4.4.0" -"@ethersproject/bytes@5.1.0", "@ethersproject/bytes@>=5.0.0-beta.129", "@ethersproject/bytes@^5.0.0", "@ethersproject/bytes@^5.1.0": +"@ethersproject/bytes@5.1.0", "@ethersproject/bytes@>=5.0.0-beta.129", "@ethersproject/bytes@^5.0.0", "@ethersproject/bytes@^5.0.2", "@ethersproject/bytes@^5.1.0": version "5.1.0" resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.1.0.tgz#55dfa9c4c21df1b1b538be3accb50fb76d5facfd" integrity sha512-sGTxb+LVjFxJcJeUswAIK6ncgOrh3D8c192iEJd7mLr95V6du119rRfYT/b87WPkZ5I3gRBUYIYXtdgCWACe8g== @@ -259,7 +259,7 @@ dependencies: "@ethersproject/bignumber" "^5.1.0" -"@ethersproject/contracts@5.1.0", "@ethersproject/contracts@^5.0.0", "@ethersproject/contracts@^5.0.5": +"@ethersproject/contracts@5.1.0", "@ethersproject/contracts@^5.0.0", "@ethersproject/contracts@^5.0.2", "@ethersproject/contracts@^5.0.5": version "5.1.0" resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.1.0.tgz#f7c3451f1af77e029005733ccab3419d07d23f6b" integrity sha512-dvTMs/4XGSc57cYOW0KjgX1NdTujUu7mNb6PQdJWg08m9ULzPyGZuBkFJnijBcp6vTOCQ59RwjboWgNWw393og== @@ -373,7 +373,7 @@ dependencies: "@ethersproject/logger" "^5.1.0" -"@ethersproject/providers@5.1.0", "@ethersproject/providers@^5.0.0", "@ethersproject/providers@^5.0.14", "@ethersproject/providers@^5.0.21", "@ethersproject/providers@^5.0.24": +"@ethersproject/providers@5.1.0", "@ethersproject/providers@^5.0.0", "@ethersproject/providers@^5.0.14", "@ethersproject/providers@^5.0.21", "@ethersproject/providers@^5.0.24", "@ethersproject/providers@^5.0.5": version "5.1.0" resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.1.0.tgz#27695a02cfafa370428cde1c7a4abab13afb6a35" integrity sha512-FjpZL2lSXrYpQDg2fMjugZ0HjQD9a+2fOOoRhhihh+Z+qi/xZ8vIlPoumrEP1DzIG4DBV6liUqLNqnX2C6FIAA== @@ -434,7 +434,7 @@ bn.js "^4.4.0" elliptic "6.5.4" -"@ethersproject/solidity@5.1.0", "@ethersproject/solidity@^5.0.0": +"@ethersproject/solidity@5.1.0", "@ethersproject/solidity@^5.0.0", "@ethersproject/solidity@^5.0.2": version "5.1.0" resolved "https://registry.yarnpkg.com/@ethersproject/solidity/-/solidity-5.1.0.tgz#095a9c75244edccb26c452c155736d363399b954" integrity sha512-kPodsGyo9zg1g9XSXp1lGhFaezBAUUsAUB1Vf6OkppE5Wksg4Et+x3kG4m7J/uShDMP2upkJtHNsIBK2XkVpKQ== @@ -454,7 +454,7 @@ "@ethersproject/constants" "^5.1.0" "@ethersproject/logger" "^5.1.0" -"@ethersproject/transactions@5.1.0", "@ethersproject/transactions@^5.0.0", "@ethersproject/transactions@^5.0.0-beta.135", "@ethersproject/transactions@^5.1.0": +"@ethersproject/transactions@5.1.0", "@ethersproject/transactions@^5.0.0", "@ethersproject/transactions@^5.0.0-beta.135", "@ethersproject/transactions@^5.0.2", "@ethersproject/transactions@^5.1.0": version "5.1.0" resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.1.0.tgz#da7fcd7e77e23dcfcca317a945f60bc228c61b36" integrity sha512-s10crRLZEA0Bgv6FGEl/AKkTw9f+RVUrlWDX1rHnD4ZncPFeiV2AJr4nT7QSUhxJdFPvjyKRDb3nEH27dIqcPQ== @@ -478,7 +478,7 @@ "@ethersproject/constants" "^5.1.0" "@ethersproject/logger" "^5.1.0" -"@ethersproject/wallet@5.1.0", "@ethersproject/wallet@^5.0.0": +"@ethersproject/wallet@5.1.0", "@ethersproject/wallet@^5.0.0", "@ethersproject/wallet@^5.0.2": version "5.1.0" resolved "https://registry.yarnpkg.com/@ethersproject/wallet/-/wallet-5.1.0.tgz#134c5816eaeaa586beae9f9ff67891104a2c9a15" integrity sha512-ULmUtiYQLTUS+y3DgkLzRhFEK10zMwmjOthnjiZxee3Q/MVwr3rnmuAnXIUZrPjna6hvUPnyRIdW5XuF0Ld0YQ== @@ -1926,7 +1926,7 @@ resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.2.3.tgz#ef65165aea2924c9359205bf748865b8881753c0" integrity sha512-PijRCG/K3s3w1We6ynUKdxEc5AcuuH3NBmMDP8uvKVp6X43UY7NQlTzczakXP3DJR0F4dfNQIGjU2cUeRYs2AA== -"@types/qs@*": +"@types/qs@*", "@types/qs@^6.9.4": version "6.9.6" resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.6.tgz#df9c3c8b31a247ec315e6996566be3171df4b3b1" integrity sha512-0/HnwIfW4ki2D8L8c9GVcG5I72s9jP5GSLVF0VIXDW00kmIpA6O33G7a8n59Tmh7Nz0WUC3rSb7PTY/sdW2JzA== @@ -4411,6 +4411,11 @@ dir-glob@^3.0.1: dependencies: path-type "^4.0.0" +directory-tree@^2.2.7: + version "2.2.7" + resolved "https://registry.yarnpkg.com/directory-tree/-/directory-tree-2.2.7.tgz#4617c794ee89d5618f03fffb7486c7e49df52ad2" + integrity sha512-fgTad/YdV6Y2njsCRK4fl4ZUlGhmb5xj1qrZUIMjvnrKvghVqh8dkB+OUssjYVvb/Q2L+5+8XG0l5uTGI9/8iQ== + dom-walk@^0.1.0: version "0.1.2" resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.2.tgz#0c548bef048f4d1f2a97249002236060daa3fd84" @@ -4513,6 +4518,11 @@ emoji-regex@^8.0.0: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== +encode-utf8@^1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/encode-utf8/-/encode-utf8-1.0.3.tgz#f30fdd31da07fb596f281beb2f6b027851994cda" + integrity sha512-ucAnuBEhUK4boH2HjVYG5Q2mQyPorvv0u/ocS+zhdw0S8AlHYY+GOFhP1Gio5z4icpP2ivFSvhtFjQi8+T9ppw== + encodeurl@~1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" @@ -5598,6 +5608,13 @@ flow-stoplight@^1.0.0: resolved "https://registry.yarnpkg.com/flow-stoplight/-/flow-stoplight-1.0.0.tgz#4a292c5bcff8b39fa6cc0cb1a853d86f27eeff7b" integrity sha1-SiksW8/4s5+mzAyxqFPYbyfu/3s= +fmix@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/fmix/-/fmix-0.1.0.tgz#c7bbf124dec42c9d191cfb947d0a9778dd986c0c" + integrity sha1-x7vxJN7ELJ0ZHPuUfQqXeN2YbAw= + dependencies: + imul "^1.0.0" + follow-redirects@1.5.10: version "1.5.10" resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.5.10.tgz#7b7a9f9aea2fdff36786a94ff643ed07f4ff5e2a" @@ -5715,7 +5732,7 @@ fs-extra@^8.1.0: jsonfile "^4.0.0" universalify "^0.1.0" -fs-extra@^9.1.0: +fs-extra@^9.0.0, fs-extra@^9.1.0: version "9.1.0" resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-9.1.0.tgz#5954460c764a8da2094ba3554bf839e6b9a7c86d" integrity sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ== @@ -6200,6 +6217,32 @@ hard-rejection@^2.1.0: resolved "https://registry.yarnpkg.com/hard-rejection/-/hard-rejection-2.1.0.tgz#1c6eda5c1685c63942766d79bb40ae773cecd883" integrity sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA== +hardhat-deploy@^0.7.4: + version "0.7.4" + resolved "https://registry.yarnpkg.com/hardhat-deploy/-/hardhat-deploy-0.7.4.tgz#6736f4e67ea62eefb2eb9790117682e2efabe0d0" + integrity sha512-i5Fdb+S7XpBSY+/j0HA09fxp7JPNO55vMfVmbvwx4y4w/TmDSxp74s/71JKGuwxVPZ8ke/gkWTsYjI1b56Zdgw== + dependencies: + "@ethersproject/abi" "^5.0.2" + "@ethersproject/abstract-signer" "^5.0.2" + "@ethersproject/address" "^5.0.2" + "@ethersproject/bignumber" "^5.0.5" + "@ethersproject/bytes" "^5.0.2" + "@ethersproject/contracts" "^5.0.2" + "@ethersproject/providers" "^5.0.5" + "@ethersproject/solidity" "^5.0.2" + "@ethersproject/transactions" "^5.0.2" + "@ethersproject/wallet" "^5.0.2" + "@types/qs" "^6.9.4" + axios "^0.21.1" + chalk "^4.1.0" + chokidar "^3.4.0" + debug "^4.1.1" + form-data "^3.0.0" + fs-extra "^9.0.0" + match-all "^1.2.6" + murmur-128 "^0.2.1" + qs "^6.9.4" + hardhat@^2.0.8, hardhat@^2.0.9, hardhat@^2.1.1, hardhat@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.1.2.tgz#a2128b71b0fb216ffc978c85a2030835b4e306ea" @@ -6541,6 +6584,11 @@ import-local@^3.0.2: pkg-dir "^4.2.0" resolve-cwd "^3.0.0" +imul@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/imul/-/imul-1.0.1.tgz#9d5867161e8b3de96c2c38d5dc7cb102f35e2ac9" + integrity sha1-nVhnFh6LPelsLDjV3HyxAvNeKsk= + imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" @@ -7868,6 +7916,11 @@ map-visit@^1.0.0: dependencies: object-visit "^1.0.0" +match-all@^1.2.6: + version "1.2.6" + resolved "https://registry.yarnpkg.com/match-all/-/match-all-1.2.6.tgz#66d276ad6b49655551e63d3a6ee53e8be0566f8d" + integrity sha512-0EESkXiTkWzrQQntBu2uzKvLu6vVkUGz40nGPbSZuegcfE5UuSzNjLaIu76zJWuaT/2I3Z/8M06OlUOZLGwLlQ== + md5.js@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" @@ -8466,6 +8519,15 @@ multimatch@^5.0.0: arrify "^2.0.1" minimatch "^3.0.4" +murmur-128@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/murmur-128/-/murmur-128-0.2.1.tgz#a9f6568781d2350ecb1bf80c14968cadbeaa4b4d" + integrity sha512-WseEgiRkI6aMFBbj8Cg9yBj/y+OdipwVC7zUo3W2W1JAJITwouUOtpqsmGSg67EQmwwSyod7hsVsWY5LsrfQVg== + dependencies: + encode-utf8 "^1.0.2" + fmix "^0.1.0" + imul "^1.0.0" + mute-stream@0.0.8, mute-stream@~0.0.4: version "0.0.8" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d"