Giter VIP home page Giter VIP logo

hardhat-starter-kit's Introduction


Chainlink Hardhat logo


Open in Gitpod

GitPOAP Badge

Chainlink Hardhat Starter Kit

Implementation of the following 4 Chainlink features using the Hardhat development environment:

Getting Started

It's recommended that you've gone through the hardhat getting started documentation before proceeding here.

Requirements

  • git
    • You'll know you did it right if you can run git --version and see a response like git version x.x.x
  • Nodejs
    • You'll know you've installed nodejs right if you can run:
      • node --version and get an output like: vx.x.x
  • Yarn instead of npm
    • You'll know you've installed yarn right if you can run:
      • 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

After installing all the requirements, run the following:

git clone https://github.com/smartcontractkit/hardhat-starter-kit/
cd hardhat-starter-kit

Then:

npm install

The recommendation is to use npm 7 or later. If you are using an older version of npm, you'll also need to install all the packages used by the toolbox.

npm install --save-dev @nomicfoundation/hardhat-toolbox @nomicfoundation/hardhat-network-helpers @nomicfoundation/hardhat-chai-matchers @nomiclabs/hardhat-ethers @nomiclabs/hardhat-etherscan chai ethers hardhat-gas-reporter solidity-coverage @typechain/hardhat typechain @typechain/ethers-v5 @ethersproject/abi @ethersproject/providers

That's also the case if you are using yarn.

yarn add --dev @nomicfoundation/hardhat-toolbox @nomicfoundation/hardhat-network-helpers @nomicfoundation/hardhat-chai-matchers @nomiclabs/hardhat-ethers @nomiclabs/hardhat-etherscan chai ethers hardhat-gas-reporter solidity-coverage @typechain/hardhat typechain @typechain/ethers-v5 @ethersproject/abi @ethersproject/providers
  1. You can now do stuff!
npx hardhat test

or

npm run test

or

yarn test

Typescript

To use typescript, run:

git checkout typescript
npm install

Usage

If you run npx hardhat --help you'll get an output of all the tasks you can run.

Deploying Contracts

npm run deploy

This will deploy your contracts to a local network. Additionally, if on a local network, it will deploy mock Chainlink contracts for you to interact with. If you'd like to interact with your deployed contracts, skip down to Interacting with Deployed Contracts.

Run a Local Network

One of the best ways to test and interact with smart contracts is by using a local network. To run a local network with all your contracts in it, execute the following command:

npx hardhat node

You'll get a local blockchain, private keys, contracts deployed (from the deployment folder scripts), and an endpoint to potentially add to an EVM wallet.

Using a Testnet or Live Network (like Mainnet or Polygon)

In your hardhat.config.js you'll see section like:

