> For the complete documentation index, see [llms.txt](https://notes.nomanaziz.me/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://notes.nomanaziz.me/development/blockchain/freecodecamp-course/6.-hardhat.md).

# 6. Hardhat

### Hardhat Setup

* Installed as a node package using npm or yarn
* Accessed via `yarn hardhat`
* Contracts compiled via `yarn hardhat compile`

***

### Deploying SimpleStorage (Method 1)

* `yarn hardhat run scripts/deploy.js`

```js
const { ethers } = require("hardhat");

async function main() {
  const SimpleStorageFactory = await ethers.getContractFactory("SimpleStorage");
  console.log("Deploying contract...");

  const simpleStorage = await SimpleStorageFactory.deploy();
  await simpleStorage.deployed();

  console.log(`Deployed contract to: ${simpleStorage.address}`);
}

main()
  .then(() => process.exit(0))
  .catch((error) => {
    console.log(error);
    process.exit(1);
  });
```

***

### Networks in Hardhat

* Hardhat contains default hardhat network, rpc and wallet by default
* We can edit `hardhat.config.js` file to change default settings
* We can also explicitly select network while running hardhat i.e `yarn hardhat run scripts/deploy.js --network goerli`

```js
require("@nomicfoundation/hardhat-toolbox");
require("dotenv").config();

const GOERLI_RPC_URL = process.env.GOERLI_RPC_URL;
const PRIVATE_KEY = process.env.PRIVATE_KEY;

/** @type import('hardhat/config').HardhatUserConfig */
module.exports = {
  defaultNetwork: "hardhat",
  networks: {
    goerli: {
      url: GOERLI_RPC_URL,
      accounts: [PRIVATE_KEY],
      chainId: 5,
    },
  },
  solidity: "0.8.17",
};
```

***

### Programatic Verification

* In our code script, we can automatically verify our contract code upon deployment
* Works on block explorers like etherScan, might not work on other explorers
* We can use etherScan API or use hardhat plugins `hardhat-etherscan`

#### hardhat.config.js

```js
// ...
require("@nomiclabs/hardhat-etherscan");
// ...
module.exports = {
	// ...
	solidity: "0.8.17",
  etherscan: {
    apiKey: ETHERSCAN_API_KEY,
  },
};
```

#### deploy.js

```js
// Run package allows us to run any hardhat task in code
// Network package gives us network information
const { ethers, run, network } = require("hardhat");

async function main() {
  // ...
  // Only verify if we are on goerli test network
  /*
    4 == 4 -> true
    4 == "4" -> true
    4 === "4" -> false (no type conversion is done)
  */
  if (network.config.chainId === 5 && process.env.ETHERSCAN_API_KEY) {
    console.log("Waiting for block txes...");
    await simpleStorage.deployTransaction.wait(6);
    await verify(simpleStorage.address, []);
  }
}

async function verify(contractAddress, args) {
  console.log("Verifying contract...");

  try {
    await run("verify:verify", {
      address: contractAddress,
      constructorArguments: args,
    });
  } catch (e) {
    if (e.message.toLowerCase().includes("already verified")) {
      console.log("Already Verified!");
    } else {
      console.log(e);
    }
  }
}
```

***

### Interacting with Contracts in Hardhat

#### deploy.js

```js
  const currentValue = await simpleStorage.retrieve();
  console.log(`Current Value is: ${currentValue}`);

  const transactionResponse = await simpleStorage.store(7);
  await transactionResponse.wait(1);
  const updatedValue = await simpleStorage.retrieve();
  console.log(`Updated Value is: ${updatedValue}`);

```

***

### Artifacts Troubleshooting

* Delete the cache and artifacts folder if any issue arises (`yarn hardhat clean`)
* Hardhat will re compile and generate the artifacts

***

### Custom Hardhat Tasks

* Can be defined in `hardhat.config.js`
* Generally created in `tasks` folder
* Can be accessed via `yarn hardhat block-number`

#### tasks/block-number.js

```js
const { task } = require("hardhat/config");

task("block-number", "Prints the current block number").setAction(
  // hre is like importing hardhat, gives access to all functionalities
  async (taskArgs, hre) => {
    const blockNumber = await hre.ethers.provider.getBlockNumber();
    console.log(`Current block number: ${blockNumber}`);
  }
);

module.exports = {};
```

#### hardhat.config.js

```js
// ...
require("./tasks/block-number");
// ...
```

***

### Hardhat Localhost Node

* `yarn hardhat node` spins up a local blockchain node as ganache, gives us accounts and rpc
* The rpc url must be added to hardhat config like before in order to use that localnode

***

### Hardhat console

* let us run interactive commands to interact with blockchain
* `yarn hardhat console --network <network>`

***

### Running Tests

* Hardhat works with `mocha` framework which is a javascript framework for running tests
* `chai` framework is required for `assert and expect` statements
* We can run individual tests using grep pattern matching in `it` description like `yarn hardhat test --grep store`
* We can also use `it.only` keyword which will ignore all other test cases and run only this test case

#### test/test-deploy.js

```js
const { ethers } = require("hardhat");
const { expect, assert } = require("chai");

describe("SimpleStorage", function () {
  let simpleStorageFactory, simpleStorage;

  beforeEach(async function () {
    simpleStorageFactory = await ethers.getContractFactory("SimpleStorage");
    simpleStorage = await simpleStorageFactory.deploy();
  });

  it("Should start with a favorite number of 0", async function () {
    const currentValue = await simpleStorage.retrieve();
    const expectedValue = "0";

    // expect(currentValue.toString()).to.equal(expectedValue)
    assert.equal(currentValue.toString(), expectedValue);
  });

  it("Should update when we call store", async function () {
    const expectedValue = "7"
    const transactionResponse = await simpleStorage.store(expectedValue)
    await transactionResponse.wait(1)

    const currentValue = await simpleStorage.retrieve()
    assert.equal(currentValue.toString(), expectedValue)
  })
});
```

***

### Hardhat Gas Reporter

* Popular hardhat extension to see how much gas our funciton costs
* Automatically gets attached to our tests
* Can also specify which tokens to test gas for

#### hardhat.config.js

```js
require("hardhat-gas-reporter")
// ...
  etherscan: {
    apiKey: ETHERSCAN_API_KEY,
  },
  gasReporter: {
    enabled: true,
    outputFile: "gas-reports.txt",
    noColors: true,
    currency: "USD",
    coinmarketcap: COINMARKETCAP_API_KEY,
    token: "MATIC"
  }
```

***

### Solidity Coverage

* A hardhat plugin that checks how many lines of our .sol code is covered in a test
* Added in `hardhat.config.js` on the top as `require("solidity-coverage")`
* Also generates a folder and file called `coverage` and `coverage.json`

***

### Hardhat Waffle

* Advanced testing framework for solidity by hardhat

***
