From 20b38df84f2361968e7c13827a98f51e762466ae Mon Sep 17 00:00:00 2001 From: andrejrakic Date: Sat, 12 Feb 2022 00:36:37 +0100 Subject: [PATCH 01/11] Bump @chainlink/contracts version to 0.4.0 --- package.json | 2 +- yarn.lock | 9 +++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index 0a07dfffa..2d5332535 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,7 @@ "dependencies": { "@appliedblockchain/chainlink-contracts": "0.0.4", "@appliedblockchain/chainlink-plugins-fund-link": "0.0.1", - "@chainlink/contracts": "^0.3.1", + "@chainlink/contracts": "^0.4.0", "@chainlink/test-helpers": "^0.0.7-alpha", "@chainlink/token": "^1.1.0", "babel-eslint": "^10.1.0", diff --git a/yarn.lock b/yarn.lock index 9014b10b3..66505771c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -347,10 +347,10 @@ "@truffle/contract" "^4.3.8" ethers "^4.0.45" -"@chainlink/contracts@^0.3.1": - version "0.3.1" - resolved "https://registry.yarnpkg.com/@chainlink/contracts/-/contracts-0.3.1.tgz#a1a2e1b179a6ce6a9b5b16992f6202918110ef5c" - integrity sha512-A8DRvmfNCwLS1iduPPj7wNAZJMe9/ZimMhoHhbbBiq+7Vq/HFjiNcdoQ5NinFdXD5aTsoNUGG5pAYKj7YMpm9A== +"@chainlink/contracts@^0.4.0": + version "0.4.0" + resolved "https://registry.yarnpkg.com/@chainlink/contracts/-/contracts-0.4.0.tgz#4bcfd486d02cdc73047f27904119d0f8cb7291f4" + integrity sha512-yZGeCBd7d+qxfw9r/JxtPzsW2kCc6MorPRZ/tDKnaJI98H99j5P2Fosfehmcwk6wVZlz+0Bp4kS1y480nw3Zow== "@chainlink/test-helpers@0.0.5": version "0.0.5" @@ -503,6 +503,7 @@ tmp "0.0.33" "@eth-optimism/solc-v0.6.12@npm:@eth-optimism/solc@^0.6.12-alpha.1", "@eth-optimism/solc@^0.6.12-alpha.1": + name "@eth-optimism/solc-v0.6.12" version "0.6.12-alpha.1" resolved "https://registry.yarnpkg.com/@eth-optimism/solc/-/solc-0.6.12-alpha.1.tgz#041876f83b34c6afe2f19dfe9626568df6ed8590" integrity sha512-Ky73mo+2iNJs/VTaT751nMeZ7hXns0TBAlffTOxIOsScjAZ/zi/KWsDUo3r89aV2JKXcYAU/bLidxF40MVJeUw== From 8b87b134c61e15a218f4264c1d791064ed0e9bf4 Mon Sep 17 00:00:00 2001 From: Patrick Collins <54278053+PatrickAlphaC@users.noreply.github.com> Date: Wed, 16 Feb 2022 06:39:52 -0700 Subject: [PATCH 02/11] update for yarn and network (#82) --- README.md | 4 +++- deploy/00_Deploy_Mocks.js | 2 +- deploy/01_Deploy_PriceConsumerV3.js | 3 ++- deploy/02_Deploy_APIConsumer.js | 3 ++- deploy/03_Deploy_RandomNumberConsumer.js | 3 ++- deploy/04_Deploy_KeepersCounter.js | 3 ++- hardhat.config.js | 2 +- helper-functions.js | 2 +- helper-hardhat-config.js | 1 + tasks/keepers/read-keepers-counter.js | 2 +- tasks/random-number-consumer/request-random-number.js | 2 +- 11 files changed, 17 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index b8d7fcad3..b71df2357 100644 --- a/README.md +++ b/README.md @@ -56,6 +56,8 @@ It's recommended that you've gone through the [hardhat getting started documenta - `yarn --version` And get an output like: `x.x.x` - You might need to install it with npm +> If you're familiar with `npx` and `npm` instead of `yarn`, you can use `npx` for execution and `npm` for installing dependencies. + ## Quickstart 1. Clone and install dependencies @@ -85,7 +87,7 @@ yarn hardhat test or ``` -npx hardhat test +yarn hardhat test ``` ### Typescript diff --git a/deploy/00_Deploy_Mocks.js b/deploy/00_Deploy_Mocks.js index faf713e32..3de9602f9 100644 --- a/deploy/00_Deploy_Mocks.js +++ b/deploy/00_Deploy_Mocks.js @@ -30,7 +30,7 @@ module.exports = async ({ getNamedAccounts, deployments, getChainId }) => { log("Mocks Deployed!") log("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") log("You are deploying to a local network, you'll need a local network running to interact") - log("Please run `npx hardhat console` to interact with the deployed smart contracts!") + log("Please run `yarn hardhat console` to interact with the deployed smart contracts!") log("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") } } diff --git a/deploy/01_Deploy_PriceConsumerV3.js b/deploy/01_Deploy_PriceConsumerV3.js index 81ea2b59e..783a94e1b 100644 --- a/deploy/01_Deploy_PriceConsumerV3.js +++ b/deploy/01_Deploy_PriceConsumerV3.js @@ -38,7 +38,8 @@ module.exports = async ({ getNamedAccounts, deployments }) => { } log("Run Price Feed contract with command:") - log(`npx hardhat read-price-feed --contract ${priceConsumerV3.address} --network ${network.name}`) + const networkName = network.name == "hardhat" ? "localhost" : network.name + log(`yarn hardhat read-price-feed --contract ${priceConsumerV3.address} --network ${networkName}`) log("----------------------------------------------------") } diff --git a/deploy/02_Deploy_APIConsumer.js b/deploy/02_Deploy_APIConsumer.js index 5742de441..377cd7985 100644 --- a/deploy/02_Deploy_APIConsumer.js +++ b/deploy/02_Deploy_APIConsumer.js @@ -61,7 +61,8 @@ module.exports = async ({ getNamedAccounts, deployments }) => { } log("Run API Consumer contract with following command:") - log(`npx hardhat request-data --contract ${apiConsumer.address} --network ${network.name}`) + const networkName = network.name == "hardhat" ? "localhost" : network.name + log(`yarn hardhat request-data --contract ${apiConsumer.address} --network ${networkName}`) log("----------------------------------------------------") } module.exports.tags = ["all", "api", "main"] diff --git a/deploy/03_Deploy_RandomNumberConsumer.js b/deploy/03_Deploy_RandomNumberConsumer.js index 5f76c3e59..e3a44f9ba 100644 --- a/deploy/03_Deploy_RandomNumberConsumer.js +++ b/deploy/03_Deploy_RandomNumberConsumer.js @@ -63,8 +63,9 @@ module.exports = async ({ getNamedAccounts, deployments }) => { } } log("Then run RandomNumberConsumer contract with the following command") + const networkName = network.name == "hardhat" ? "localhost" : network.name log( - `npx hardhat request-random-number --contract ${randomNumberConsumer.address} --network ${network.name}` + `yarn hardhat request-random-number --contract ${randomNumberConsumer.address} --network ${networkName}` ) log("----------------------------------------------------") } diff --git a/deploy/04_Deploy_KeepersCounter.js b/deploy/04_Deploy_KeepersCounter.js index 9b83515a3..e6b4b8804 100644 --- a/deploy/04_Deploy_KeepersCounter.js +++ b/deploy/04_Deploy_KeepersCounter.js @@ -30,8 +30,9 @@ module.exports = async ({ getNamedAccounts, deployments, getChainId }) => { log( "Head to https://keepers.chain.link/ to register your contract for upkeeps. Then run the following command to track the counter updates: " ) + const networkName = network.name == "hardhat" ? "localhost" : network.name log( - `npx hardhat read-keepers-counter --contract ${keepersCounter.address} --network ${network.name}` + `yarn hardhat read-keepers-counter --contract ${keepersCounter.address} --network ${networkName}` ) log("----------------------------------------------------") } diff --git a/hardhat.config.js b/hardhat.config.js index 1a5c97581..e7866d058 100644 --- a/hardhat.config.js +++ b/hardhat.config.js @@ -78,7 +78,7 @@ module.exports = { }, }, etherscan: { - // npx hardhat verify --network + // yarn hardhat verify --network apiKey: { rinkeby: ETHERSCAN_API_KEY, kovan: ETHERSCAN_API_KEY, diff --git a/helper-functions.js b/helper-functions.js index bb3c9c44b..daf0b87da 100644 --- a/helper-functions.js +++ b/helper-functions.js @@ -32,7 +32,7 @@ const autoFundCheck = async (contractAddr, networkName, linkTokenAddress, additi `Please obtain LINK via the faucet at https://faucets.chain.link/${networkName} then run the following command to fund contract with LINK:` ) console.log( - `npx hardhat fund-link --contract ${contractAddr} --network ${networkName} ${additionalMessage}` + `yarn hardhat fund-link --contract ${contractAddr} --network ${networkName} ${additionalMessage}` ) return false } diff --git a/helper-hardhat-config.js b/helper-hardhat-config.js index cd735c957..5d7e8d032 100644 --- a/helper-hardhat-config.js +++ b/helper-hardhat-config.js @@ -14,6 +14,7 @@ const networkConfig = { jobId: "29fa9aa13bf1468788b7cc4a500a45b8", fundAmount: "1000000000000000000", keepersUpdateInterval: "30", + ethUsdPriceFeed: "0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419", }, 42: { name: "kovan", diff --git a/tasks/keepers/read-keepers-counter.js b/tasks/keepers/read-keepers-counter.js index 85317d8be..6de090574 100644 --- a/tasks/keepers/read-keepers-counter.js +++ b/tasks/keepers/read-keepers-counter.js @@ -7,7 +7,7 @@ task( const contractAddr = taskArgs.contract const networkId = network.name - const KeepersCounterContract = await ethers.getContractFactory("Counter") + const KeepersCounterContract = await ethers.getContractFactory("KeepersCounter") console.log("Reading counter from Keepers contract ", contractAddr, " on network ", networkId) //Get signer information diff --git a/tasks/random-number-consumer/request-random-number.js b/tasks/random-number-consumer/request-random-number.js index 4588848d2..3fa976577 100644 --- a/tasks/random-number-consumer/request-random-number.js +++ b/tasks/random-number-consumer/request-random-number.js @@ -30,7 +30,7 @@ task("request-random-number", "Requests a random number for a Chainlink VRF enab ) console.log("Run the following to read the returned random number:") console.log( - "npx hardhat read-random-number --contract " + contractAddr + " --network " + network.name + "yarn hardhat read-random-number --contract " + contractAddr + " --network " + network.name ) }) From 9946d6bacde30cc417619a1d6be953233436f89b Mon Sep 17 00:00:00 2001 From: andrejrakic Date: Mon, 28 Feb 2022 00:48:58 +0100 Subject: [PATCH 03/11] Add VRF V2, Fuzz Testing, NatSpec, Coverage --- .env.example | 5 +- .gitignore | 4 +- .solcover.js | 3 + README.md | 93 +++++++++++++----- contracts/APIConsumer.sol | 39 +++++--- contracts/KeepersCounter.sol | 16 ++++ contracts/PriceConsumerV3.sol | 18 +++- contracts/RandomNumberConsumer.sol | 57 ----------- contracts/RandomNumberConsumerV2.sol | 96 +++++++++++++++++++ contracts/test/VRFCoordinatorMock.sol | 4 - contracts/test/VRFCoordinatorV2Mock.sol | 4 + .../fuzzing/KeepersCounterEchidnaTest.sol | 12 +++ contracts/test/fuzzing/config.yaml | 14 +++ deploy/00_Deploy_Mocks.js | 12 ++- deploy/03_Deploy_RandomNumberConsumer.js | 47 ++++----- hardhat.config.js | 8 +- helper-hardhat-config.js | 12 +-- package.json | 9 +- .../read-random-number.js | 28 ++++-- .../request-random-number.js | 10 +- test/staging/APIConsumer_int_test.js | 7 +- ....js => RandomNumberConsumerV2_int_test.js} | 39 ++++---- test/unit/RandomNumberConsumerV2_unit_test.js | 45 +++++++++ test/unit/RandomNumberConsumer_unit_test.js | 74 -------------- 24 files changed, 398 insertions(+), 258 deletions(-) create mode 100644 .solcover.js delete mode 100644 contracts/RandomNumberConsumer.sol create mode 100644 contracts/RandomNumberConsumerV2.sol delete mode 100644 contracts/test/VRFCoordinatorMock.sol create mode 100644 contracts/test/VRFCoordinatorV2Mock.sol create mode 100644 contracts/test/fuzzing/KeepersCounterEchidnaTest.sol create mode 100644 contracts/test/fuzzing/config.yaml rename test/staging/{RandomNumberConsumer_int_test.js => RandomNumberConsumerV2_int_test.js} (50%) create mode 100755 test/unit/RandomNumberConsumerV2_unit_test.js delete mode 100755 test/unit/RandomNumberConsumer_unit_test.js diff --git a/.env.example b/.env.example index 9e75a992a..f93700be7 100644 --- a/.env.example +++ b/.env.example @@ -1,8 +1,9 @@ KOVAN_RPC_URL='https://kovan.infura.io/v3/1234567890' -RINKEBY_RPC_URL='https://alchemy.infura.io/v3/1234567890' +RINKEBY_RPC_URL='https://rinkeby.infura.io/v3/1234567890' POLYGON_MAINNET_RPC_URL='https://rpc-mainnet.maticvigil.com' PRIVATE_KEY='abcdefg' ALCHEMY_MAINNET_RPC_URL="https://eth-mainnet.alchemyapi.io/v2/your-api-key" REPORT_GAS=true COINMARKETCAP_API_KEY="YOUR_KEY" -AUTO_FUND=true \ No newline at end of file +AUTO_FUND=true +VRF_SUBSCRIPTION_ID=YOUR_SUBSCRIPTION_ID \ No newline at end of file diff --git a/.gitignore b/.gitignore index 0edd52575..61cbe1cf7 100644 --- a/.gitignore +++ b/.gitignore @@ -98,4 +98,6 @@ lint/outputs/ lint/tmp/ # lint/reports/ -gas-report.txt \ No newline at end of file +gas-report.txt + +contracts/test/fuzzing/crytic-export \ No newline at end of file diff --git a/.solcover.js b/.solcover.js new file mode 100644 index 000000000..227654225 --- /dev/null +++ b/.solcover.js @@ -0,0 +1,3 @@ +module.exports = { + skipFiles: ['test/fuzzing/KeepersCounterEchidnaTest.sol', 'test/LinkToken.sol', 'test/MockOracle.sol', 'test/MockV3Aggregator.sol', 'test/VRFCoordinatorV2Mock.sol'], +}; \ No newline at end of file diff --git a/README.md b/README.md index b71df2357..e5e088fe1 100644 --- a/README.md +++ b/README.md @@ -6,16 +6,16 @@


-- [Chainlink Hardhat Box](#chainlink-hardhat-box) +- [Chainlink Hardhat Starter Kit](#chainlink-hardhat-starter-kit) - [Getting Started](#getting-started) - [Requirements](#requirements) - [Quickstart](#quickstart) - [Typescript](#typescript) -- [Useage](#useage) +- [Usage](#usage) - [Deploying Contracts](#deploying-contracts) - [Run a Local Network](#run-a-local-network) - [Using a Testnet or Live Network (like Mainnet or Polygon)](#using-a-testnet-or-live-network-like-mainnet-or-polygon) - - [Kovan Ethereum Testnet Setup](#kovan-ethereum-testnet-setup) + - [Rinkeby Ethereum Testnet Setup](#rinkeby-ethereum-testnet-setup) - [Forking](#forking) - [Auto-Funding](#auto-funding) - [Test](#test) @@ -29,11 +29,13 @@ - [Linting](#linting) - [Code Formating](#code-formating) - [Estimaging Gas](#estimaging-gas) +- [Code Coverage](#code-coverage) +- [Fuzzing](#fuzzing) - [Contributing](#contributing) - [Thank You!](#thank-you) - [Resources](#resources) -# Chainlink Hardhat Box +# Chainlink Hardhat Starter Kit Implementation of the following 4 Chainlink features using the [Hardhat](https://hardhat.org/) development environment: - [Chainlink Price Feeds](https://docs.chain.link/docs/using-chainlink-reference-contracts) - [Chainlink VRF](https://docs.chain.link/docs/chainlink-vrf) @@ -99,7 +101,7 @@ git checkout typescript yarn ``` -# Useage +# Usage If you run `yarn hardhat --help` you'll get an output of all the tasks you can run. @@ -139,15 +141,15 @@ To interact with a live or test network, you'll need: 2. A Private Key 3. ETH & LINK token (either testnet or real) -Let's look at an example of setting these up using the Kovan testnet. +Let's look at an example of setting these up using the Rinkeby testnet. -### Kovan Ethereum Testnet Setup +### Rinkeby Ethereum Testnet Setup First, we will need to set environment variables. We can do so by setting them in our `.env` file (create it if it's not there). You can also read more about [environment variables](https://www.twilio.com/blog/2017/01/how-to-set-environment-variables.html) from the linked twilio blog. You'll find a sample of what this file will look like in `.env.example` > IMPORTANT: MAKE SURE YOU'D DONT EXPOSE THE KEYS YOU PUT IN THIS `.env` FILE. By that, I mean don't push them to a public repo, and please try to keep them keys you use in development not associated with any real funds. -1. Set your `KOVAN_RPC_URL` [environment variable.](https://www.twilio.com/blog/2017/01/how-to-set-environment-variables.html) +1. Set your `RINKEBY_RPC_URL` [environment variable.](https://www.twilio.com/blog/2017/01/how-to-set-environment-variables.html) You can get one for free from [Alchmey](https://www.alchemy.com/), [Infura](https://infura.io/), or [Moralis](https://moralis.io/speedy-nodes/). This is your connection to the blockchain. @@ -163,12 +165,12 @@ Don't commit and push any changes to .env files that may contain sensitive infor `.env` example: ``` -KOVAN_RPC_URL='www.infura.io/asdfadsfafdadf' +RINKEBY_RPC_URL='www.infura.io/asdfadsfafdadf' PRIVATE_KEY='abcdef' ``` `bash` example ``` -export KOVAN_RPC_URL='www.infura.io/asdfadsfafdadf' +export RINKEBY_RPC_URL='www.infura.io/asdfadsfafdadf' export PRIVATE_KEY='abcdef' ``` @@ -176,40 +178,48 @@ export PRIVATE_KEY='abcdef' For other networks like mainnet and polygon, you can use different environment variables for your RPC URL and your private key. See the `hardhat.config.js` to learn more. -3. Get some Kovan Testnet ETH and LINK +3. Get some Rinkeby Testnet ETH and LINK Head over to the [Chainlink faucets](https://faucets.chain.link/) and get some ETH and LINK. Please follow [the chainlink documentation](https://docs.chain.link/docs/acquire-link/) if unfamiliar. -4. Running commands +4. Create VRF V2 subscription -You should now be all setup! You can run any command and just pass the `--network kovan` now! +Head over to [VRF Subscription Page](https://vrf.chain.link/rinkeby) and create the new subscription. Save your subscription ID and put it in `.env` file as `VRF_SUBSCRIPTION_ID` + +5. Running commands + +You should now be all setup! You can run any command and just pass the `--network rinkeby` now! To deploy contracts: ``` -yarn hardhat deploy --network kovan +yarn hardhat deploy --network rinkeby ``` To run staging testnet tests ``` -yarn hardhat test --network kovan +yarn hardhat test --network rinkeby ``` ## Forking If you'd like to run tests or on a network that is a [forked network](https://hardhat.org/hardhat-network/guides/mainnet-forking.html) 1. Set a `MAINNET_RPC_URL` environment variable that connects to the mainnet. -2. Uncomment the section in your `hardhat.config.js` +2. Choose a block number to select a state of the network you are forking. If ignored, it will use the latest block each time which can lead to test inconsistency. +3. Set `enabled` flag to `true`/`false` to enable/disable forking feature +4. Uncomment the section in your `hardhat.config.js` ``` // forking: { - // url: MAINNET_RPC_URL + // url: MAINNET_RPC_URL, + // blockNumber: "your forking block number goes here", + // enabled: false, // } ``` ## Auto-Funding -This Starter Kit is configured by default to attempt to auto-fund any newly deployed contract that uses Any-API or Chainlink VRF, to save having to manually fund them after each deployment. The amount in LINK to send as part of this process can be modified in the [Starter Kit Config](helper-hardhat-config.js), and are configurable per network. +This Starter Kit is configured by default to attempt to auto-fund any newly deployed contract that uses Any-API, to save having to manually fund them after each deployment. The amount in LINK to send as part of this process can be modified in the [Starter Kit Config](helper-hardhat-config.js), and are configurable per network. | Parameter | Description | Default Value | | ---------- | :------------------------------------------------ | :------------ | @@ -240,13 +250,12 @@ yarn test-integration or ``` -yarn hardhat test --network kovan +yarn hardhat test --network rinkeby ``` # Interacting with Deployed Contracts -After deploying your contracts. -The deployment output will give you the contract addresses as they are deployed. You can then use these contract addresses in conjunction with Hardhat tasks to perform operations on each contract. +After deploying your contracts, the deployment output will give you the contract addresses as they are deployed. You can then use these contract addresses in conjunction with Hardhat tasks to perform operations on each contract. ## Chainlink Price Feeds @@ -276,13 +285,19 @@ yarn hardhat read-data --contract insert-contract-address-here --network network ## VRF Get a random number -The VRFConsumer contract has two tasks, one to request a random number, and one to read the result of the random number request. This contract needs to be funded with link first: +The VRFConsumer contract has two tasks, one to request a random number, and one to read the result of the random number request. To start, go to [VRF Subscription Page](https://vrf.chain.link/rinkeby) and create the new subscription. Save your subscription ID and put it in `.env` file as `VRF_SUBSCRIPTION_ID`: ```bash -yarn hardhat fund-link --contract insert-contract-address-here --network network +VRF_SUBSCRIPTION_ID=subscription_id +``` + +Then, deploy your VRF V2 contract consumer to the network of your recent subscription using subscription id as constructor argument. + +```bash +yarn hardhat deploy --network network ``` -Once it's funded, you can perform a VRF request with the request-random-number task: +Finally, you need to go to your subscription page one more time and add the address of deployed contract as a new consumer. Once that's done, you can perform a VRF request with the request-random-number task: ```bash yarn hardhat request-random-number --contract insert-contract-address-here --network network @@ -312,7 +327,7 @@ yarn hardhat verify --network Resources->Advanced->Memory_). + +To start Echidna instance run + +``` +yarn fuzzing +``` + +If you are using it for the first time, you will need to wait for Docker to download [eth-security-toolbox](https://hub.docker.com/r/trailofbits/eth-security-toolbox) image for us. + +To start Fuzzing run +``` +echidna-test /src/contracts/test/fuzzing/KeepersCounterEchidnaTest.sol --contract KeepersCounterEchidnaTest --config /src/contracts/test/fuzzing/config.yaml +``` + +To exit Echidna type +```bash +exit +``` # Contributing diff --git a/contracts/APIConsumer.sol b/contracts/APIConsumer.sol index a464e6d54..2d241c8fc 100644 --- a/contracts/APIConsumer.sol +++ b/contracts/APIConsumer.sol @@ -1,25 +1,32 @@ +// SPDX-License-Identifier: MIT pragma solidity ^0.8.7; import "@chainlink/contracts/src/v0.8/ChainlinkClient.sol"; /** - * THIS IS AN EXAMPLE CONTRACT WHICH USES HARDCODED VALUES FOR CLARITY. - * PLEASE DO NOT USE THIS CODE IN PRODUCTION. + * @title The APIConsumer contract + * @notice An API Consumer contract that makes GET requests to obtain 24h trading volume of ETH in USD */ contract APIConsumer is ChainlinkClient { using Chainlink for Chainlink.Request; uint256 public volume; - address private oracle; - bytes32 private jobId; - uint256 private fee; + address private immutable oracle; + bytes32 private immutable jobId; + uint256 private immutable fee; event DataFullfilled(uint256 volume); /** + * @notice Executes once when a contract is created to initialize state variables + * + * @param _oracle - address of the specific Chainlink node that a contract makes an API call from + * @param _jobId - specific job for :_oracle: to run; each job is unique and returns different types of data + * @param _fee - node operator price per API call / data request + * @param _link - LINK token address on the corresponding network + * * Network: Kovan - * Oracle: 0xc57B33452b4F7BB189bB5AfaE9cc4aBa1f7a4FD8 (Chainlink Devrel - * Node) + * Oracle: 0xc57B33452b4F7BB189bB5AfaE9cc4aBa1f7a4FD8 (Chainlink Devrel Node) * Job ID: d5270d1c311941d0b08bead21fea7747 * Fee: 0.1 LINK */ @@ -34,17 +41,16 @@ contract APIConsumer is ChainlinkClient { } else { setChainlinkToken(_link); } - // oracle = 0x2f90A6D021db21e1B2A077c5a37B3C7E75D15b7e; - // jobId = "29fa9aa13bf1468788b7cc4a500a45b8"; - // fee = 0.1 * 10 ** 18; // 0.1 LINK oracle = _oracle; jobId = _jobId; fee = _fee; } /** - * Create a Chainlink request to retrieve API response, find the target + * @notice Creates a Chainlink request to retrieve API response, find the target * data, then multiply by 1000000000000000000 (to remove decimal places from data). + * + * @return requestId - id of the request */ function requestVolumeData() public returns (bytes32 requestId) { Chainlink.Request memory request = buildChainlinkRequest( @@ -77,7 +83,10 @@ contract APIConsumer is ChainlinkClient { } /** - * Receive the response in the form of uint256 + * @notice Receives the response in the form of uint256 + * + * @param _requestId - id of the request + * @param _volume - response; requested 24h trading volume of ETH in USD */ function fulfill(bytes32 _requestId, uint256 _volume) public @@ -86,4 +95,10 @@ contract APIConsumer is ChainlinkClient { volume = _volume; emit DataFullfilled(volume); } + + /** + * @notice Witdraws LINK from the contract + * @dev Implement a withdraw function to avoid locking your LINK in the contract + */ + function withdrawLink() external {} } diff --git a/contracts/KeepersCounter.sol b/contracts/KeepersCounter.sol index 70d6ccff8..fa7104b10 100644 --- a/contracts/KeepersCounter.sol +++ b/contracts/KeepersCounter.sol @@ -1,7 +1,12 @@ +// SPDX-License-Identifier: MIT pragma solidity ^0.8.7; import "@chainlink/contracts/src/v0.8/interfaces/KeeperCompatibleInterface.sol"; +/** + * @title The Counter contract + * @notice A keeper-compatible contract that increments counter variable at fixed time intervals + */ contract KeepersCounter is KeeperCompatibleInterface { /** * Public counter variable @@ -14,6 +19,11 @@ contract KeepersCounter is KeeperCompatibleInterface { uint256 public immutable interval; uint256 public lastTimeStamp; + /** + * @notice Executes once when a contract is created to initialize state variables + * + * @param updateInterval - Period of time between two counter increments expressed as UNIX timestamp value + */ constructor(uint256 updateInterval) { interval = updateInterval; lastTimeStamp = block.timestamp; @@ -21,6 +31,9 @@ contract KeepersCounter is KeeperCompatibleInterface { counter = 0; } + /** + * @notice Checks if the contract requires work to be done + */ function checkUpkeep( bytes memory /* checkData */ ) @@ -35,6 +48,9 @@ contract KeepersCounter is KeeperCompatibleInterface { // We don't use the checkData in this example. The checkData is defined when the Upkeep was registered. } + /** + * @notice Performs the work on the contract, if instructed by :checkUpkeep(): + */ function performUpkeep( bytes calldata /* performData */ ) external override { diff --git a/contracts/PriceConsumerV3.sol b/contracts/PriceConsumerV3.sol index 755d1739b..06f45f2ee 100644 --- a/contracts/PriceConsumerV3.sol +++ b/contracts/PriceConsumerV3.sol @@ -1,11 +1,20 @@ +// SPDX-License-Identifier: MIT pragma solidity ^0.8.7; import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol"; +/** + * @title The PriceConsumerV3 contract + * @notice Acontract that returns latest price from Chainlink Price Feeds + */ contract PriceConsumerV3 { AggregatorV3Interface internal priceFeed; /** + * @notice Executes once when a contract is created to initialize state variables + * + * @param _priceFeed - Price Feed Address + * * Network: Kovan * Aggregator: ETH/USD * Address: 0x9326BFA02ADD2366b30bacB125260Af641031331 @@ -15,7 +24,9 @@ contract PriceConsumerV3 { } /** - * Returns the latest price + * @notice Returns the latest price + * + * @return latest price */ function getLatestPrice() public view returns (int256) { ( @@ -28,6 +39,11 @@ contract PriceConsumerV3 { return price; } + /** + * @notice Returns the Price Feed address + * + * @return Price Feed address + */ function getPriceFeed() public view returns (AggregatorV3Interface) { return priceFeed; } diff --git a/contracts/RandomNumberConsumer.sol b/contracts/RandomNumberConsumer.sol deleted file mode 100644 index 66d477813..000000000 --- a/contracts/RandomNumberConsumer.sol +++ /dev/null @@ -1,57 +0,0 @@ -pragma solidity ^0.8.7; - -import "@chainlink/contracts/src/v0.8/VRFConsumerBase.sol"; - -/** - * THIS IS AN EXAMPLE CONTRACT WHICH USES HARDCODED VALUES FOR CLARITY. - * PLEASE DO NOT USE THIS CODE IN PRODUCTION. - */ -contract RandomNumberConsumer is VRFConsumerBase { - bytes32 internal keyHash; - uint256 internal fee; - - uint256 public randomResult; - event ReturnedRandomness(uint256 randomNumber); - - /** - * Constructor inherits VRFConsumerBase - * - * Network: Kovan - * Chainlink VRF Coordinator address: 0xdD3782915140c8f3b190B5D67eAc6dc5760C46E9 - * LINK token address: 0xa36085F69e2889c224210F603D836748e7dC0088 - * Key Hash: 0x6c3699283bda56ad74f6b855546325b68d482e983852a7a82979cc4807b641f4 - */ - constructor( - address _vrfCoordinator, - address _link, - bytes32 _keyHash, - uint256 _fee - ) - public - VRFConsumerBase( - _vrfCoordinator, // VRF Coordinator - _link // LINK Token - ) - { - keyHash = _keyHash; - fee = _fee; - } - - /** - * Requests randomness - */ - function getRandomNumber() public returns (bytes32 requestId) { - require(LINK.balanceOf(address(this)) >= fee, "Not enough LINK - fill contract with faucet"); - return requestRandomness(keyHash, fee); - } - - /** - * Callback function used by VRF Coordinator - */ - function fulfillRandomness(bytes32 requestId, uint256 randomness) internal override { - randomResult = randomness; - emit ReturnedRandomness(randomResult); - } - - // function withdrawLink() external {} - Implement a withdraw function to avoid locking your LINK in the contract -} diff --git a/contracts/RandomNumberConsumerV2.sol b/contracts/RandomNumberConsumerV2.sol new file mode 100644 index 000000000..720125109 --- /dev/null +++ b/contracts/RandomNumberConsumerV2.sol @@ -0,0 +1,96 @@ +// SPDX-License-Identifier: MIT +// An example of a consumer contract that relies on a subscription for funding. +pragma solidity ^0.8.7; + +import "@chainlink/contracts/src/v0.8/interfaces/LinkTokenInterface.sol"; +import "@chainlink/contracts/src/v0.8/interfaces/VRFCoordinatorV2Interface.sol"; +import "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol"; + +/** + * @title The RandomNumberConsumerV2 contract + * @notice A contract that gets random values from Chainlink VRF V2 + */ +contract RandomNumberConsumerV2 is VRFConsumerBaseV2 { + VRFCoordinatorV2Interface COORDINATOR; + LinkTokenInterface LINKTOKEN; + + // Your subscription ID. + uint64 s_subscriptionId; + + // The gas lane to use, which specifies the maximum gas price to bump to. + // For a list of available gas lanes on each network, + // see https://docs.chain.link/docs/vrf-contracts/#configurations + bytes32 s_keyHash; + + // Depends on the number of requested values that you want sent to the + // fulfillRandomWords() function. Storing each word costs about 20,000 gas, + // so 100,000 is a safe default for this example contract. Test and adjust + // this limit based on the network that you select, the size of the request, + // and the processing of the callback request in the fulfillRandomWords() + // function. + uint32 s_callbackGasLimit = 100000; + + // The default is 3, but you can set this higher. + uint16 s_requestConfirmations = 3; + + // For this example, retrieve 2 random values in one request. + // Cannot exceed VRFCoordinatorV2.MAX_NUM_WORDS. + uint32 s_numWords = 2; + + uint256[] public s_randomWords; + uint256 public s_requestId; + address s_owner; + + event ReturnedRandomness(uint256[] randomWords); + + /** + * @notice Constructor inherits VRFConsumerBaseV2 + * + * @param subscriptionId - the subscription ID that this contract uses for funding requests + * @param vrfCoordinator - coordinator, check https://docs.chain.link/docs/vrf-contracts/#configurations + * @param keyHash - the gas lane to use, which specifies the maximum gas price to bump to + */ + constructor( + uint64 subscriptionId, + address vrfCoordinator, + address link, + bytes32 keyHash + ) VRFConsumerBaseV2(vrfCoordinator) { + COORDINATOR = VRFCoordinatorV2Interface(vrfCoordinator); + LINKTOKEN = LinkTokenInterface(link); + s_keyHash = keyHash; + s_owner = msg.sender; + s_subscriptionId = subscriptionId; + } + + /** + * @notice Requests randomness + * Assumes the subscription is funded sufficiently; "Words" refers to unit of data in Computer Science + */ + function requestRandomWords() external onlyOwner { + // Will revert if subscription is not set and funded. + s_requestId = COORDINATOR.requestRandomWords( + s_keyHash, + s_subscriptionId, + s_requestConfirmations, + s_callbackGasLimit, + s_numWords + ); + } + + /** + * @notice Callback function used by VRF Coordinator + * + * @param requestId - id of the request + * @param randomWords - array of random results from VRF Coordinator + */ + function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal override { + s_randomWords = randomWords; + emit ReturnedRandomness(randomWords); + } + + modifier onlyOwner() { + require(msg.sender == s_owner); + _; + } +} diff --git a/contracts/test/VRFCoordinatorMock.sol b/contracts/test/VRFCoordinatorMock.sol deleted file mode 100644 index ab122bbf7..000000000 --- a/contracts/test/VRFCoordinatorMock.sol +++ /dev/null @@ -1,4 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.6.0; - -import "@chainlink/contracts/src/v0.6/tests/VRFCoordinatorMock.sol"; diff --git a/contracts/test/VRFCoordinatorV2Mock.sol b/contracts/test/VRFCoordinatorV2Mock.sol new file mode 100644 index 000000000..11c46e973 --- /dev/null +++ b/contracts/test/VRFCoordinatorV2Mock.sol @@ -0,0 +1,4 @@ +//SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "@chainlink/contracts/src/v0.8/mocks/VRFCoordinatorV2Mock.sol"; diff --git a/contracts/test/fuzzing/KeepersCounterEchidnaTest.sol b/contracts/test/fuzzing/KeepersCounterEchidnaTest.sol new file mode 100644 index 000000000..57467bc9f --- /dev/null +++ b/contracts/test/fuzzing/KeepersCounterEchidnaTest.sol @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.7; + +import "../../KeepersCounter.sol"; + +contract KeepersCounterEchidnaTest is KeepersCounter { + constructor() KeepersCounter(8 days) {} + + function echidna_test_perform_upkeep_gate() public view returns (bool) { + return counter == 0; + } +} diff --git a/contracts/test/fuzzing/config.yaml b/contracts/test/fuzzing/config.yaml new file mode 100644 index 000000000..d4f9417f2 --- /dev/null +++ b/contracts/test/fuzzing/config.yaml @@ -0,0 +1,14 @@ +# testLimit is the number of test sequences to run; default is 50000 +testLimit: 10000 +# maximum time between generated txs; default is one week +maxTimeDelay: 0 +# maximum number of blocks elapsed between generated txs; default is expected increment in one week +maxBlockDelay: 60480 +# additional arguments to use in crytic-compile for the compilation of the contract to test. +cryticArgs: + [ + "--solc-remaps", + "@chainlink/contracts=/src/node_modules/@chainlink/contracts", + "--solc-args", + "--allow-paths /src/contracts", + ] diff --git a/deploy/00_Deploy_Mocks.js b/deploy/00_Deploy_Mocks.js index 3de9602f9..2faab487d 100644 --- a/deploy/00_Deploy_Mocks.js +++ b/deploy/00_Deploy_Mocks.js @@ -2,6 +2,7 @@ const { getNamedAccounts, deployments, network } = require("hardhat") const DECIMALS = "18" const INITIAL_PRICE = "200000000000000000000" +const POINT_ONE_LINK = "100000000000000000" module.exports = async ({ getNamedAccounts, deployments, getChainId }) => { const { deploy, log } = deployments @@ -17,10 +18,13 @@ module.exports = async ({ getNamedAccounts, deployments, getChainId }) => { log: true, args: [DECIMALS, INITIAL_PRICE], }) - await deploy("VRFCoordinatorMock", { + await deploy("VRFCoordinatorV2Mock", { from: deployer, log: true, - args: [linkToken.address], + args: [ + POINT_ONE_LINK, + 1e9, // 0.000000001 LINK per gas + ], }) await deploy("MockOracle", { from: deployer, @@ -28,10 +32,10 @@ module.exports = async ({ getNamedAccounts, deployments, getChainId }) => { args: [linkToken.address], }) log("Mocks Deployed!") - log("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") + log("----------------------------------------------------") log("You are deploying to a local network, you'll need a local network running to interact") log("Please run `yarn hardhat console` to interact with the deployed smart contracts!") - log("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!") + log("----------------------------------------------------") } } module.exports.tags = ["all", "mocks", "main"] diff --git a/deploy/03_Deploy_RandomNumberConsumer.js b/deploy/03_Deploy_RandomNumberConsumer.js index e3a44f9ba..706ddb942 100644 --- a/deploy/03_Deploy_RandomNumberConsumer.js +++ b/deploy/03_Deploy_RandomNumberConsumer.js @@ -1,10 +1,10 @@ -const { getNamedAccounts, deployments, network } = require("hardhat") +const { network } = require("hardhat") const { networkConfig, developmentChains, VERIFICATION_BLOCK_CONFIRMATIONS, } = require("../helper-hardhat-config") -const { autoFundCheck, verify } = require("../helper-functions") +const { verify } = require("../helper-functions") module.exports = async ({ getNamedAccounts, deployments }) => { const { deploy, get, log } = deployments @@ -12,26 +12,30 @@ module.exports = async ({ getNamedAccounts, deployments }) => { const chainId = network.config.chainId let linkTokenAddress let vrfCoordinatorAddress - let additionalMessage = "" + let subscriptionId if (chainId == 31337) { linkToken = await get("LinkToken") - VRFCoordinatorMock = await get("VRFCoordinatorMock") + VRFCoordinatorV2Mock = await ethers.getContract("VRFCoordinatorV2Mock") + + vrfCoordinatorAddress = VRFCoordinatorV2Mock.address linkTokenAddress = linkToken.address - vrfCoordinatorAddress = VRFCoordinatorMock.address - additionalMessage = " --linkaddress " + linkTokenAddress + + subscriptionId = await VRFCoordinatorV2Mock.callStatic.createSubscription() + const fundAmount = networkConfig[chainId]["fundAmount"] + await VRFCoordinatorV2Mock.createSubscription() + await VRFCoordinatorV2Mock.fundSubscription(subscriptionId, fundAmount) } else { + subscriptionId = process.env.VRF_SUBSCRIPTION_ID linkTokenAddress = networkConfig[chainId]["linkToken"] vrfCoordinatorAddress = networkConfig[chainId]["vrfCoordinator"] } const keyHash = networkConfig[chainId]["keyHash"] - const fee = networkConfig[chainId]["fee"] - const waitBlockConfirmations = developmentChains.includes(network.name) ? 1 : VERIFICATION_BLOCK_CONFIRMATIONS - const args = [vrfCoordinatorAddress, linkTokenAddress, keyHash, fee] - const randomNumberConsumer = await deploy("RandomNumberConsumer", { + const args = [subscriptionId, vrfCoordinatorAddress, linkTokenAddress, keyHash] + const randomNumberConsumerV2 = await deploy("RandomNumberConsumerV2", { from: deployer, args: args, log: true, @@ -40,32 +44,13 @@ module.exports = async ({ getNamedAccounts, deployments }) => { if (!developmentChains.includes(network.name) && process.env.ETHERSCAN_API_KEY) { log("Verifying...") - await verify(randomNumberConsumer.address, args) + await verify(randomNumberConsumerV2.address, args) } - // Checking for funding... - if (networkConfig.fundAmount > 0) { - log("Funding with LINK...") - if ( - await autoFundCheck( - randomNumberConsumer.address, - network.name, - linkTokenAddress, - additionalMessage - ) - ) { - await hre.run("fund-link", { - contract: randomNumberConsumer.address, - linkaddress: linkTokenAddress, - }) - } else { - log("Contract already has LINK!") - } - } log("Then run RandomNumberConsumer contract with the following command") const networkName = network.name == "hardhat" ? "localhost" : network.name log( - `yarn hardhat request-random-number --contract ${randomNumberConsumer.address} --network ${networkName}` + `yarn hardhat request-random-number --contract ${randomNumberConsumerV2.address} --network ${networkName}` ) log("----------------------------------------------------") } diff --git a/hardhat.config.js b/hardhat.config.js index e7866d058..6444137c6 100644 --- a/hardhat.config.js +++ b/hardhat.config.js @@ -34,10 +34,12 @@ module.exports = { defaultNetwork: "hardhat", networks: { hardhat: { - // // If you want to do some forking, uncomment this + // If you want to do some forking, uncomment this and set `enabled` to true // forking: { - // url: MAINNET_RPC_URL - // } + // url: MAINNET_RPC_URL, + // blockNumber: "your forking block number goes here", + // enabled: false, + // }, chainId: 31337, }, localhost: { diff --git a/helper-hardhat-config.js b/helper-hardhat-config.js index 5d7e8d032..996b5d60e 100644 --- a/helper-hardhat-config.js +++ b/helper-hardhat-config.js @@ -2,7 +2,7 @@ const networkConfig = { default: { name: "hardhat", fee: "100000000000000000", - keyHash: "0x6c3699283bda56ad74f6b855546325b68d482e983852a7a82979cc4807b641f4", + keyHash: "0xd89b2bf150e3b9e13446986e571fb9cab24b13cea0a43ea20a6049a85cc807cc", jobId: "29fa9aa13bf1468788b7cc4a500a45b8", fundAmount: "1000000000000000000", keepersUpdateInterval: "30", @@ -10,7 +10,7 @@ const networkConfig = { 31337: { name: "localhost", fee: "100000000000000000", - keyHash: "0x6c3699283bda56ad74f6b855546325b68d482e983852a7a82979cc4807b641f4", + keyHash: "0xd89b2bf150e3b9e13446986e571fb9cab24b13cea0a43ea20a6049a85cc807cc", jobId: "29fa9aa13bf1468788b7cc4a500a45b8", fundAmount: "1000000000000000000", keepersUpdateInterval: "30", @@ -20,8 +20,6 @@ const networkConfig = { name: "kovan", linkToken: "0xa36085F69e2889c224210F603D836748e7dC0088", ethUsdPriceFeed: "0x9326BFA02ADD2366b30bacB125260Af641031331", - keyHash: "0x6c3699283bda56ad74f6b855546325b68d482e983852a7a82979cc4807b641f4", - vrfCoordinator: "0xdD3782915140c8f3b190B5D67eAc6dc5760C46E9", oracle: "0xc57b33452b4f7bb189bb5afae9cc4aba1f7a4fd8", jobId: "d5270d1c311941d0b08bead21fea7747", fee: "100000000000000000", @@ -32,8 +30,8 @@ const networkConfig = { name: "rinkeby", linkToken: "0x01be23585060835e02b77ef475b0cc51aa1e0709", ethUsdPriceFeed: "0x8A753747A1Fa494EC906cE90E9f37563A8AF630e", - keyHash: "0x2ed0feb3e7fd2022120aa84fab1945545a9f2ffc9076fd6156fa96eaff4c1311", - vrfCoordinator: "0xb3dCcb4Cf7a26f6cf6B120Cf5A73875B7BBc655B", + keyHash: "0xd89b2bf150e3b9e13446986e571fb9cab24b13cea0a43ea20a6049a85cc807cc", + vrfCoordinator: "0x6168499c0cFfCaCD319c818142124B7A15E857ab", oracle: "0xc57b33452b4f7bb189bb5afae9cc4aba1f7a4fd8", jobId: "6b88e0402e5d415eb946e528b8e0c7ba", fee: "100000000000000000", @@ -55,8 +53,6 @@ const networkConfig = { name: "polygon", linkToken: "0xb0897686c545045afc77cf20ec7a532e3120e0f1", ethUsdPriceFeed: "0xF9680D99D6C9589e2a93a78A04A279e509205945", - keyHash: "0xf86195cf7690c55907b2b611ebb7343a6f649bff128701cc542f0569e2c549da", - vrfCoordinator: "0x3d2341ADb2D31f1c5530cDC622016af293177AE0", oracle: "0x0a31078cd57d23bf9e8e8f1ba78356ca2090569e", jobId: "12b86114fa9e46bab3ca436f88e1a912", fee: "100000000000000", diff --git a/package.json b/package.json index 2d5332535..dd88f5194 100644 --- a/package.json +++ b/package.json @@ -3,11 +3,14 @@ "version": "1.0.0", "description": "", "scripts": { - "test": "hardhat test test/unit/PriceConsumerV3_unit_test.js --network hardhat && hardhat test test/unit/APIConsumer_unit_test.js --network hardhat && hardhat test test/unit/RandomNumberConsumer_unit_test.js --network hardhat && hardhat test test/unit/KeepersCounter_unit_test.js --network hardhat", - "test-staging": "hardhat test test/staging/APIConsumer_int_test.js --network kovan && hardhat test test/staging/RandomNumberConsumer_int_test.js --network kovan", + "compile": "hardhat compile", + "test": "hardhat test test/unit/*_test.js --network hardhat", + "test-staging": "hardhat test test/staging/*_test.js --network rinkeby", "lint": "solhint 'contracts/*.sol'", "lint:fix": "solhint 'contracts/**/*.sol' --fix", - "format": "prettier --write ." + "format": "prettier --write .", + "coverage": "hardhat coverage --solcoverjs ./.solcover.js", + "fuzzing": "docker run -it --rm -v $PWD:/src trailofbits/eth-security-toolbox" }, "license": "MIT", "devDependencies": { diff --git a/tasks/random-number-consumer/read-random-number.js b/tasks/random-number-consumer/read-random-number.js index 2f37dd4a5..b6a9e9cad 100644 --- a/tasks/random-number-consumer/read-random-number.js +++ b/tasks/random-number-consumer/read-random-number.js @@ -4,25 +4,33 @@ task("read-random-number", "Reads the random number returned to a contract by Ch const contractAddr = taskArgs.contract const networkId = network.name console.log("Reading data from VRF contract ", contractAddr, " on network ", networkId) - const RandomNumberConsumer = await ethers.getContractFactory("RandomNumberConsumer") + const RandomNumberConsumerV2 = await ethers.getContractFactory("RandomNumberConsumerV2") //Get signer information const accounts = await hre.ethers.getSigners() const signer = accounts[0] //Create connection to API Consumer Contract and call the createRequestTo function - const vrfConsumerContract = new ethers.Contract( + const vrfConsumerContractV2 = new ethers.Contract( contractAddr, - RandomNumberConsumer.interface, + RandomNumberConsumerV2.interface, signer ) - let result = BigInt(await vrfConsumerContract.randomResult()).toString() - console.log("Random Number is: ", result) - if (result == 0 && ["hardhat", "localhost", "ganache"].indexOf(network.name) == 0) { - console.log("You'll either need to wait another minute, or fix something!") - } - if (["hardhat", "localhost", "ganache"].indexOf(network.name) >= 0) { - console.log("You'll have to manually update the value since you're on a local chain!") + + try { + const firstRandomNumber = await vrfConsumerContractV2.s_randomWords(0) + const secondRandomNumber = await vrfConsumerContractV2.s_randomWords(1) + console.log( + `Random Numbers are: ${firstRandomNumber.toString()} and ${secondRandomNumber.toString()}` + ) + } catch (error) { + if (["hardhat", "localhost", "ganache"].includes(network.name)) { + console.log("You'll have to manually update the value since you're on a local chain!") + } else { + console.log( + `Visit https://vrf.chain.link/rinkeby/${process.env.VRF_SUBSCRIPTION_ID} and make sure that your last request fulfillment is there` + ) + } } }) diff --git a/tasks/random-number-consumer/request-random-number.js b/tasks/random-number-consumer/request-random-number.js index 3fa976577..3e3354209 100644 --- a/tasks/random-number-consumer/request-random-number.js +++ b/tasks/random-number-consumer/request-random-number.js @@ -9,24 +9,24 @@ task("request-random-number", "Requests a random number for a Chainlink VRF enab " on network ", networkId ) - const RandomNumberConsumer = await ethers.getContractFactory("RandomNumberConsumer") + const RandomNumberConsumerV2 = await ethers.getContractFactory("RandomNumberConsumerV2") //Get signer information const accounts = await hre.ethers.getSigners() const signer = accounts[0] //Create connection to VRF Contract and call the getRandomNumber function - const vrfConsumerContract = new ethers.Contract( + const vrfConsumerContractV2 = new ethers.Contract( contractAddr, - RandomNumberConsumer.interface, + RandomNumberConsumerV2.interface, signer ) - var result = await vrfConsumerContract.getRandomNumber() + const transaction = await vrfConsumerContractV2.requestRandomWords() console.log( "Contract ", contractAddr, " random number request successfully called. Transaction Hash: ", - result.hash + transaction.hash ) console.log("Run the following to read the returned random number:") console.log( diff --git a/test/staging/APIConsumer_int_test.js b/test/staging/APIConsumer_int_test.js index 3bcf3a3fd..f46899373 100755 --- a/test/staging/APIConsumer_int_test.js +++ b/test/staging/APIConsumer_int_test.js @@ -19,6 +19,10 @@ developmentChains.includes(network.name) } }) + afterEach(async function () { + apiConsumer.removeAllListeners() + }) + // We can't use an arrow functions here because we need to use `this`. So we need // to use `async function() {` as seen. it("Our event should successfully fire on callback", async function () { @@ -39,7 +43,8 @@ developmentChains.includes(network.name) reject(e) } }) - const transaction = await apiConsumer.requestVolumeData() + + await apiConsumer.requestVolumeData() }) }) }) diff --git a/test/staging/RandomNumberConsumer_int_test.js b/test/staging/RandomNumberConsumerV2_int_test.js similarity index 50% rename from test/staging/RandomNumberConsumer_int_test.js rename to test/staging/RandomNumberConsumerV2_int_test.js index 25d96dc86..768082e6f 100755 --- a/test/staging/RandomNumberConsumer_int_test.js +++ b/test/staging/RandomNumberConsumerV2_int_test.js @@ -1,22 +1,18 @@ -const { assert, expect } = require("chai") -const { network, ethers, run } = require("hardhat") -const { developmentChains, networkConfig } = require("../../helper-hardhat-config") -const { autoFundCheck } = require("../../helper-functions") +const { assert } = require("chai") +const { network, ethers } = require("hardhat") +const { developmentChains } = require("../../helper-hardhat-config") developmentChains.includes(network.name) ? describe.skip : describe("RandomNumberConsumer Staging Tests", async function () { - let randomNumberConsumer, linkTokenAddress + let randomNumberConsumerV2 beforeEach(async () => { - randomNumberConsumer = await ethers.getContract("RandomNumberConsumer") - linkTokenAddress = networkConfig[network.config.chainId].linkToken - if (await autoFundCheck(randomNumberConsumer.address, network.name, linkTokenAddress, "")) { - await run("fund-link", { - contract: randomNumberConsumer.address, - linkaddress: linkTokenAddress, - }) - } + randomNumberConsumerV2 = await ethers.getContract("RandomNumberConsumerV2") + }) + + afterEach(async function () { + randomNumberConsumerV2.removeAllListeners() }) // We can't use an arrow functions here because we need to use `this`. So we need @@ -26,20 +22,29 @@ developmentChains.includes(network.name) // we setup a promise so we can wait for our callback from the `once` function await new Promise(async (resolve, reject) => { // setup listener for our event - randomNumberConsumer.once("ReturnedRandomness", async () => { + randomNumberConsumerV2.once("ReturnedRandomness", async () => { console.log("ReturnedRandomness event fired!") - const result = await randomNumberConsumer.randomResult() + const firstRandomNumber = await randomNumberConsumerV2.s_randomWords(0) + const secondRandomNumber = await randomNumberConsumerV2.s_randomWords(1) // assert throws an error if it fails, so we need to wrap // it in a try/catch so that the promise returns event // if it fails. try { - assert(result.gt(0), "The result is more than 0. ") + assert( + firstRandomNumber.gt(ethers.constants.Zero), + "First random number is greather than zero" + ) + assert( + secondRandomNumber.gt(ethers.constants.Zero), + "Second random number is greather than zero" + ) resolve() } catch (e) { reject(e) } }) - const transaction = await randomNumberConsumer.getRandomNumber() + + await randomNumberConsumerV2.requestRandomWords() }) }) }) diff --git a/test/unit/RandomNumberConsumerV2_unit_test.js b/test/unit/RandomNumberConsumerV2_unit_test.js new file mode 100755 index 000000000..cbb7077e5 --- /dev/null +++ b/test/unit/RandomNumberConsumerV2_unit_test.js @@ -0,0 +1,45 @@ +const { assert, expect } = require("chai") +const { network, deployments, ethers } = require("hardhat") +const { developmentChains } = require("../../helper-hardhat-config") + +!developmentChains.includes(network.name) + ? describe.skip + : describe("RandomNumberConsumer Unit Tests", async function () { + let randomNumberConsumerV2, vrfCoordinatorV2Mock + + beforeEach(async () => { + await deployments.fixture(["mocks", "vrf"]) + vrfCoordinatorV2Mock = await ethers.getContract("VRFCoordinatorV2Mock") + randomNumberConsumerV2 = await ethers.getContract("RandomNumberConsumerV2") + }) + + it("Should successfully request a random number", async () => { + await expect(randomNumberConsumerV2.requestRandomWords()).to.emit( + vrfCoordinatorV2Mock, + "RandomWordsRequested" + ) + }) + + it("Should successfully request a random number and get a result", async () => { + await randomNumberConsumerV2.requestRandomWords() + const requestId = await randomNumberConsumerV2.s_requestId() + + // simulate callback from the oracle network + await expect( + vrfCoordinatorV2Mock.fulfillRandomWords(requestId, randomNumberConsumerV2.address) + ).to.emit(randomNumberConsumerV2, "ReturnedRandomness") + + const firstRandomNumber = await randomNumberConsumerV2.s_randomWords(0) + const secondRandomNumber = await randomNumberConsumerV2.s_randomWords(1) + + assert( + firstRandomNumber.gt(ethers.constants.Zero), + "First random number is greather than zero" + ) + + assert( + secondRandomNumber.gt(ethers.constants.Zero), + "Second random number is greather than zero" + ) + }) + }) diff --git a/test/unit/RandomNumberConsumer_unit_test.js b/test/unit/RandomNumberConsumer_unit_test.js deleted file mode 100755 index a529c48d3..000000000 --- a/test/unit/RandomNumberConsumer_unit_test.js +++ /dev/null @@ -1,74 +0,0 @@ -const { assert, expect } = require("chai") -const { network, deployments, ethers } = require("hardhat") -const { developmentChains } = require("../../helper-hardhat-config") - -!developmentChains.includes(network.name) - ? describe.skip - : describe("RandomNumberConsumer Unit Tests", async function () { - let randomNumberConsumer, linkToken, vrfCoordinatorMock - - beforeEach(async () => { - await deployments.fixture(["mocks", "vrf"]) - linkToken = await ethers.getContract("LinkToken") - vrfCoordinatorMock = await ethers.getContract("VRFCoordinatorMock") - linkTokenAddress = linkToken.address - additionalMessage = " --linkaddress " + linkTokenAddress - - randomNumberConsumer = await ethers.getContract("RandomNumberConsumer") - - await hre.run("fund-link", { - contract: randomNumberConsumer.address, - linkaddress: linkTokenAddress, - }) - }) - - it("Should successfully request a random number", async () => { - const transaction = await randomNumberConsumer.getRandomNumber() - const transactionReceipt = await transaction.wait(1) - const requestId = transactionReceipt.events[0].topics[1] - console.log("requestId: ", requestId) - expect(requestId).to.not.be.null - }) - - it("Should successfully request a random number and get a result", async () => { - const transaction = await randomNumberConsumer.getRandomNumber() - const transactionReceipt = await transaction.wait(1) - const requestId = transactionReceipt.events[0].topics[1] - const randomValue = 777 - await vrfCoordinatorMock.callBackWithRandomness( - requestId, - randomValue, - randomNumberConsumer.address - ) - assert.equal((await randomNumberConsumer.randomResult()).toString(), randomValue) - }) - - it("Our event should successfully fire event on callback", async function () { - const randomValue = 777 - // we setup a promise so we can wait for our callback from the `once` function - await new Promise(async (resolve, reject) => { - // setup listener for our event - randomNumberConsumer.once("ReturnedRandomness", async () => { - console.log("ReturnedRandomness event fired!") - const result = await randomNumberConsumer.randomResult() - // assert throws an error if it fails, so we need to wrap - // it in a try/catch so that the promise returns event - // if it fails. - try { - assert.equal(result.toString(), randomValue.toString()) - resolve() - } catch (e) { - reject(e) - } - }) - const transaction = await randomNumberConsumer.getRandomNumber() - const transactionReceipt = await transaction.wait(1) - const requestId = transactionReceipt.events[0].topics[1] - await vrfCoordinatorMock.callBackWithRandomness( - requestId, - randomValue, - randomNumberConsumer.address - ) - }) - }) - }) From f72188f0a1e5dee8189fb1d446d1354dadcc1c8c Mon Sep 17 00:00:00 2001 From: andrejrakic Date: Mon, 28 Feb 2022 01:11:41 +0100 Subject: [PATCH 04/11] Make some storage variables immutable to save gas --- contracts/APIConsumer.sol | 6 +++--- contracts/PriceConsumerV3.sol | 6 +++--- contracts/RandomNumberConsumerV2.sol | 14 +++++++------- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/contracts/APIConsumer.sol b/contracts/APIConsumer.sol index 2d241c8fc..01e651dd3 100644 --- a/contracts/APIConsumer.sol +++ b/contracts/APIConsumer.sol @@ -25,9 +25,9 @@ contract APIConsumer is ChainlinkClient { * @param _fee - node operator price per API call / data request * @param _link - LINK token address on the corresponding network * - * Network: Kovan - * Oracle: 0xc57B33452b4F7BB189bB5AfaE9cc4aBa1f7a4FD8 (Chainlink Devrel Node) - * Job ID: d5270d1c311941d0b08bead21fea7747 + * Network: Rinkeby + * Oracle: 0xc57b33452b4f7bb189bb5afae9cc4aba1f7a4fd8 + * Job ID: 6b88e0402e5d415eb946e528b8e0c7ba * Fee: 0.1 LINK */ constructor( diff --git a/contracts/PriceConsumerV3.sol b/contracts/PriceConsumerV3.sol index 06f45f2ee..d0117d545 100644 --- a/contracts/PriceConsumerV3.sol +++ b/contracts/PriceConsumerV3.sol @@ -8,16 +8,16 @@ import "@chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol"; * @notice Acontract that returns latest price from Chainlink Price Feeds */ contract PriceConsumerV3 { - AggregatorV3Interface internal priceFeed; + AggregatorV3Interface internal immutable priceFeed; /** * @notice Executes once when a contract is created to initialize state variables * * @param _priceFeed - Price Feed Address * - * Network: Kovan + * Network: Rinkeby * Aggregator: ETH/USD - * Address: 0x9326BFA02ADD2366b30bacB125260Af641031331 + * Address: 0x8A753747A1Fa494EC906cE90E9f37563A8AF630e */ constructor(address _priceFeed) public { priceFeed = AggregatorV3Interface(_priceFeed); diff --git a/contracts/RandomNumberConsumerV2.sol b/contracts/RandomNumberConsumerV2.sol index 720125109..72f975f4d 100644 --- a/contracts/RandomNumberConsumerV2.sol +++ b/contracts/RandomNumberConsumerV2.sol @@ -11,16 +11,16 @@ import "@chainlink/contracts/src/v0.8/VRFConsumerBaseV2.sol"; * @notice A contract that gets random values from Chainlink VRF V2 */ contract RandomNumberConsumerV2 is VRFConsumerBaseV2 { - VRFCoordinatorV2Interface COORDINATOR; - LinkTokenInterface LINKTOKEN; + VRFCoordinatorV2Interface immutable COORDINATOR; + LinkTokenInterface immutable LINKTOKEN; // Your subscription ID. - uint64 s_subscriptionId; + uint64 immutable s_subscriptionId; // The gas lane to use, which specifies the maximum gas price to bump to. // For a list of available gas lanes on each network, // see https://docs.chain.link/docs/vrf-contracts/#configurations - bytes32 s_keyHash; + bytes32 immutable s_keyHash; // Depends on the number of requested values that you want sent to the // fulfillRandomWords() function. Storing each word costs about 20,000 gas, @@ -28,14 +28,14 @@ contract RandomNumberConsumerV2 is VRFConsumerBaseV2 { // this limit based on the network that you select, the size of the request, // and the processing of the callback request in the fulfillRandomWords() // function. - uint32 s_callbackGasLimit = 100000; + uint32 immutable s_callbackGasLimit = 100000; // The default is 3, but you can set this higher. - uint16 s_requestConfirmations = 3; + uint16 immutable s_requestConfirmations = 3; // For this example, retrieve 2 random values in one request. // Cannot exceed VRFCoordinatorV2.MAX_NUM_WORDS. - uint32 s_numWords = 2; + uint32 immutable s_numWords = 2; uint256[] public s_randomWords; uint256 public s_requestId; From d7cd0b9e75965188d2ad2b63d11032e850606942 Mon Sep 17 00:00:00 2001 From: armgp Date: Mon, 28 Feb 2022 20:34:04 +0530 Subject: [PATCH 05/11] Readme file, spelling of Usage corrected. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b71df2357..9dcb4511b 100644 --- a/README.md +++ b/README.md @@ -99,7 +99,7 @@ git checkout typescript yarn ``` -# Useage +# Usage If you run `yarn hardhat --help` you'll get an output of all the tasks you can run. From efcf76debbadc4e13fbe564f8d7cfb7770bbec62 Mon Sep 17 00:00:00 2001 From: armgp Date: Mon, 28 Feb 2022 20:49:50 +0530 Subject: [PATCH 06/11] spelling of Usage corrected --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9dcb4511b..01e943ae6 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ - [Requirements](#requirements) - [Quickstart](#quickstart) - [Typescript](#typescript) -- [Useage](#useage) +- [Usage](#usage) - [Deploying Contracts](#deploying-contracts) - [Run a Local Network](#run-a-local-network) - [Using a Testnet or Live Network (like Mainnet or Polygon)](#using-a-testnet-or-live-network-like-mainnet-or-polygon) From 5f0fa88b6edc63dfcf67afd228b270a5a4cb113d Mon Sep 17 00:00:00 2001 From: andrejrakic Date: Wed, 2 Mar 2022 23:52:07 +0100 Subject: [PATCH 07/11] Bump hardhat version to improve testing performance --- README.md | 15 ++- package.json | 2 +- yarn.lock | 372 +++++++++++++++++++++++++++++++++++++++++++-------- 3 files changed, 331 insertions(+), 58 deletions(-) diff --git a/README.md b/README.md index e5e088fe1..ad2d5943d 100644 --- a/README.md +++ b/README.md @@ -236,7 +236,7 @@ To run unit tests: ```bash yarn test ``` -Or +or ``` yarn hardhat test ``` @@ -253,6 +253,19 @@ or yarn hardhat test --network rinkeby ``` +## Performance optimizations + +Since all tests are written in a way to be independent from each other, you can save time by running them in parallel. Make sure that `AUTO_FUND=false` inside `.env` file. There are some limitations with parallel testing, read more about them [here](https://hardhat.org/guides/parallel-tests.html) + +To run tests in parallel: +``` +yarn test --parallel +``` +or +``` +yarn hardhat test --parallel +``` + # Interacting with Deployed Contracts After deploying your contracts, the deployment output will give you the contract addresses as they are deployed. You can then use these contract addresses in conjunction with Hardhat tasks to perform operations on each contract. diff --git a/package.json b/package.json index dd88f5194..eedd188a5 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "chai": "^4.3.4", "ethereum-waffle": "^3.4.0", "ethers": "^5.5.1", - "hardhat": "^2.6.7", + "hardhat": "^2.9.0", "hardhat-contract-sizer": "^2.4.0", "hardhat-deploy": "^0.9.29", "hardhat-gas-reporter": "^1.0.7", diff --git a/yarn.lock b/yarn.lock index 66505771c..d7994f96d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1214,6 +1214,17 @@ resolved "https://registry.yarnpkg.com/@ledgerhq/logs/-/logs-5.50.0.tgz#29c6419e8379d496ab6d0426eadf3c4d100cd186" integrity sha512-swKHYCOZUGyVt4ge0u8a7AwNcA//h4nx5wIi0sruGye1IJ5Cva0GyK9L2/WdX+kWVTKp92ZiEo1df31lrWGPgA== +"@metamask/eth-sig-util@^4.0.0": + version "4.0.0" + resolved "https://registry.yarnpkg.com/@metamask/eth-sig-util/-/eth-sig-util-4.0.0.tgz#11553ba06de0d1352332c1bde28c8edd00e0dcf6" + integrity sha512-LczOjjxY4A7XYloxzyxJIHONELmUxVZncpOLoClpEcTiebiVdM46KRPYXGuULro9oNNR2xdVx3yoKiQjdfWmoA== + dependencies: + ethereumjs-abi "^0.6.8" + ethereumjs-util "^6.2.1" + ethjs-util "^0.1.6" + tweetnacl "^1.0.3" + tweetnacl-util "^0.15.1" + "@nodelib/fs.scandir@2.1.5": version "2.1.5" resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" @@ -1430,6 +1441,13 @@ dependencies: antlr4ts "^0.5.0-alpha.4" +"@solidity-parser/parser@^0.14.1": + version "0.14.1" + resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.14.1.tgz#179afb29f4e295a77cc141151f26b3848abc3c46" + integrity sha512-eLjj2L6AuQjBB6s/ibwCAc0DwrR5Ge+ys+wgWo+bviU7fV2nTMQhU63CGaDKXg9iTmMxwhkyoggdIR7ZGRfMgw== + dependencies: + antlr4ts "^0.5.0-alpha.4" + "@szmarczak/http-timer@^1.1.2": version "1.1.2" resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-1.1.2.tgz#b1665e2c461a2cd92f4c1bbf50d5454de0d4b421" @@ -1848,6 +1866,11 @@ resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-11.1.8.tgz#b730ecb2bde209d12194cdf8bf9f12c4bd21965a" integrity sha512-49Pmk3GBUOrs/ZKJodGMJeEeiulv2VdfAYpGgkTCSXpNWx7KCX36+PbrkItwzrjTDHO2QoEZDpbhFoMN1lxe9A== +"@ungap/promise-all-settled@1.1.2": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@ungap/promise-all-settled/-/promise-all-settled-1.1.2.tgz#aa58042711d6e3275dd37dc597e5d31e8c290a44" + integrity sha512-sL/cEvJWAnClXw0wHk85/2L0G6Sj8UB0Ctc1TEMbKSsmpRosqhwj9gWgFRZSrBr2f9tiXISwNhCPmlfqUqyb9Q== + "@yarnpkg/lockfile@^1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz#e77a97fbd345b76d83245edcd17d393b1b41fb31" @@ -1987,6 +2010,14 @@ agent-base@6: dependencies: debug "4" +aggregate-error@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + ajv-keywords@^3.1.0: version "3.5.2" resolved "https://registry.yarnpkg.com/ajv-keywords/-/ajv-keywords-3.5.2.tgz#31f29da5ab6e00d1c2d329acf7b5929614d5014d" @@ -2021,7 +2052,7 @@ ansi-colors@3.2.3: resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-3.2.3.tgz#57d35b8686e851e2cc04c403f1c00203976a1813" integrity sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw== -ansi-colors@^4.1.1: +ansi-colors@4.1.1, ansi-colors@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" integrity sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA== @@ -2081,7 +2112,7 @@ ansi-styles@^3.2.0, ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" -ansi-styles@^4.1.0: +ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== @@ -2134,6 +2165,11 @@ argparse@^1.0.7: dependencies: sprintf-js "~1.0.2" +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + arr-diff@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-4.0.0.tgz#d6461074febfec71e7e15235761a329a5dc7c520" @@ -3331,6 +3367,11 @@ camelcase@^5.0.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== +camelcase@^6.0.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + caniuse-lite@^1.0.30000844: version "1.0.30001307" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001307.tgz#27a67f13ebc4aa9c977e6b8256a11d5eafb30f27" @@ -3495,6 +3536,21 @@ chokidar@3.3.0: optionalDependencies: fsevents "~2.1.1" +chokidar@3.5.3, chokidar@^3.0.2, chokidar@^3.4.0, chokidar@^3.4.1, chokidar@^3.5.2: + version "3.5.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" + integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + chokidar@^2.1.8: version "2.1.8" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-2.1.8.tgz#804b3a7b6a99358c3c5c61e71d8728f041cff917" @@ -3514,21 +3570,6 @@ chokidar@^2.1.8: optionalDependencies: fsevents "^1.2.7" -chokidar@^3.0.2, chokidar@^3.4.0, chokidar@^3.4.1, chokidar@^3.5.2: - version "3.5.3" - resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.5.3.tgz#1cf37c8707b932bd1af1ae22c0432e2acd1903bd" - integrity sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw== - dependencies: - anymatch "~3.1.2" - braces "~3.0.2" - glob-parent "~5.1.2" - is-binary-path "~2.1.0" - is-glob "~4.0.1" - normalize-path "~3.0.0" - readdirp "~3.6.0" - optionalDependencies: - fsevents "~2.3.2" - chownr@^1.1.1, chownr@^1.1.4: version "1.1.4" resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" @@ -3573,6 +3614,11 @@ class-utils@^0.3.5: isobject "^3.0.0" static-extend "^0.1.1" +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + cli-cursor@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cli-cursor/-/cli-cursor-2.1.0.tgz#b35dac376479facc3e94747d41d0d0f5238ffcb5" @@ -3640,6 +3686,15 @@ cliui@^5.0.0: strip-ansi "^5.2.0" wrap-ansi "^5.1.0" +cliui@^7.0.2: + version "7.0.4" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" + integrity sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^7.0.0" + clone-response@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/clone-response/-/clone-response-1.0.2.tgz#d1dc973920314df67fbeb94223b4ee350239e96b" @@ -4029,7 +4084,7 @@ debug@3.2.6: dependencies: ms "^2.1.1" -debug@4, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3: +debug@4, debug@4.3.3, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.2.0, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3: version "4.3.3" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.3.tgz#04266e0b70a98d4462e6e288e38259213332b664" integrity sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q== @@ -4048,6 +4103,11 @@ decamelize@^1.0.0, decamelize@^1.1.1, decamelize@^1.2.0: resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" integrity sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= +decamelize@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" + integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== + decode-uri-component@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/decode-uri-component/-/decode-uri-component-0.2.0.tgz#eb3913333458775cb84cd1a1fae062106bb87545" @@ -4226,6 +4286,11 @@ diff@3.5.0: resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" integrity sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA== +diff@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.0.0.tgz#7ed6ad76d859d030787ec35855f5b1daf31d852b" + integrity sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w== + diffie-hellman@^5.0.0: version "5.0.3" resolved "https://registry.yarnpkg.com/diffie-hellman/-/diffie-hellman-5.0.3.tgz#40e8ee98f55a2149607146921c63e1ae5f3d2875" @@ -4566,6 +4631,11 @@ es6-weak-map@^2.0.1: es6-iterator "^2.0.3" es6-symbol "^3.1.1" +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" @@ -4576,7 +4646,7 @@ escape-string-regexp@1.0.5, escape-string-regexp@^1.0.2, escape-string-regexp@^1 resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= -escape-string-regexp@^4.0.0: +escape-string-regexp@4.0.0, escape-string-regexp@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== @@ -4852,16 +4922,6 @@ eth-sig-util@^1.4.2: ethereumjs-abi "git+https://github.com/ethereumjs/ethereumjs-abi.git" ethereumjs-util "^5.1.1" -eth-sig-util@^2.5.2: - version "2.5.4" - resolved "https://registry.yarnpkg.com/eth-sig-util/-/eth-sig-util-2.5.4.tgz#577b01fe491b6bf59b0464be09633e20c1677bc5" - integrity sha512-aCMBwp8q/4wrW4QLsF/HYBOSA7TpLKmkVwP3pYQNkEEseW2Rr8Z5Uxc9/h6HX+OG3tuHo+2bINVSihIeBfym6A== - dependencies: - ethereumjs-abi "0.6.8" - ethereumjs-util "^5.1.1" - tweetnacl "^1.0.3" - tweetnacl-util "^0.15.0" - eth-tx-summary@^3.1.2: version "3.2.4" resolved "https://registry.yarnpkg.com/eth-tx-summary/-/eth-tx-summary-3.2.4.tgz#e10eb95eb57cdfe549bf29f97f1e4f1db679035c" @@ -5074,7 +5134,7 @@ ethereumjs-util@6.2.0: rlp "^2.2.3" secp256k1 "^3.0.1" -ethereumjs-util@6.2.1, ethereumjs-util@^6.0.0, ethereumjs-util@^6.1.0, ethereumjs-util@^6.2.0, "ethjs-util-v6@npm:ethereumjs-util@6.2.1": +ethereumjs-util@6.2.1, ethereumjs-util@^6.0.0, ethereumjs-util@^6.1.0, ethereumjs-util@^6.2.0, ethereumjs-util@^6.2.1, "ethjs-util-v6@npm:ethereumjs-util@6.2.1": version "6.2.1" resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-6.2.1.tgz#fcb4e4dd5ceacb9d2305426ab1a5cd93e3163b69" integrity sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw== @@ -5269,7 +5329,7 @@ ethjs-unit@0.1.6: bn.js "4.11.6" number-to-bn "1.7.0" -ethjs-util@0.1.6, ethjs-util@^0.1.3: +ethjs-util@0.1.6, ethjs-util@^0.1.3, ethjs-util@^0.1.6: version "0.1.6" resolved "https://registry.yarnpkg.com/ethjs-util/-/ethjs-util-0.1.6.tgz#f308b62f185f9fe6237132fb2a9818866a5cd536" integrity sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w== @@ -5581,6 +5641,14 @@ find-up@3.0.0, find-up@^3.0.0: dependencies: locate-path "^3.0.0" +find-up@5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + find-up@^1.0.0: version "1.1.2" resolved "https://registry.yarnpkg.com/find-up/-/find-up-1.1.2.tgz#6b2e9822b1a2ce0a60ab64d610eccad53cb24d0f" @@ -5627,6 +5695,11 @@ flat@^4.1.0: dependencies: is-buffer "~2.0.3" +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + flatted@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/flatted/-/flatted-2.0.2.tgz#4575b21e2bcee7434aa9be662f4b7b5f9c2b5138" @@ -5896,7 +5969,7 @@ get-caller-file@^1.0.1: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-1.0.3.tgz#f978fa4c90d1dfe7ff2d6beda2a515e713bdcf4a" integrity sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w== -get-caller-file@^2.0.1: +get-caller-file@^2.0.1, get-caller-file@^2.0.5: version "2.0.5" resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== @@ -5999,26 +6072,26 @@ glob@7.1.3: once "^1.3.0" path-is-absolute "^1.0.0" -glob@^5.0.15: - version "5.0.15" - resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" - integrity sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E= +glob@7.2.0, glob@^7.0.0, glob@^7.1.2, glob@^7.1.3, glob@~7.2.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" + integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== dependencies: + fs.realpath "^1.0.0" inflight "^1.0.4" inherits "2" - minimatch "2 || 3" + minimatch "^3.0.4" once "^1.3.0" path-is-absolute "^1.0.0" -glob@^7.0.0, glob@^7.1.2, glob@^7.1.3, glob@~7.2.0: - version "7.2.0" - resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.0.tgz#d15535af7732e02e948f4c41628bd910293f6023" - integrity sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q== +glob@^5.0.15: + version "5.0.15" + resolved "https://registry.yarnpkg.com/glob/-/glob-5.0.15.tgz#1bc936b9e02f4a603fcc222ecf7633d30b8b93b1" + integrity sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E= dependencies: - fs.realpath "^1.0.0" inflight "^1.0.4" inherits "2" - minimatch "^3.0.4" + minimatch "2 || 3" once "^1.3.0" path-is-absolute "^1.0.0" @@ -6187,10 +6260,10 @@ hardhat-gas-reporter@^1.0.7: eth-gas-reporter "^0.2.24" sha1 "^1.1.1" -hardhat@^2.6.7: - version "2.8.3" - resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.8.3.tgz#94cccc92d18c6361d9fbbc5d77a4fabf0166a396" - integrity sha512-VxqiVTSayRoeLHly8zKnlvtWoG8sroTP4vl8GHuj7OjfAdrHu4Blk7NBJ5+Rl8cmMEp6CuZtDaDmcHJIRTwEPA== +hardhat@^2.9.0: + version "2.9.0" + resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.9.0.tgz#3154faf616a87b735fd81311e68b82f1d7dd9916" + integrity sha512-jF8UlisdQ07ldCqaRU+rEB6lzAJzWS5Gg4KT2pUyqat0hJc7jfccE8ITRvAGP8ksC6DZ+kRpDfUSgoLsPFynaA== dependencies: "@ethereumjs/block" "^3.6.0" "@ethereumjs/blockchain" "^5.5.0" @@ -6198,12 +6271,14 @@ hardhat@^2.6.7: "@ethereumjs/tx" "^3.4.0" "@ethereumjs/vm" "^5.6.0" "@ethersproject/abi" "^5.1.2" + "@metamask/eth-sig-util" "^4.0.0" "@sentry/node" "^5.18.1" - "@solidity-parser/parser" "^0.14.0" + "@solidity-parser/parser" "^0.14.1" "@types/bn.js" "^5.1.0" "@types/lru-cache" "^5.1.0" abort-controller "^3.0.0" adm-zip "^0.4.16" + aggregate-error "^3.0.0" ansi-escapes "^4.3.0" chalk "^2.4.2" chokidar "^3.4.0" @@ -6211,7 +6286,6 @@ hardhat@^2.6.7: debug "^4.1.1" enquirer "^2.3.0" env-paths "^2.2.0" - eth-sig-util "^2.5.2" ethereum-cryptography "^0.1.2" ethereumjs-abi "^0.6.8" ethereumjs-util "^7.1.3" @@ -6219,14 +6293,13 @@ hardhat@^2.6.7: fp-ts "1.19.3" fs-extra "^7.0.1" glob "^7.1.3" - https-proxy-agent "^5.0.0" immutable "^4.0.0-rc.12" io-ts "1.10.4" lodash "^4.17.11" merkle-patricia-tree "^4.2.2" mnemonist "^0.38.0" - mocha "^7.2.0" - node-fetch "^2.6.0" + mocha "^9.2.0" + p-map "^4.0.0" qs "^6.7.0" raw-body "^2.4.1" resolve "1.17.0" @@ -6237,6 +6310,7 @@ hardhat@^2.6.7: stacktrace-parser "^0.1.10" "true-case-path" "^2.2.1" tsort "0.0.1" + undici "^4.14.1" uuid "^8.3.2" ws "^7.4.6" @@ -6579,6 +6653,11 @@ imurmurhash@^0.1.4: resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + inflight@^1.0.4: version "1.0.6" resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" @@ -6919,6 +6998,11 @@ is-plain-obj@^1.1.0: resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-1.1.0.tgz#71a50c8429dfca773c92a390a4a03b39fcd51d3e" integrity sha1-caUMhCnfync8kqOQpKA7OfzVHT4= +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + is-plain-object@^2.0.3, is-plain-object@^2.0.4: version "2.0.4" resolved "https://registry.yarnpkg.com/is-plain-object/-/is-plain-object-2.0.4.tgz#2c163b3fafb1b606d9d17928f05c2a1c38e07677" @@ -6979,6 +7063,11 @@ is-typedarray@^1.0.0, is-typedarray@~1.0.0: resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + is-upper-case@^1.1.0: version "1.1.2" resolved "https://registry.yarnpkg.com/is-upper-case/-/is-upper-case-1.1.2.tgz#8d0b1fa7e7933a1e58483600ec7d9661cbaf756f" @@ -7129,6 +7218,13 @@ js-yaml@3.x, js-yaml@^3.12.0, js-yaml@^3.13.0, js-yaml@^3.13.1: argparse "^1.0.7" esprima "^4.0.0" +js-yaml@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + jsbn@~0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" @@ -7624,6 +7720,13 @@ locate-path@^3.0.0: p-locate "^3.0.0" path-exists "^3.0.0" +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + lodash.assign@^4.0.3, lodash.assign@^4.0.6: version "4.2.0" resolved "https://registry.yarnpkg.com/lodash.assign/-/lodash.assign-4.2.0.tgz#0d99f3ccd7a6d261d19bdaeb9245005d285808e7" @@ -7676,6 +7779,14 @@ log-symbols@3.0.0: dependencies: chalk "^2.4.2" +log-symbols@4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + loglevel@^1.6.1: version "1.8.0" resolved "https://registry.yarnpkg.com/loglevel/-/loglevel-1.8.0.tgz#e7ec73a57e1e7b419cb6c6ac06bf050b67356114" @@ -8103,7 +8214,7 @@ mnemonist@^0.38.0: dependencies: obliterator "^2.0.0" -mocha@^7.1.1, mocha@^7.2.0: +mocha@^7.1.1: version "7.2.0" resolved "https://registry.yarnpkg.com/mocha/-/mocha-7.2.0.tgz#01cc227b00d875ab1eed03a75106689cfed5a604" integrity sha512-O9CIypScywTVpNaRrCAgoUnJgozpIofjKUYmJhiCIJMiuYnLI6otcb1/kpW9/n/tJODHGZ7i8aLQoDVsMtOKQQ== @@ -8133,6 +8244,36 @@ mocha@^7.1.1, mocha@^7.2.0: yargs-parser "13.1.2" yargs-unparser "1.6.0" +mocha@^9.2.0: + version "9.2.1" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-9.2.1.tgz#a1abb675aa9a8490798503af57e8782a78f1338e" + integrity sha512-T7uscqjJVS46Pq1XDXyo9Uvey9gd3huT/DD9cYBb4K2Xc/vbKRPUWK067bxDQRK0yIz6Jxk73IrnimvASzBNAQ== + dependencies: + "@ungap/promise-all-settled" "1.1.2" + ansi-colors "4.1.1" + browser-stdout "1.3.1" + chokidar "3.5.3" + debug "4.3.3" + diff "5.0.0" + escape-string-regexp "4.0.0" + find-up "5.0.0" + glob "7.2.0" + growl "1.10.5" + he "1.2.0" + js-yaml "4.1.0" + log-symbols "4.1.0" + minimatch "3.0.4" + ms "2.1.3" + nanoid "3.2.0" + serialize-javascript "6.0.0" + strip-json-comments "3.1.1" + supports-color "8.1.1" + which "2.0.2" + workerpool "6.2.0" + yargs "16.2.0" + yargs-parser "20.2.4" + yargs-unparser "2.0.0" + mock-fs@^4.1.0: version "4.14.0" resolved "https://registry.yarnpkg.com/mock-fs/-/mock-fs-4.14.0.tgz#ce5124d2c601421255985e6e94da80a7357b1b18" @@ -8227,6 +8368,11 @@ nano-json-stream-parser@^0.1.2: resolved "https://registry.yarnpkg.com/nano-json-stream-parser/-/nano-json-stream-parser-0.1.2.tgz#0cc8f6d0e2b622b479c40d499c46d64b755c6f5f" integrity sha1-DMj20OK2IrR5xA1JnEbWS3Vcb18= +nanoid@3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.2.0.tgz#62667522da6673971cca916a6d3eff3f415ff80c" + integrity sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA== + nanomatch@^1.2.9: version "1.2.13" resolved "https://registry.yarnpkg.com/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119" @@ -8705,6 +8851,13 @@ p-limit@^2.0.0: dependencies: p-try "^2.0.0" +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + p-locate@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-2.0.0.tgz#20a0103b222a70c8fd39cc2e580680f3dde5ec43" @@ -8719,6 +8872,20 @@ p-locate@^3.0.0: dependencies: p-limit "^2.0.0" +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +p-map@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-4.0.0.tgz#bb2f95a5eda2ec168ec9274e06a747c3e2904d2b" + integrity sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ== + dependencies: + aggregate-error "^3.0.0" + p-timeout@^1.1.1: version "1.2.1" resolved "https://registry.yarnpkg.com/p-timeout/-/p-timeout-1.2.1.tgz#5eb3b353b7fce99f101a1038880bb054ebbea386" @@ -8892,6 +9059,11 @@ path-exists@^3.0.0: resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-3.0.0.tgz#ce0ebeaa5f78cb18925ea7d810d7b59b010fd515" integrity sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + path-is-absolute@^1.0.0, path-is-absolute@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" @@ -9898,6 +10070,13 @@ sentence-case@^2.1.0: no-case "^2.2.0" upper-case-first "^1.1.2" +serialize-javascript@6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" + integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== + dependencies: + randombytes "^2.1.0" + serve-static@1.14.2: version "1.14.2" resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.2.tgz#722d6294b1d62626d41b43a013ece4598d292bfa" @@ -10395,7 +10574,7 @@ string-width@^1.0.1: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" -"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.2.0, string-width@^4.2.3: +"string-width@^1.0.2 || 2 || 3 || 4", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -10478,7 +10657,7 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" -strip-ansi@^6.0.1: +strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -10524,6 +10703,11 @@ strip-json-comments@2.0.1, strip-json-comments@^2.0.1, strip-json-comments@~2.0. resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo= +strip-json-comments@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + super-split@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/super-split/-/super-split-1.1.0.tgz#43b3ba719155f4d43891a32729d59b213d9155fc" @@ -10536,6 +10720,13 @@ supports-color@6.0.0: dependencies: has-flag "^3.0.0" +supports-color@8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + supports-color@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" @@ -10904,7 +11095,7 @@ tunnel-agent@^0.6.0: dependencies: safe-buffer "^5.0.1" -tweetnacl-util@^0.15.0: +tweetnacl-util@^0.15.0, tweetnacl-util@^0.15.1: version "0.15.1" resolved "https://registry.yarnpkg.com/tweetnacl-util/-/tweetnacl-util-0.15.1.tgz#b80fcdb5c97bcc508be18c44a4be50f022eea00b" integrity sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw== @@ -11083,6 +11274,11 @@ underscore@^1.8.3: resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.13.2.tgz#276cea1e8b9722a8dbed0100a407dda572125881" integrity sha512-ekY1NhRzq0B08g4bGuX4wd2jZx5GnKz6mKSqFL4nqBlfyMGiG10gDFhDTMEfYmDL6Jy0FUIZp7wiRB+0BP7J2g== +undici@^4.14.1: + version "4.14.1" + resolved "https://registry.yarnpkg.com/undici/-/undici-4.14.1.tgz#7633b143a8a10d6d63335e00511d071e8d52a1d9" + integrity sha512-WJ+g+XqiZcATcBaUeluCajqy4pEDcQfK1vy+Fo+bC4/mqXI9IIQD/XWHLS70fkGUT6P52Drm7IFslO651OdLPQ== + union-value@^1.0.0: version "1.0.1" resolved "https://registry.yarnpkg.com/union-value/-/union-value-1.0.1.tgz#0b6fe7b835aecda61c6ea4d4f02c14221e109847" @@ -12460,6 +12656,13 @@ which@1.3.1, which@^1.1.1, which@^1.2.9, which@^1.3.1: dependencies: isexe "^2.0.0" +which@2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + wide-align@1.1.3: version "1.1.3" resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" @@ -12499,6 +12702,11 @@ wordwrap@^1.0.0: resolved "https://registry.yarnpkg.com/wordwrap/-/wordwrap-1.0.0.tgz#27584810891456a4171c8d0226441ade90cbcaeb" integrity sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus= +workerpool@6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.0.tgz#827d93c9ba23ee2019c3ffaff5c27fccea289e8b" + integrity sha512-Rsk5qQHJ9eowMH28Jwhe8HEbmdYDX4lwoMWshiCXugjtHqMD9ZbiqSDLxcsfdqsETPzVUtX5s1Z5kStiIM6l4A== + wrap-ansi@^2.0.0: version "2.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-2.1.0.tgz#d8fc3d284dd05794fe84973caecdd1cf824fdd85" @@ -12516,6 +12724,15 @@ wrap-ansi@^5.1.0: string-width "^3.0.0" strip-ansi "^5.0.0" +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -12618,6 +12835,11 @@ y18n@^4.0.0: resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + yaeti@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/yaeti/-/yaeti-0.0.6.tgz#f26f484d72684cf42bedfb76970aa1608fbf9577" @@ -12646,6 +12868,11 @@ yargs-parser@13.1.2, yargs-parser@^13.1.0, yargs-parser@^13.1.2: camelcase "^5.0.0" decamelize "^1.2.0" +yargs-parser@20.2.4: + version "20.2.4" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.4.tgz#b42890f14566796f85ae8e3a25290d205f154a54" + integrity sha512-WOkpgNhPTlE73h4VFAFsOnomJVaovO8VqLDzy5saChRBFQFBoMYirowyW+Q9HB4HFF4Z7VZTiG3iSzJJA29yRA== + yargs-parser@^2.4.1: version "2.4.1" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-2.4.1.tgz#85568de3cf150ff49fa51825f03a8c880ddcc5c4" @@ -12654,6 +12881,11 @@ yargs-parser@^2.4.1: camelcase "^3.0.0" lodash.assign "^4.0.6" +yargs-parser@^20.2.2: + version "20.2.9" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" + integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== + yargs-parser@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-7.0.0.tgz#8d0ac42f16ea55debd332caf4c4038b3e3f5dfd9" @@ -12677,6 +12909,16 @@ yargs-unparser@1.6.0: lodash "^4.17.15" yargs "^13.3.0" +yargs-unparser@2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" + integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== + dependencies: + camelcase "^6.0.0" + decamelize "^4.0.0" + flat "^5.0.2" + is-plain-obj "^2.1.0" + yargs@13.2.4: version "13.2.4" resolved "https://registry.yarnpkg.com/yargs/-/yargs-13.2.4.tgz#0b562b794016eb9651b98bd37acf364aa5d6dc83" @@ -12710,6 +12952,19 @@ yargs@13.3.2, yargs@^13.3.0: y18n "^4.0.0" yargs-parser "^13.1.2" +yargs@16.2.0: + version "16.2.0" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" + integrity sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw== + dependencies: + cliui "^7.0.2" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.0" + y18n "^5.0.5" + yargs-parser "^20.2.2" + yargs@^10.0.3: version "10.1.2" resolved "https://registry.yarnpkg.com/yargs/-/yargs-10.1.2.tgz#454d074c2b16a51a43e2fb7807e4f9de69ccb5c5" @@ -12776,3 +13031,8 @@ yargs@~3.10.0: cliui "^2.1.0" decamelize "^1.0.0" window-size "0.1.0" + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== From 0f0dbf610a1a86dcdb59db3d8740aebae398026a Mon Sep 17 00:00:00 2001 From: andrejrakic Date: Mon, 7 Mar 2022 23:02:40 +0100 Subject: [PATCH 08/11] Resolve open PR conversations --- README.md | 13 +++++------ deploy/03_Deploy_RandomNumberConsumer.js | 5 ++-- hardhat.config.js | 15 ++++++------ test/unit/RandomNumberConsumerV2_unit_test.js | 23 +++++++++++++++++++ 4 files changed, 40 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index ad2d5943d..ce37ef4ad 100644 --- a/README.md +++ b/README.md @@ -205,15 +205,14 @@ yarn hardhat test --network rinkeby If you'd like to run tests or on a network that is a [forked network](https://hardhat.org/hardhat-network/guides/mainnet-forking.html) 1. Set a `MAINNET_RPC_URL` environment variable that connects to the mainnet. -2. Choose a block number to select a state of the network you are forking. If ignored, it will use the latest block each time which can lead to test inconsistency. +2. Choose a block number to select a state of the network you are forking and set it as `FORKING_BLOCK_NUMBER` environment variable. If ignored, it will use the latest block each time which can lead to test inconsistency. 3. Set `enabled` flag to `true`/`false` to enable/disable forking feature -4. Uncomment the section in your `hardhat.config.js` ``` - // forking: { - // url: MAINNET_RPC_URL, - // blockNumber: "your forking block number goes here", - // enabled: false, - // } + forking: { + url: MAINNET_RPC_URL, + blockNumber: FORKING_BLOCK_NUMBER, + enabled: false, + } ``` diff --git a/deploy/03_Deploy_RandomNumberConsumer.js b/deploy/03_Deploy_RandomNumberConsumer.js index 706ddb942..2de2ac5eb 100644 --- a/deploy/03_Deploy_RandomNumberConsumer.js +++ b/deploy/03_Deploy_RandomNumberConsumer.js @@ -21,9 +21,10 @@ module.exports = async ({ getNamedAccounts, deployments }) => { vrfCoordinatorAddress = VRFCoordinatorV2Mock.address linkTokenAddress = linkToken.address - subscriptionId = await VRFCoordinatorV2Mock.callStatic.createSubscription() const fundAmount = networkConfig[chainId]["fundAmount"] - await VRFCoordinatorV2Mock.createSubscription() + const transaction = await VRFCoordinatorV2Mock.createSubscription() + const transactionReceipt = await transaction.wait(1) + subscriptionId = ethers.BigNumber.from(transactionReceipt.events[0].topics[1]) await VRFCoordinatorV2Mock.fundSubscription(subscriptionId, fundAmount) } else { subscriptionId = process.env.VRF_SUBSCRIPTION_ID diff --git a/hardhat.config.js b/hardhat.config.js index 6444137c6..bbf75e589 100644 --- a/hardhat.config.js +++ b/hardhat.config.js @@ -23,7 +23,8 @@ const POLYGON_MAINNET_RPC_URL = process.env.POLYGON_MAINNET_RPC_URL || "https://polygon-mainnet.alchemyapi.io/v2/your-api-key" const PRIVATE_KEY = process.env.PRIVATE_KEY // optional -const MNEMONIC = process.env.MNEMONIC || "your mnemonic" +const MNEMONIC = process.env.MNEMONIC || "Your mnemonic" +const FORKING_BLOCK_NUMBER = process.env.FORKING_BLOCK_NUMBER // Your API key for Etherscan, obtain one at https://etherscan.io/ const ETHERSCAN_API_KEY = process.env.ETHERSCAN_API_KEY || "Your etherscan API key" @@ -34,12 +35,12 @@ module.exports = { defaultNetwork: "hardhat", networks: { hardhat: { - // If you want to do some forking, uncomment this and set `enabled` to true - // forking: { - // url: MAINNET_RPC_URL, - // blockNumber: "your forking block number goes here", - // enabled: false, - // }, + // If you want to do some forking set `enabled` to true + forking: { + url: MAINNET_RPC_URL, + blockNumber: FORKING_BLOCK_NUMBER, + enabled: false, + }, chainId: 31337, }, localhost: { diff --git a/test/unit/RandomNumberConsumerV2_unit_test.js b/test/unit/RandomNumberConsumerV2_unit_test.js index cbb7077e5..be43521d6 100755 --- a/test/unit/RandomNumberConsumerV2_unit_test.js +++ b/test/unit/RandomNumberConsumerV2_unit_test.js @@ -42,4 +42,27 @@ const { developmentChains } = require("../../helper-hardhat-config") "Second random number is greather than zero" ) }) + + it("Should successfully fire event on callback", async function () { + await new Promise(async (resolve, reject) => { + randomNumberConsumerV2.once("ReturnedRandomness", async () => { + console.log("ReturnedRandomness event fired!") + const firstRandomNumber = await randomNumberConsumerV2.s_randomWords(0) + const secondRandomNumber = await randomNumberConsumerV2.s_randomWords(1) + // assert throws an error if it fails, so we need to wrap + // it in a try/catch so that the promise returns event + // if it fails. + try { + assert(firstRandomNumber.gt(ethers.constants.Zero)) + assert(secondRandomNumber.gt(ethers.constants.Zero)) + resolve() + } catch (e) { + reject(e) + } + }) + await randomNumberConsumerV2.requestRandomWords() + const requestId = await randomNumberConsumerV2.s_requestId() + vrfCoordinatorV2Mock.fulfillRandomWords(requestId, randomNumberConsumerV2.address) + }) + }) }) From 0492b69cbd80b3e1c473756b20532a2c728a70b4 Mon Sep 17 00:00:00 2001 From: Patrick Collins <54278053+PatrickAlphaC@users.noreply.github.com> Date: Thu, 17 Mar 2022 08:03:38 -0400 Subject: [PATCH 09/11] removed public constructors (#91) --- contracts/APIConsumer.sol | 2 +- contracts/PriceConsumerV3.sol | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/APIConsumer.sol b/contracts/APIConsumer.sol index 01e651dd3..15675d6df 100644 --- a/contracts/APIConsumer.sol +++ b/contracts/APIConsumer.sol @@ -35,7 +35,7 @@ contract APIConsumer is ChainlinkClient { bytes32 _jobId, uint256 _fee, address _link - ) public { + ) { if (_link == address(0)) { setPublicChainlinkToken(); } else { diff --git a/contracts/PriceConsumerV3.sol b/contracts/PriceConsumerV3.sol index d0117d545..b9d5f4660 100644 --- a/contracts/PriceConsumerV3.sol +++ b/contracts/PriceConsumerV3.sol @@ -19,7 +19,7 @@ contract PriceConsumerV3 { * Aggregator: ETH/USD * Address: 0x8A753747A1Fa494EC906cE90E9f37563A8AF630e */ - constructor(address _priceFeed) public { + constructor(address _priceFeed) { priceFeed = AggregatorV3Interface(_priceFeed); } From f43eb7979ef2b4797c282b0322e7f91faf871b8f Mon Sep 17 00:00:00 2001 From: PatrickAlphac <54278053+PatrickAlphaC@users.noreply.github.com> Date: Tue, 22 Mar 2022 07:08:09 -0400 Subject: [PATCH 10/11] updated for comma delimited requests --- contracts/APIConsumer.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contracts/APIConsumer.sol b/contracts/APIConsumer.sol index 15675d6df..2913c04c1 100644 --- a/contracts/APIConsumer.sol +++ b/contracts/APIConsumer.sol @@ -72,7 +72,8 @@ contract APIConsumer is ChainlinkClient { // } // } // } - request.add("path", "RAW.ETH.USD.VOLUME24HOUR"); + // request.add("path", "RAW.ETH.USD.VOLUME24HOUR"); // Chainlink nodes prior to 1.0.0 support this format + request.add("path", "RAW,ETH,USD,VOLUME24HOUR"); // Chainlink nodes 1.0.0 and later support this format // Multiply the result by 1000000000000000000 to remove decimals int256 timesAmount = 10**18; From 2083738c97b6a9864e33ae1282693d46fcfb6327 Mon Sep 17 00:00:00 2001 From: PatrickAlphac <54278053+PatrickAlphaC@users.noreply.github.com> Date: Mon, 11 Apr 2022 11:36:01 -0400 Subject: [PATCH 11/11] updated prettier --- .prettierrc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.prettierrc b/.prettierrc index 8674c6257..1871c8bc8 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,5 +1,5 @@ { - "tabWidth": 2, + "tabWidth": 4, "useTabs": false, "semi": false, "singleQuote": false,