module.exports = {
  defaultNetwork: "hardhat",
  networks: {

This section of the file is where you define which networks you want to interact with. You can read more about that whole file in the hardhat documentation.

To interact with a live or test network, you'll need:

  1. An rpc URL
  2. A Private Key
  3. ETH & LINK token (either testnet or real)

Let's look at an example of setting these up using the Sepolia testnet.

Sepolia 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 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 DON'T 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 SEPOLIA_RPC_URL environment variable.

You can get one for free from Alchemy, Infura, or Moralis. This is your connection to the blockchain.

  1. Set your PRIVATE_KEY environment variable.

This is your private key from your wallet, ie MetaMask. This is needed for deploying contracts to public networks. You can optionally set your MNEMONIC environment variable instead with some changes to the hardhat.config.js.

WARNING WARNING WARNING

When developing, it's best practice to use a Metamask that isn't associated with any real money. A good way to do this is to make a new browser profile (on Chrome, Brave, Firefox, etc) and install Metamask on that browser, and never send this wallet money.

Don't commit and push any changes to .env files that may contain sensitive information, such as a private key! If this information reaches a public GitHub repository, someone can use it to check if you have any Mainnet funds in that wallet address, and steal them!

.env example:

SEPOLIA_RPC_URL='https://sepolia.infura.io/v3/asdfadsfafdadf'
PRIVATE_KEY='abcdef'

bash example:

export SEPOLIA_RPC_URL='https://sepolia.infura.io/v3/asdfadsfafdadf'
export PRIVATE_KEY='abcdef'

You can also use a MNEMONIC instead of a PRIVATE_KEY environment variable by uncommenting the section in the hardhat.config.js, and commenting out the PRIVATE_KEY line. However this is not recommended.

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.

  1. Get some Sepolia Testnet ETH and LINK

Head over to the Chainlink faucets and get some ETH and LINK. Please follow the chainlink documentation if unfamiliar.

  1. Create VRF V2 subscription

Head over to VRF Subscription Page and create the new subscription. Save your subscription ID and put it in helper-hardhat-config.js file as subscriptionId

  1. Running commands

You should now be all setup! You can run any command and just pass the --network sepolia now!

To deploy contracts:

npm run deploy --network sepolia

To run staging testnet tests

npm run test-staging

Forking

If you would like to run tests on a forked network, follow these steps:

  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 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
      forking: {
        url: MAINNET_RPC_URL,
        blockNumber: FORKING_BLOCK_NUMBER,
        enabled: false,
      }

Auto-Funding

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, and are configurable per network.

Parameter Description Default Value
fundAmount Amount of LINK to transfer when funding contracts 0.1 LINK

If you wish to deploy the smart contracts without performing the auto-funding, add an AUTO_FUND environment variable, and set it to false.

Test

Tests are located in the test directory, and are split between unit tests and staging/testnet tests. Unit tests should only be run on local environments, and staging tests should only run on live environments.

To run unit tests:

npx hardhat test

or

npm run test

or

yarn test

To run staging tests on Sepolia network:

npx hardhat test --network sepolia

or

npm run test-staging

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

To run tests in parallel:

npx hardhat test --parallel

or

npm run 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.

Chainlink Price Feeds

The Price Feeds consumer contract has one task, to read the latest price of a specified price feed contract

npx hardhat read-price-feed --contract insert-contract-address-here --network network

Request & Receive Data

The APIConsumer contract has two tasks, one to request external data based on a set of parameters, and one to check to see what the result of the data request is. This contract needs to be funded with link first:

npx hardhat fund-link --contract insert-contract-address-here --network network

Once it's funded, you can request external data by passing in a number of parameters to the request-data task. The contract parameter is mandatory, the rest are optional

npx hardhat request-data --contract insert-contract-address-here --network network

Once you have successfully made a request for external data, you can see the result via the read-data task

npx 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. As explained in the developer documentation, there are two methods:

Read the docs first to understand which method is the most suitable for your use case.

VRF Subscription method

To start, go to VRF Subscription Page and create the new subscription. Save your subscription ID and put it in helper-hardhat-config.js file as subscriptionId:

5: {
    // rest of the config
    subscriptionId: "777"
}

Then, deploy your VRF V2 contract consumer to the network of your recent subscription using subscription id as constructor argument.

npm run deploy --network network   

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:

npx hardhat request-random-number --contract insert-contract-address-here --network network

Once you have successfully made a request for a random number, you can see the result via the read-random-number task:

npx hardhat read-random-number --contract insert-contract-address-here --network network

VRF Direct Funding method

Deploy your VRF V2 contract consumer to the network.

npm run deploy --network network   

or (if you are using yarn)

yarn deploy --network network   

Now you have to fund your consumer contract with LINK tokens:

npx hardhat transfer-link --recipient insert-contract-address-here --amount insert-amount-in-juels-here --network network

Once that's done, you can perform a VRF request with the request-random-number task:

npx hardhat request-random-number-direct-funding --callbackgaslimit insert-callback-gas-limit-here --requestconfirmations insert-request-confirmations-here --numwords insert-number-words-here --contract insert-contract-address-here --network network

Once you have successfully made a request for a random number, you can see the result via the read-random-number task:

npx hardhat read-random-number-direct-funding --contract insert-contract-address-here --network network

Automation

The AutomationCounter contract is a simple Chainlink Automation enabled contract that simply maintains a counter variable that gets incremented each time the performUpkeep task is performed by a Chainlink Automation. Once the contract is deployed, you should head to https://automation.chain.link/ to register it for upkeeps, then you can use the task below to view the counter variable that gets incremented by Chainlink Automation

npx hardhat read-automation-counter --contract insert-contract-address-here --network network

Verify on Etherscan

You'll need an ETHERSCAN_API_KEY environment variable. You can get one from the Etherscan API site.. If you have it set, your deploy script will try to verify them by default, but if you want to verify any manually, you can run:

npx hardhat verify --network <NETWORK> <CONTRACT_ADDRESS> <CONSTRUCTOR_PARAMETERS>

example:

npx hardhat verify --network sepolia 0x9279791897f112a41FfDa267ff7DbBC46b96c296 "0x694AA1769357215DE4FAC081bf1f309aDC325306"

Linting

This will lint your smart contracts.

npm run lint:fix

Code Formatting

This will format both your javascript and solidity to look nicer.

npm run format

Estimating Gas

To estimate gas, just set a REPORT_GAS environment variable to true, and then run:

npx hardhat test

If you'd like to see the gas prices in USD or other currency, add a COINMARKETCAP_API_KEY from Coinmarketcap.

Code coverage

To see a measure in percent of the degree to which the smart contract source code is executed when a particular test suite is run, type

npm run coverage

Fuzzing

We are going to use Echidna as a Fuzz testing tool. You need to have Docker installed with at least 8GB virtual memory allocated (To update this parameter go to Settings->Resources->Advanced->Memory).

To start Echidna instance run

npm run fuzzing

If you are using it for the first time, you will need to wait for Docker to download eth-security-toolbox image for us.

To start Fuzzing run

echidna-test /src/contracts/test/fuzzing/AutomationCounterEchidnaTest.sol --contract AutomationCounterEchidnaTest --config /src/contracts/test/fuzzing/config.yaml

To exit Echidna type

exit

Contributing

Contributions are always welcome! Open a PR or an issue!

Thank You!

Resources

hardhat-starter-kit's People

Contributors

0xshivamagarwal avatar aelmanaa avatar andrejrakic avatar armgp avatar bobanm avatar crypt0hackers avatar danielgruesso avatar dependabot[bot] avatar fabiodmferreira avatar hasanza avatar igorshadurin avatar jake-vaughn avatar jmarcelocjr avatar l8y avatar lknsi avatar lucaperret avatar luislucena16 avatar mi2valley avatar omahs avatar pappas999 avatar patrickalphac avatar rahul-prasad-07 avatar rgottleber avatar rishabh42 avatar rogargon avatar sebasg22 avatar thodges-gh avatar tomfkearney avatar turupawn avatar zeuslawyer avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

hardhat-starter-kit's Issues

Make variable in the constructor `immutable`

immutable variables save on gas, and cannot be changed and we have a number of variables that we won't want to change, like the VRFCoordinator address.

We can also use immutable to set these variables in the constructor.

constant variables cannot be set in the constructor.

Remove `stringToBytes32`

We don't need to do this. We should just encode the jobid using ethers.

This is best practice anyways.

Predictable number for testing

In the RandomNumberConsumerV2 unit test, the result of the number is validated with always being greater than zero.
At first it's fine. but how is it applied for the moment in which it must be tested with a winning or specific number?

assert(firstRandomNumber.gt(ethers.constants.Zero))

Is there any way to provide the number as in the v1 mock?

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) })

