diff --git a/.changeset/chatty-clouds-melt.md b/.changeset/chatty-clouds-melt.md new file mode 100644 index 0000000000000..2d037bf75fed0 --- /dev/null +++ b/.changeset/chatty-clouds-melt.md @@ -0,0 +1,5 @@ +--- +"@eth-optimism/hardhat-ovm": minor +--- + +allow overriding the ethers polling interval diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index 727b3a72a923c..2b1ffdf24bf9f 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -15,6 +15,7 @@ jobs: DOCKER_BUILDKIT: 1 COMPOSE_DOCKER_CLI_BUILD: 1 steps: + # Monorepo tests - uses: actions/checkout@v2 - name: Get yarn cache directory path @@ -46,5 +47,19 @@ jobs: env: FORCE_COLOR: 1 ENABLE_GAS_REPORT: 1 + - name: Print gas report run: cat integration-tests/gas-report.txt + + # Examples Tests + - name: Test & deploy hardhat-example on hardhat (regression) + working-directory: ./examples/hardhat + run: | + yarn deploy + yarn test + + - name: Test & deploy hardhat-example on Optimism + working-directory: ./examples/hardhat + run: | + yarn deploy:ovm + yarn test:ovm diff --git a/examples/hardhat/README.md b/examples/hardhat/README.md new file mode 100644 index 0000000000000..93624eec5b88f --- /dev/null +++ b/examples/hardhat/README.md @@ -0,0 +1,6 @@ +# The Officialâ„¢ Optimism Tutorial + +[![Discord](https://img.shields.io/discord/667044843901681675.svg?color=768AD4&label=discord&logo=https%3A%2F%2Fdiscordapp.com%2Fassets%2F8c9701b98ad4372b58f13fd9f65f966e.svg)](https://discord.com/channels/667044843901681675) +[![Twitter Follow](https://img.shields.io/twitter/follow/optimismPBC.svg?label=optimismPBC&style=social)](https://twitter.com/optimismPBC) + +### For the full README, please see the [guided repository of the `optimism-tutorial`](https://github.com/ethereum-optimism/optimism-tutorial) repository \ No newline at end of file diff --git a/examples/hardhat/contracts/ERC20.sol b/examples/hardhat/contracts/ERC20.sol new file mode 100644 index 0000000000000..26b36611f3fb3 --- /dev/null +++ b/examples/hardhat/contracts/ERC20.sol @@ -0,0 +1,196 @@ +// SPDX-License-Identifier: MIT +pragma solidity >0.6.0 <0.8.0; + +/** + * @title ERC20 + * @dev A super simple ERC20 implementation! + */ +contract ERC20 { + + /********** + * Events * + **********/ + + event Transfer( + address indexed _from, + address indexed _to, + uint256 _value + ); + + event Approval( + address indexed _owner, + address indexed _spender, + uint256 _value + ); + + + /************* + * Variables * + *************/ + + mapping (address => uint256) public balances; + mapping (address => mapping (address => uint256)) public allowances; + + // Some optional extra goodies. + uint256 public totalSupply; + string public name; + + + /*************** + * Constructor * + ***************/ + + /** + * @param _initialSupply Initial maximum token supply. + * @param _name A name for our ERC20 (technically optional, but it's fun ok jeez). + */ + constructor( + uint256 _initialSupply, + string memory _name + ) + public + { + balances[msg.sender] = _initialSupply; + totalSupply = _initialSupply; + name = _name; + } + + + /******************** + * Public Functions * + ********************/ + + /** + * Checks the balance of an address. + * @param _owner Address to check a balance for. + * @return Balance of the address. + */ + function balanceOf( + address _owner + ) + external + view + returns ( + uint256 + ) + { + return balances[_owner]; + } + + /** + * Transfers a balance from your account to someone else's account! + * @param _to Address to transfer a balance to. + * @param _amount Amount to transfer to the other account. + * @return true if the transfer was successful. + */ + function transfer( + address _to, + uint256 _amount + ) + external + returns ( + bool + ) + { + require( + balances[msg.sender] >= _amount, + "You don't have enough balance to make this transfer!" + ); + + balances[msg.sender] -= _amount; + balances[_to] += _amount; + + emit Transfer( + msg.sender, + _to, + _amount + ); + + return true; + } + + /** + * Transfers a balance from someone else's account to another account. You need an allowance + * from the sending account for this to work! + * @param _from Account to transfer a balance from. + * @param _to Account to transfer a balance to. + * @param _amount Amount to transfer to the other account. + * @return true if the transfer was successful. + */ + function transferFrom( + address _from, + address _to, + uint256 _amount + ) + external + returns ( + bool + ) + { + require( + balances[_from] >= _amount, + "Can't transfer from the desired account because it doesn't have enough balance." + ); + + require( + allowances[_from][msg.sender] >= _amount, + "Can't transfer from the desired account because you don't have enough of an allowance." + ); + + balances[_to] += _amount; + balances[_from] -= _amount; + + emit Transfer( + _from, + _to, + _amount + ); + + return true; + } + + /** + * Approves an account to spend some amount from your account. + * @param _spender Account to approve a balance for. + * @param _amount Amount to allow the account to spend from your account. + * @return true if the allowance was successful. + */ + function approve( + address _spender, + uint256 _amount + ) + external + returns ( + bool + ) + { + allowances[msg.sender][_spender] = _amount; + + emit Approval( + msg.sender, + _spender, + _amount + ); + + return true; + } + + /** + * Checks how much a given account is allowed to spend from another given account. + * @param _owner Address of the account to check an allowance from. + * @param _spender Address of the account trying to spend from the owner. + * @return Allowance for the spender from the owner. + */ + function allowance( + address _owner, + address _spender + ) + external + view + returns ( + uint256 + ) + { + return allowances[_owner][_spender]; + } +} diff --git a/examples/hardhat/deploy/ERC20.deploy.js b/examples/hardhat/deploy/ERC20.deploy.js new file mode 100644 index 0000000000000..6023f53d8fd97 --- /dev/null +++ b/examples/hardhat/deploy/ERC20.deploy.js @@ -0,0 +1,20 @@ +// Just a standard hardhat-deploy deployment definition file! +const func = async (hre) => { + const { deployments, getNamedAccounts } = hre + const { deploy } = deployments + const { deployer } = await getNamedAccounts() + + const initialSupply = 1000000 + const name = 'My Optimistic Token' + + await deploy('ERC20', { + from: deployer, + args: [initialSupply, name], + gasPrice: hre.ethers.BigNumber.from('0'), + gasLimit: 8999999, + log: true + }) +} + +func.tags = ['ERC20'] +module.exports = func diff --git a/examples/hardhat/hardhat.config.js b/examples/hardhat/hardhat.config.js new file mode 100644 index 0000000000000..c42677ecf5f87 --- /dev/null +++ b/examples/hardhat/hardhat.config.js @@ -0,0 +1,29 @@ +require('@nomiclabs/hardhat-ethers') +require('@nomiclabs/hardhat-waffle') +require('hardhat-deploy') +require("@eth-optimism/hardhat-ovm") + +module.exports = { + networks: { + // Add this network to your config! + optimism: { + url: 'http://127.0.0.1:8545', + // instantiate with a mnemonic so that you have >1 accounts available + accounts: { + mnemonic: 'test test test test test test test test test test test junk' + }, + // This sets the gas price to 0 for all transactions on L2. We do this + // because account balances are not automatically initiated with an ETH + // balance (yet, sorry!). + gasPrice: 0, + ovm: true // This sets the network as using the ovm and ensure contract will be compiled against that. + }, + }, + solidity: '0.7.6', + ovm: { + solcVersion: '0.7.6' + }, + namedAccounts: { + deployer: 0 + }, +} diff --git a/examples/hardhat/package.json b/examples/hardhat/package.json new file mode 100644 index 0000000000000..ad588a3d108a6 --- /dev/null +++ b/examples/hardhat/package.json @@ -0,0 +1,28 @@ +{ + "name": "@eth-optimism/hardhat-example", + "private": true, + "version": "1.0.0", + "main": "index.js", + "license": "MIT", + "scripts": { + "deploy": "hardhat deploy", + "deploy:ovm": "hardhat deploy --network optimism", + "compile": "hardhat compile", + "compile:ovm": "hardhat compile --network optimism", + "test": "hardhat test", + "test:ovm": "hardhat test --network optimism", + "clean": "rimraf ./cache-ovm ./cache ./artifacts-ovm ./artifacts ./deployments" + }, + "devDependencies": { + "@eth-optimism/hardhat-ovm": "^0.0.3", + "@nomiclabs/hardhat-ethers": "^2.0.1", + "@nomiclabs/hardhat-waffle": "^2.0.1", + "chai": "4.3.4", + "chai-as-promised": "^7.1.1", + "ethereum-waffle": "^3.3.0", + "ethers": "^5.1.4", + "hardhat": "^2.2.0", + "hardhat-deploy": "^0.7.5", + "mocha": "^8.2.1" + } +} diff --git a/examples/hardhat/test/erc20.test.js b/examples/hardhat/test/erc20.test.js new file mode 100644 index 0000000000000..e3e2141c5aa27 --- /dev/null +++ b/examples/hardhat/test/erc20.test.js @@ -0,0 +1,107 @@ +/* External Imports */ +const { ethers } = require('hardhat') +const { expect } = require('chai') + + +describe(`ERC20`, () => { + const INITIAL_SUPPLY = 1000000 + const TOKEN_NAME = 'An Optimistic ERC20' + + let account1 + let account2 + before(`load accounts`, async () => { + ;[ account1, account2 ] = await ethers.getSigners() + }) + + let ERC20 + beforeEach(`deploy ERC20 contract`, async () => { + const Factory__ERC20 = await ethers.getContractFactory('ERC20') + ERC20 = await Factory__ERC20.connect(account1).deploy( + INITIAL_SUPPLY, + TOKEN_NAME, + ) + + await ERC20.deployTransaction.wait() + }) + + it(`should have a name`, async () => { + const tokenName = await ERC20.name() + expect(tokenName).to.equal(TOKEN_NAME) + }) + + it(`should have a total supply equal to the initial supply`, async () => { + const tokenSupply = await ERC20.totalSupply() + expect(tokenSupply).to.equal(INITIAL_SUPPLY) + }) + + it(`should give the initial supply to the creator's address`, async () => { + const balance = await ERC20.balanceOf(await account1.getAddress()) + expect(balance).to.equal(INITIAL_SUPPLY) + }) + + describe(`transfer(...)`, () => { + it(`should revert when the sender does not have enough balance`, async () => { + const tx = ERC20.connect(account1).transfer( + await account2.getAddress(), + INITIAL_SUPPLY + 1, + ) + await expect(tx).to.be.reverted + }) + + it(`should succeed when the sender has enough balance`, async () => { + const tx = await ERC20.connect(account1).transfer( + await account2.getAddress(), + INITIAL_SUPPLY, + ) + await tx.wait() + + expect( + (await ERC20.balanceOf( + await account1.getAddress() + )).toNumber() + ).to.equal(0) + expect( + (await ERC20.balanceOf( + await account2.getAddress() + )).toNumber() + ).to.equal(INITIAL_SUPPLY) + }) + }) + + describe(`transferFrom(...)`, () => { + it(`should revert when the sender does not have enough of an allowance`, async () => { + const tx = ERC20.connect(account2).transferFrom( + await account1.getAddress(), + await account2.getAddress(), + INITIAL_SUPPLY, + ) + await expect(tx).to.be.reverted + }) + + it(`should succeed when the owner has enough balance and the sender has a large enough allowance`, async () => { + const tx1 = await ERC20.connect(account1).approve( + await account2.getAddress(), + INITIAL_SUPPLY, + ) + await tx1.wait() + + const tx2 = await ERC20.connect(account2).transferFrom( + await account1.getAddress(), + await account2.getAddress(), + INITIAL_SUPPLY, + ) + await tx2.wait() + + expect( + (await ERC20.balanceOf( + await account1.getAddress() + )).toNumber() + ).to.equal(0) + expect( + (await ERC20.balanceOf( + await account2.getAddress() + )).toNumber() + ).to.equal(INITIAL_SUPPLY) + }) + }) +}) diff --git a/package.json b/package.json index fa457ab21463c..ee6e03161c4fb 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,8 @@ "packages/*", "l2geth", "integration-tests", - "specs" + "specs", + "examples/*" ], "private": true, "devDependencies": { diff --git a/packages/contracts/hardhat.config.ts b/packages/contracts/hardhat.config.ts index 3d73bfd4a4116..26a9bfe9c3d83 100644 --- a/packages/contracts/hardhat.config.ts +++ b/packages/contracts/hardhat.config.ts @@ -29,6 +29,7 @@ const config: HardhatUserConfig = { live: false, saveDeployments: false, tags: ['local'], + hardfork: 'istanbul', }, // Add this network to your config! optimism: { diff --git a/packages/contracts/scripts/build.sh b/packages/contracts/scripts/build.sh index a61e5aca3316e..cc7d44cc48469 100755 --- a/packages/contracts/scripts/build.sh +++ b/packages/contracts/scripts/build.sh @@ -3,7 +3,5 @@ set -e yarn build:typescript & -yarn build:contracts & +yarn build:contracts yarn build:contracts:ovm - -wait diff --git a/packages/contracts/test/contracts/OVM/execution/OVM_ExecutionManager/nuisance-gas.spec.ts b/packages/contracts/test/contracts/OVM/execution/OVM_ExecutionManager/nuisance-gas.spec.ts index cfa5a449f38e5..334ea818ac10b 100644 --- a/packages/contracts/test/contracts/OVM/execution/OVM_ExecutionManager/nuisance-gas.spec.ts +++ b/packages/contracts/test/contracts/OVM/execution/OVM_ExecutionManager/nuisance-gas.spec.ts @@ -180,18 +180,6 @@ const test_nuisanceGas: TestDefinition = { { name: 'ovmCREATE consumes all allotted nuisance gas if creation code throws data-less exception', - postState: { - ExecutionManager: { - messageRecord: { - // note: this is slightly higher than the "idealized" value which would be: - // OVM_TX_GAS_LIMIT / 2 - 2 * ( Helper_TestRunner_BYTELEN * NUISANCE_GAS_PER_CONTRACT_BYTE ) - // This is because there is natural gas consumption between the ovmCALL(GAS/2) and ovmCREATE, which allots nuisance gas via _getNuisanceGasLimit. - // This means that the ovmCREATE exception, DOES consumes all nuisance gas allotted, but that allotment - // is less than the full OVM_TX_GAS_LIMIT / 2 which is alloted to the parent ovmCALL. - nuisanceGasLeft: 0x3f9e7f, - }, - }, - }, parameters: [ { name: 'give 1/2 gas to ovmCALL => ovmCREATE, evmINVALID', diff --git a/packages/hardhat-ovm/package.json b/packages/hardhat-ovm/package.json index 1c274ee776a29..2beaf6f88447d 100644 --- a/packages/hardhat-ovm/package.json +++ b/packages/hardhat-ovm/package.json @@ -18,7 +18,10 @@ "node-fetch": "^2.6.1" }, "devDependencies": { - "@types/mocha": "^8.2.2", + "@types/mocha": "^8.2.2" + }, + "peerDependencies": { + "ethers": "^5.1.4", "hardhat": "^2.2.1" } } diff --git a/packages/hardhat-ovm/src/index.ts b/packages/hardhat-ovm/src/index.ts index 274ec7bc68daf..7ac54e3d301f8 100644 --- a/packages/hardhat-ovm/src/index.ts +++ b/packages/hardhat-ovm/src/index.ts @@ -2,7 +2,9 @@ import * as fs from 'fs' import * as path from 'path' import fetch from 'node-fetch' +import { ethers } from 'ethers' import { subtask, extendEnvironment } from 'hardhat/config' +import { HardhatNetworkHDAccountsConfig } from 'hardhat/types/config' import { getCompilersDir } from 'hardhat/internal/util/global-dir' import { Artifacts } from 'hardhat/internal/artifacts' import { @@ -23,6 +25,10 @@ const OPTIMISM_SOLC_BIN_URL = // default to 0.6.X instead? const DEFAULT_OVM_SOLC_VERSION = '0.7.6' +// Poll the node every 50ms, to override ethers.js's default 4000ms causing OVM +// tests to be slow. +const OVM_POLLING_INTERVAL = 50 + /** * Find or generate an OVM soljson.js compiler file and return the path of this file. * We pass the path to this file into hardhat. @@ -174,7 +180,7 @@ subtask( } ) -extendEnvironment((hre) => { +extendEnvironment(async (hre) => { if (hre.network.config.ovm) { hre.network.ovm = hre.network.config.ovm @@ -200,5 +206,48 @@ extendEnvironment((hre) => { ;(hre as any).config.typechain.outDir += '-ovm' } } + + // if ethers is present and the node is running, override the polling interval to not wait the full + // duration in tests + if ((hre as any).ethers) { + const interval = hre.network.config.interval || OVM_POLLING_INTERVAL + if ((hre as any).ethers.provider.pollingInterval === interval) { + return + } + + // override the provider polling interval + const provider = new ethers.providers.JsonRpcProvider( + (hre as any).ethers.provider.url + ) + provider.pollingInterval = interval + provider.getGasPrice = async () => + ethers.BigNumber.from(hre.network.config.gasPrice) + ;(hre as any).ethers.provider = provider + + // if the node is up, override the getSigners method's signers + try { + let signers: ethers.Signer[] + const accounts = hre.network.config + .accounts as HardhatNetworkHDAccountsConfig + if (accounts) { + const indices = Array.from(Array(20).keys()) // generates array of [0, 1, 2, ..., 18, 19] + signers = indices.map((i) => + ethers.Wallet.fromMnemonic( + accounts.mnemonic, + `${accounts.path}/${i}` + ).connect(provider) + ) + } else { + signers = await (hre as any).ethers.getSigners() + signers = signers.map((s: any) => { + s._signer.provider.pollingInterval = interval + return s + }) + } + + ;(hre as any).ethers.getSigners = () => signers + /* tslint:disable:no-empty */ + } catch (e) {} + } } }) diff --git a/packages/hardhat-ovm/src/type-extensions.ts b/packages/hardhat-ovm/src/type-extensions.ts index 2d6758ca6adce..dfe8ef6beef91 100644 --- a/packages/hardhat-ovm/src/type-extensions.ts +++ b/packages/hardhat-ovm/src/type-extensions.ts @@ -26,11 +26,13 @@ declare module 'hardhat/types/config' { interface HardhatNetworkConfig { ovm: boolean ignoreRxList: string[] + interval?: number } interface HttpNetworkConfig { ovm: boolean ignoreRxList: string[] + interval?: number } } diff --git a/yarn.lock b/yarn.lock index f6cfced37c945..42410912569f9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -405,7 +405,7 @@ "@ethersproject/properties" "^5.1.0" "@ethersproject/strings" "^5.1.0" -"@ethersproject/abi@^5.0.0-beta.146": +"@ethersproject/abi@5.1.2", "@ethersproject/abi@^5.0.0-beta.146": version "5.1.2" resolved "https://registry.yarnpkg.com/@ethersproject/abi/-/abi-5.1.2.tgz#a8e75cd0455e6dc9e4861c3d1c22bbe436c1d775" integrity sha512-uMhoQVPX0UtfzTpekYQSEUcJGDgsJ25ifz+SV6PDETWaUFhcR8RNgb1QPTASP13inW8r6iy0/Xdq9D5hK2pNvA== @@ -479,6 +479,15 @@ "@ethersproject/logger" "^5.1.0" bn.js "^4.4.0" +"@ethersproject/bignumber@5.1.1": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@ethersproject/bignumber/-/bignumber-5.1.1.tgz#84812695253ccbc639117f7ac49ee1529b68e637" + integrity sha512-AVz5iqz7+70RIqoQTznsdJ6DOVBYciNlvO+AlQmPTB6ofCvoihI9bQdr6wljsX+d5W7Yc4nyvQvP4JMzg0Agig== + dependencies: + "@ethersproject/bytes" "^5.1.0" + "@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.0.2", "@ethersproject/bytes@^5.1.0": version "5.1.0" resolved "https://registry.yarnpkg.com/@ethersproject/bytes/-/bytes-5.1.0.tgz#55dfa9c4c21df1b1b538be3accb50fb76d5facfd" @@ -509,6 +518,22 @@ "@ethersproject/properties" "^5.1.0" "@ethersproject/transactions" "^5.1.0" +"@ethersproject/contracts@5.1.1": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@ethersproject/contracts/-/contracts-5.1.1.tgz#c66cb6d618fcbd73e20a6b808e8f768b2b781d0b" + integrity sha512-6WwktLJ0DFWU8pDkgH4IGttQHhQN4SnwKFu9h+QYVe48VGWtbDu4W8/q/7QA1u/HWlWMrKxqawPiZUJj0UMvOw== + dependencies: + "@ethersproject/abi" "^5.1.0" + "@ethersproject/abstract-provider" "^5.1.0" + "@ethersproject/abstract-signer" "^5.1.0" + "@ethersproject/address" "^5.1.0" + "@ethersproject/bignumber" "^5.1.0" + "@ethersproject/bytes" "^5.1.0" + "@ethersproject/constants" "^5.1.0" + "@ethersproject/logger" "^5.1.0" + "@ethersproject/properties" "^5.1.0" + "@ethersproject/transactions" "^5.1.0" + "@ethersproject/hardware-wallets@^5.0.8": version "5.1.0" resolved "https://registry.yarnpkg.com/@ethersproject/hardware-wallets/-/hardware-wallets-5.1.0.tgz#588d318f7232e02eaf4fa64374002ef3f53842e7" @@ -632,6 +657,31 @@ bech32 "1.1.4" ws "7.2.3" +"@ethersproject/providers@5.1.2": + version "5.1.2" + resolved "https://registry.yarnpkg.com/@ethersproject/providers/-/providers-5.1.2.tgz#4e4459698903f911402fe91aa7544eb07f3921ed" + integrity sha512-GqsS8rd+eyd4eNkcNgzZ4l9IRULBPUZa7JPnv22k4MHflMobUseyhfbVnmoN5bVNNkOxjV1IPTw9i0sV1hwdpg== + dependencies: + "@ethersproject/abstract-provider" "^5.1.0" + "@ethersproject/abstract-signer" "^5.1.0" + "@ethersproject/address" "^5.1.0" + "@ethersproject/basex" "^5.1.0" + "@ethersproject/bignumber" "^5.1.0" + "@ethersproject/bytes" "^5.1.0" + "@ethersproject/constants" "^5.1.0" + "@ethersproject/hash" "^5.1.0" + "@ethersproject/logger" "^5.1.0" + "@ethersproject/networks" "^5.1.0" + "@ethersproject/properties" "^5.1.0" + "@ethersproject/random" "^5.1.0" + "@ethersproject/rlp" "^5.1.0" + "@ethersproject/sha2" "^5.1.0" + "@ethersproject/strings" "^5.1.0" + "@ethersproject/transactions" "^5.1.0" + "@ethersproject/web" "^5.1.0" + bech32 "1.1.4" + ws "7.2.3" + "@ethersproject/random@5.1.0", "@ethersproject/random@^5.0.0", "@ethersproject/random@^5.1.0": version "5.1.0" resolved "https://registry.yarnpkg.com/@ethersproject/random/-/random-5.1.0.tgz#0bdff2554df03ebc5f75689614f2d58ea0d9a71f" @@ -703,6 +753,21 @@ "@ethersproject/rlp" "^5.1.0" "@ethersproject/signing-key" "^5.1.0" +"@ethersproject/transactions@5.1.1": + version "5.1.1" + resolved "https://registry.yarnpkg.com/@ethersproject/transactions/-/transactions-5.1.1.tgz#5a6bbb25fb062c3cc75eb0db12faefcdd3870813" + integrity sha512-Nwgbp09ttIVN0OoUBatCXaHxR7grWPHbozJN8v7AXDLrl6nnOIBEMDh+yJTnosSQlFhcyjfTGGN+Mx6R8HdvMw== + dependencies: + "@ethersproject/address" "^5.1.0" + "@ethersproject/bignumber" "^5.1.0" + "@ethersproject/bytes" "^5.1.0" + "@ethersproject/constants" "^5.1.0" + "@ethersproject/keccak256" "^5.1.0" + "@ethersproject/logger" "^5.1.0" + "@ethersproject/properties" "^5.1.0" + "@ethersproject/rlp" "^5.1.0" + "@ethersproject/signing-key" "^5.1.0" + "@ethersproject/units@5.1.0", "@ethersproject/units@^5.0.0": version "5.1.0" resolved "https://registry.yarnpkg.com/@ethersproject/units/-/units-5.1.0.tgz#b6ab3430ebc22adc3cb4839516496f167bee3ad5" @@ -3951,7 +4016,7 @@ chai-as-promised@^7.1.1: dependencies: check-error "^1.0.2" -chai@^4.2.0, chai@^4.3.0, chai@^4.3.1, chai@^4.3.3, chai@^4.3.4: +chai@4.3.4, chai@^4.2.0, chai@^4.3.0, chai@^4.3.1, chai@^4.3.3, chai@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.4.tgz#b55e655b31e1eac7099be4c08c21964fce2e6c49" integrity sha512-yS5H68VYOCtN1cjfwumDSuzn/9c+yza4f3reKXlE5rUg7SFcCEy90gJvydNgOYtblyf4Zi6jIWRnXOgErta0KA== @@ -5829,6 +5894,42 @@ ethers@^5.0.0, ethers@^5.0.1, ethers@^5.0.2, ethers@^5.0.26, ethers@^5.0.31, eth "@ethersproject/web" "5.1.0" "@ethersproject/wordlists" "5.1.0" +ethers@^5.1.4: + version "5.1.4" + resolved "https://registry.yarnpkg.com/ethers/-/ethers-5.1.4.tgz#8ae973705ed962f8f41dc59693704002a38dd18b" + integrity sha512-EAPQ/fgGRu0PoR/VNFnHTMOtG/IZ0AItdW55C9T8ffmVu0rnyllZL404eBF66elJehOLz2kxnUrhXpE7TCpW7g== + dependencies: + "@ethersproject/abi" "5.1.2" + "@ethersproject/abstract-provider" "5.1.0" + "@ethersproject/abstract-signer" "5.1.0" + "@ethersproject/address" "5.1.0" + "@ethersproject/base64" "5.1.0" + "@ethersproject/basex" "5.1.0" + "@ethersproject/bignumber" "5.1.1" + "@ethersproject/bytes" "5.1.0" + "@ethersproject/constants" "5.1.0" + "@ethersproject/contracts" "5.1.1" + "@ethersproject/hash" "5.1.0" + "@ethersproject/hdnode" "5.1.0" + "@ethersproject/json-wallets" "5.1.0" + "@ethersproject/keccak256" "5.1.0" + "@ethersproject/logger" "5.1.0" + "@ethersproject/networks" "5.1.0" + "@ethersproject/pbkdf2" "5.1.0" + "@ethersproject/properties" "5.1.0" + "@ethersproject/providers" "5.1.2" + "@ethersproject/random" "5.1.0" + "@ethersproject/rlp" "5.1.0" + "@ethersproject/sha2" "5.1.0" + "@ethersproject/signing-key" "5.1.0" + "@ethersproject/solidity" "5.1.0" + "@ethersproject/strings" "5.1.0" + "@ethersproject/transactions" "5.1.1" + "@ethersproject/units" "5.1.0" + "@ethersproject/wallet" "5.1.0" + "@ethersproject/web" "5.1.0" + "@ethersproject/wordlists" "5.1.0" + ethjs-unit@0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/ethjs-unit/-/ethjs-unit-0.1.6.tgz#c665921e476e87bce2a9d588a6fe0405b2c41699" @@ -6901,6 +7002,32 @@ hardhat-deploy@^0.7.4: murmur-128 "^0.2.1" qs "^6.9.4" +hardhat-deploy@^0.7.5: + version "0.7.5" + resolved "https://registry.yarnpkg.com/hardhat-deploy/-/hardhat-deploy-0.7.5.tgz#d31edcca709e9a8314efeaecb9a35792c295bc77" + integrity sha512-b+raIZBhrlw3lzkj7La8wyfczgxRsSWo8IHQM4STY4VUw0I/zjjeMm1naIvtGuebdrW/63ADLsucXZUZ8yVLkQ== + dependencies: + "@ethersproject/abi" "^5.0.0" + "@ethersproject/abstract-signer" "^5.0.0" + "@ethersproject/address" "^5.0.0" + "@ethersproject/bignumber" "^5.0.0" + "@ethersproject/bytes" "^5.0.0" + "@ethersproject/contracts" "^5.0.0" + "@ethersproject/providers" "^5.0.0" + "@ethersproject/solidity" "^5.0.0" + "@ethersproject/transactions" "^5.0.0" + "@ethersproject/wallet" "^5.0.0" + "@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-gas-reporter@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/hardhat-gas-reporter/-/hardhat-gas-reporter-1.0.4.tgz#59e3137e38e0dfeac2e4f90d5c74160b50ad4829" @@ -6909,7 +7036,7 @@ hardhat-gas-reporter@^1.0.4: eth-gas-reporter "^0.2.20" sha1 "^1.1.1" -hardhat@^2.2.1: +hardhat@^2.2.0, hardhat@^2.2.1: version "2.2.1" resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.2.1.tgz#bef0031b994e3f60a88d428f2097195c58cf9ed2" integrity sha512-8s7MtGXdh0NDwQKdlA8m8QdloVIN1+hv5aFpn0G5Ljj9vfNY9kUoc0a9pMboeGbd9WrS+XrZs5YlsPgQjaW/Tg== @@ -9150,7 +9277,7 @@ mocha@^7.1.1, mocha@^7.1.2: yargs-parser "13.1.2" yargs-unparser "1.6.0" -mocha@^8.3.0, mocha@^8.3.1, mocha@^8.3.2: +mocha@^8.2.1, mocha@^8.3.0, mocha@^8.3.1, mocha@^8.3.2: version "8.3.2" resolved "https://registry.yarnpkg.com/mocha/-/mocha-8.3.2.tgz#53406f195fa86fbdebe71f8b1c6fb23221d69fcc" integrity sha512-UdmISwr/5w+uXLPKspgoV7/RXZwKRTiTjJ2/AC5ZiEztIoOYdfKb19+9jNmEInzx5pBsCyJQzarAxqIGBNYJhg==