# 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

***


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://notes.nomanaziz.me/development/blockchain/freecodecamp-course/6.-hardhat.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