Remove "Hardcoded" warning in `RandomNumberConsumer.sol` or clarify what it means

hardhat-starter-kit/contracts/RandomNumberConsumer.sol states:

/**
 * THIS IS AN EXAMPLE CONTRACT WHICH USES HARDCODED VALUES FOR CLARITY.
 * PLEASE DO NOT USE THIS CODE IN PRODUCTION.
 */

But it's unclear what it is referring to when it says "Hardcoded values", it doesn't look like there are any hardcoded values, and the contract appears to be fine for a production deployment aside from maybe also having a withdraw function for any LINK in the contract.

Am I missing something which makes this unsuitable for a production deployment (aside from the withdraw function)? Are there any hardcoded values here?

Link for clarity: https://github.com/smartcontractkit/hardhat-starter-kit/blob/main/contracts/RandomNumberConsumer.sol#L5-L8

Update oracle and jobs for kovan and rinkeby

To the Chainlink devrel node

kovan:
    oracle: '0xc57b33452b4f7bb189bb5afae9cc4aba1f7a4fd8'
    jobId: 'd5270d1c311941d0b08bead21fea7747'
  rinkeby:
    oracle: '0xc57b33452b4f7bb189bb5afae9cc4aba1f7a4fd8'
    jobId: '6b88e0402e5d415eb946e528b8e0c7ba'

Change the LINK token to version 0.4

Version 0.6 of the LINK token imports openzeppelin contracts, which can cause conflicts when others want to use OZ packages.

Default to the mock contract using v0.4 of solidity to avoid collision

Random number is always 0

First of all, thanks for putting this demo repo together.

I'm trying to test some smart contracts that interact with VRF locally. Even though I think I've followed the instructions correctly, I keep getting 0 as the randomly generated number, regardless of the seed.

Looking at the code, it seems like this line would be logging You'll either need to wait another minute, or fix something!, but it won't do that either, since the result is being casted into a string.

        const vrfConsumerContract = new ethers.Contract(contractAddr, RandomNumberConsumer.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!")
        }

Is there anything I could be missing?

Thanks!

Add tasks back in

npx hardhat request-random-number --contract shouldn't be a plug-in. It abstracts how this task is happening and isn't something a lot of projects are necessarily going to use. We want to show users how to make this task.
Please add this task back in.

In fact, the majority of these shouldn't be abstracted out. The only tasks that should be tasks are reading price feeds and funding LINK .

Remove mumbai

The developer experience on mumbai is not good. I'd much rather developers use kovan, rinkeby, or other instead.

Many are running into odd unexplained errors.

Add a `00_deploy_mocks` deploy script

This will deploy mocks IF the chainId is a developChain id, then you can just call like "getAddress" and not duplicate deploy.

