Commit 122df8cc authored by platocrat's avatar platocrat Committed by GitHub

docs: add hardhat example + ci (#641)

* feat(hardhat-ovm): allow overriding the polling interval for the provider and its signers

The default is 50ms, which should make running the OVM tests smooth. If you want
to run tests against a remote node and do not want to overwhelm it, set the
parameter in the hardhat config's network

* chore: add changeset

* docs: add hardhat example

imported from https://github.com/ethereum-optimism/optimism-tutorial/

* ci: add deploy/deploy:ovm

* fix(contracts): wait for contracts to finish

workaround hardhat not generating build artifacts for both evm and ovm

* fix: use istanbul hard fork

* test(contracts): remove hardcoded post-state in nuisance gas test

this post state is not giving us much info, and it's hard to
update it or debug it when it does not pass for any reason
Co-authored-by: default avatarGeorgios Konstantopoulos <me@gakonst.com>
parent 6daa408f
---
"@eth-optimism/hardhat-ovm": minor
---
allow overriding the ethers polling interval
......@@ -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
# 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
// 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];
}
}
// 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
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
},
}
{
"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"
}
}
/* 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)
})
})
})
......@@ -6,7 +6,8 @@
"packages/*",
"l2geth",
"integration-tests",
"specs"
"specs",
"examples/*"
],
"private": true,
"devDependencies": {
......
......@@ -29,6 +29,7 @@ const config: HardhatUserConfig = {
live: false,
saveDeployments: false,
tags: ['local'],
hardfork: 'istanbul',
},
// Add this network to your config!
optimism: {
......
......@@ -3,7 +3,5 @@
set -e
yarn build:typescript &
yarn build:contracts &
yarn build:contracts
yarn build:contracts:ovm
wait
......@@ -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',
......
......@@ -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"
}
}
......@@ -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) {}
}
}
})
......@@ -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
}
}
......
......@@ -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==
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment