/my-first-hardhat

First crypto project using Hardhat (instead of Truffle)

Primary LanguageJavaScript

my-first-hardhat

First crypto project develped using Hardhat (instead of Truffle).

This project, and README file are following the excellent video by Julien on How to use Hardhat.

This repo includes:

  1. Smart contract
  2. Tests
  3. Debug
  4. Deployment (in-memory, actual network)
  5. Frontend

How to start from scratch

Setup

  1. npm init -y - create new project
  2. npm i -D hardhat - install hardhat as dev dependency
  3. npx hardhat - run and choose empty config
  4. npm i -D ethers @nomiclabs/hardhat-ethers ethereum-waffle @nomiclabs/hardhat-waffle chai -install plugins and test platforms
  5. Add require('@nomiclabs/hardhat-waffle'); at top of config file. No need to require the ethers plugin, since the waffle plugin requires it.

Develop

  1. Create a contracts folder and start working on Solidity contracts!
  2. Compile using npx hardhat compile

Test

  1. Create a test folder and put your test files in there
  2. Start the test file with const {expect} = require('chai');
  3. The ethers object is injected automatically into the test. Use it to deploy the contract and get the addresses:
    Token = await ethers.getContractFactory('Token');
    token = await Token.deploy();
    [owner, addr1, addr2, _] = await ethers.getSigners();
    
  4. No need to do BigNumber conversions - hardhat does it for you
  5. Run tests with npx hardhat test

Debug

  1. Add import 'hardhat/console.sol'; at the top of your contract file
  2. Use console.log statments, using substitution strings (read more here)
  3. When you run your tests, you'll be able to see values in the console window

Deploy

  1. Create a directory called scripts and a deploy.js file in it
  2. The ethers object is injected automatically into the test. Use it to deploy the contract:
    Token = await ethers.getContractFactory('Token');
    token = await Token.deploy();
    
  3. To deploy to Hardhat in-memory blockchain: npx hardhat run scripts/deploy.js
  4. To deploy to other networks (ie Rinkeby):
    1. Get the Infura URL and private key of the account to use for deployment:
      1. Create a .env file
      2. Add INFURA_RINKBEY_URL= to .env with your Rinkeby Infura key (get free project)
      3. Add RINKEBEY_PRIVATEKEY= to .env with the private key of the account you intend to use
      4. Add .env to .gitignore to avoid saving file to repo
      5. Run npm i -D dotenv
      6. Add the line require('dotenv').config(); to the top of hardhat.config.js
    2. Add the network to the config in hardhat.config.js:
      networks: {
          rinkeby: {
              url: process.env.INFURA_RINKBEY_URL,
              accounts: [`0x${process.env.RINKBEY_PRIVATE_KEY}`]
          }
      }
      
    3. Deploy: npx hardhat run scripts/deploy.js --network rinkeby
    4. Check on Rinkeby Etherscan to verify your contract has been deployed to that address
    5. You can now repeat the same with mainnet, or other testnets, by adding keys to .env and networks to hardhat.config.js

Frontend

Unlike Truffle, we need to generate the abi file/s ourselves, to allow the frontend to interact with our contract.

  1. We'll first create a frontend folder and a src subfolder.
  2. We'll add the following to our deploy.js:
    const fs = require('fs');
    // ... rest of the deployemnt
    // after the .deploy()
    const data = {
        address: token.address,
        abi: JSON.parse(token.interface.format('json'))
    }
    fs.writeFileSync('frontend/src/Token.js', JSON.stringify(data));
    
  3. We'll then run a local blockchain: npx hardhat node
  4. We'll deploy the contract to the local chain (in a separate console window!): npx hardhat run scripts/deploy.js --network localhost
  5. Our contract is now deployed, and the abi file created. We can use the localhost chain to debug, and finally redeploy again to any chain we need.
  6. The App.js and ethereum.js files in frontend/src show how to connect to, and use our contract.
  7. You can use create-react-app to bootstrap the app, and add ethers and bootstrap modules to have a workable app.