Also use:
Use const LinkToken = await deployments.get('LinkToken') in the scripts

npm/yarn to install "chainlink-plugins-fund-link", but with following error

npm install

npm ERR! 404 Not Found - GET https://registry.npmjs.org/@appliedblockchain/chainlink-plugins-fund-link/-/chainlink-plugins-fund-link-0.0.1.tgz
npm ERR! 404
npm ERR! 404 '@appliedblockchain/[email protected]' is not in the npm registry.
npm ERR! 404 You should bug the author to publish it (or use the name yourself!)
npm ERR! 404 It was specified as a dependency of 'hardhat-starter-kit'

yarn

error An unexpected error occurred: "https://registry.yarnpkg.com/@appliedblockchain%2fchainlink-plugins-fund-link: Not found".

How to Use Chainlink With Hardhat

Suggesting an issue to have the GitHub repository on this tutorial be replaced with this one as it is the latest hardhat-starter-kit and the one isn't being maintained anymore according to its ReadMe File and the repository name was changed to this one

named accounts

use named accounts instead of that garbaged "if network is kovan -> do this, if network is rinkeby -> do this"

Have default network be hardhat

have the default network be hardhat, and have it smart enough to swap addresses based on the network. Including deploying mocks if you're on a local network.

Premium and gas per link variable in the deploy mocks scripts should be clarified

Right now, we deploy the VRFCoordinatorV2Mock as such:

    await deploy("VRFCoordinatorV2Mock", {
      from: deployer,
      log: true,
      args: [
        POINT_ONE_LINK,
        1e9, // 0.000000001 LINK per gas
      ],
    })

POINT_ONE_LINK and 1e9 are not descriptive for what each stands for, they should be something like:

BASE_FEE,
GAS_PRICE_LINK

Respectively, with a link explaining what each means.

Unit testing of randomness - callback from mock?

Would it be possible to have the fulfillRandomness fire from the mock during tests, so that the following behaviour can be tested in unit-tests? This does not seem to happen in my project. It does not in your starter either.

The contract I would like to create really depends on this random value as its starting point, without alternative public entrypoints to accomodate for testing (the random value not being manipulated from outside factors is crucial when the contract is deployed on a real chain).

How are people testing this today?

Change PRIVATE_KEY to MNEMONIC in env file

The bash environment variable names (in the readme) are inconsistent with the env file. Rename PRIVATE_KEY as MNEMONIC in the env and example env files, or, add them in addition to PRIVATE_KEY.

Wrong requestId in RandomNumberConsumer unit test

The requestId from

const transaction = await randomNumberConsumer.getRandomNumber()
const transactionReceipt = await transaction.wait(1)
const requestId = transactionReceipt.events[0].topics[1]

is different to the requestId from the RandomNumberConsumer contract if you log and see them

function getRandomNumber() public returns (bytes32 requestId) {
    require(LINK.balanceOf(address(this)) >= fee, "Not enough LINK - fill contract with faucet");
    requestId = requestRandomness(keyHash, fee);
    console.logBytes32(requestId);
  }

image

Extract some parts of this project as separate npm packages

I came across this repository while reading the Chainlink documentation about how to set it up with Hardhat. I gotta say you guys did an amazing job setting this up.

I see some bits of it could be extracted in separate npm packages, which could be used in existing set-ups (when someone doesn't start from this project):

  • Network configs and auto-funding logic: could be probably even shared with the truffle set-up
  • Tasks into a hardhat plugin
  • A new task to generate mock contracts and basic deployment scripts (I believe you can't have contracts and deployments as a plugin), somewhat in Golang generator fashion.

If you guys think it might be a good idea, let me know. I am more than happy to help with this.

The repository could still be used as reference of the final implementation though.

CC0 licence?

Hi there. I was wondering if you would consider switching to a public domain licence like CC0 or the unlicense?

Complying with the MIT licence is often not too hard - if you're using a library then you have an exact copy and you simply preserve the licence declaration. Easy. Not so when creating a derivative work, and this is a template project so all usage is derivative in nature. How do you refer to the code that remains copied from here to attribute the MIT licence?

If a part of that project itself is used to create another derivative work, how is that author to know if they have used any of this project's code, and whether they are subject to its MIT licence? That downstream author, if paying attention to compliance, may be forced to write something like:

Though I am not aware of any specific examples, there may be portions of this   
project that are considered derivative of hardhat-starter-kit. The copyright       
for those portions would be held by pappas999 (c) 2021, and the MIT licence        
below would apply.

(MIT licence goes here)

IANAL, but to the best of my knowledge, project authors are required to do this kind of thing. I think it's a bit silly, and it would be better if we all stopped worrying about attribution in open source licences, and just committed the work to the public domain (assuming having other projects benefit from your work is the goal, of course).

Wdyt?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.