A Concise Hardhat Tutorial : Part 1
Tags: web3, ethereum, solidity, blockchain
Published: 2022-01-10 09:39:35

I prepare this concise and step-by-step tutorial to supplement Hardhat's official [ tutorial](https://hardhat.org/tutorial/) for beginners in Solidity. The tutorial includes an introduction and the following three sections:

1 . Install and init an (empty) sample project
2 . Write ERC20 token with OpenZeppelin
3 . Write ERC72 NFT token

(updated at 03/2023 for **Hardhat V2.13.0** and **Solidity 0.8.18**)

Hardhat is an Ethereum development tool suite which can be used to compile, unit test, debug and deploy smart contracts. Like most Ethereum libraries and tools, Hardhat is written in JavaScript and `Node.js`. Btw, you may also be interested to know `foundry` which is written in Rust.

Let me explain several important features of Hardhat for you before we install Hardhat and use it. 

---

## 0. Introduction

The main component of Hardhat is currently called Hardhat Runner which is a command line tool. 

### Hardhat Runner, Tasks and Plugins

According to Hardhat's documents, it is designed around the concepts of Tasks and Plugins.

- **Tasks**: When we run Hardhat from command line, we run a task. Tasks are used for automation. We can check all the built-in and user-created tasks with `yarn hardhat help`.

- **Plugins**: Plugins of Hardhat are used for integrating other libraries/tools and extending the built-in functionality. It comes with official plugins such as hardhat-ethers, hardhat-waffle, hardhat-ganache, etc. We can also create our own hardhat plugins. 

### Hardhat Network, a local ethereum blockchain testnet

Hardhat comes with a local ethereum blockchain with EVM called **Hardhat Network**. You can run Hardhat Network in two modes: 

- **In-process** local blockchain, an ephemeral ethereum network that is created and destroyed with the process; 

- **Stand-alone** local blockchain, serving JSON-RPC and WebSocket requests. You can start it by running `yarn hardhat node`.

Instead of Hardhat Network, Hardhat can also be used with Ganache, the most known ethereum local blockchain testnet for developers. The Ethereum Virtual Machines (EVMs) in Hardhat Network, Ganache and Remix IDE are all based on `@ethereumjs/vm` EVM implementation. 

Hardhat can also fork mainnet which means "copy the state of the Ethereum mainnet into your local testnet including all balances and deployed contracts." Find more information at: https://hardhat.org/hardhat-network/guides/mainnet-forking.html . 

### Debugging-first: `console.log()`

The first reason why many developers choose Hardhat over Truffle Suite is `console.log()`. Hardhat is debugging-first by providing the most-needed JavaScript style `console.log()` in Solidity for debugging smart contract. It also provides Solidity stack traces and explicit error messages when transactions fail.

Hardhat's unit test uses `Mocha` and `Chai` currently.

### Interactive console

Just as Truffle Suite, Hardhat provides an interactive JavaScript console. We can run Hardhat console by running `yarn hardhat console` or `yarn hardhat console --network localhost`.

I prefer to interact with my contracts step by step using this console during the development process although I surely write scripts.

---

## 1. Install Hardhat and init an (empty) Hardhat Project

In this section, we go through the process of initiating a hardhat project in 6 steps to give you an overall view of how to use Hardhat. Deep explanation of Solidity smart contract and Javascript script is deferred to later sections.

---

### Step 1: Install Node.js and yarn

Hardhat is written in JavaScript using Node.js. To use it, we need `Node.js` and `yarn` (or `npm`) installed.

If needed, you can download and install them from https://nodejs.org/en/. Once Node.js installed, check its version by running:

```bash
node -v
//v19.7.0
```

---

### Step 2: Prepare directory and install Hardhat

We conduct 3 tasks in this step: make a directory; init a Node.js project with `yarn`; and install hardhat as devDependencies in this environment. 

```bash
mkdir hardhat-tut && cd hardhat-tut
yarn init --yes
yarn add hardhat
```

Check the hardhat version:

```bash
yarn hardhat --version
//2.13.0
```

---

### Step 3: Init Hardhat project

When Hardhat is installed, we use Hardhat Runner CLI to init a sample project. Run the following command and choose "Create an advanced sample project that uses TypeScript". 

```bash
yarn hardhat
```

It will init a project and add some dependencies. In the sample project, there are three sub-directories and a configuration file. Let's check it with `tree -I node_modules/ -d -L 1`

```bash
.
├── contracts
├── scripts
└── test
```

Sample smart contract is in the `contracts` dir, unit test file is in the `test` dir, and deploy script is in `scripts` dir.

Now, you can choose your favorite IDE (VS Code for example) to write smart contracts in Solidity as well as unit test and deploy scripts in Javascript.

---

### Step 4: Compile, Test and Deploy

In the basic sample project, there is already a sample smart contract `Lock.sol` in contracts directory as well as unit test script `Lock.ts` and deploy script `deploy.ts` for it. (You may also 
 be interested in the `Greeter.sol` in the previous version of hardhat/Remix.)

The development circle of smart contract is "Compile, Test and Deploy". 

**Compile :**

```bash
yarn hardhat compile
```

**Unit Test :** 

```bash
yarn hardhat test
```

**Deploy:** 

```bash
yarn hardhat run scripts/deploy.ts
//Output: 
Lock with 0.001ETH and unlock timestamp 1679119583 deployed to 0x5FbDB2315678afecb367f032d93F642f64180aa3
```

Please note that the Lock smart contract is deployed to **the in-process blockchain testnet** which is destroyed with the precess. 

If you want to deploy it to another network such as localhost, run `yarn hardhat run scripts/deploy.ts --network localhost`. Let's continue to configure for the standalone Hardhat local blockchain testnet and deploy `Lock.sol` to it. 

---

### Step 5: Config the hardhat project 

The config file is `hardhat.config.ts`. We can configure our hardhat project in it.

```ts
import { HardhatUserConfig } from "hardhat/config";
import "@nomicfoundation/hardhat-toolbox";

const config: HardhatUserConfig = {
  solidity: "0.8.18",
};

export default config;
```

By default, hardhat support stand-alone `localhost` network and in-process `hardhat` network. So to use localhost standalone testnet,  we don't need to do any modification in the configuration file. 

```
{
    localhost: {
      url: "http://127.0.0.1:8545"
    },
    hardhat: {
      // See its defaults
    }
}
```

Let's run a standalone testnet and deploy smart contract to it.

Task ONE: in another terminal, run the testnet:

```bash
yarn hardhat node
```

Output:
```bash
Started HTTP and WebSocket JSON-RPC server at http://127.0.0.1:8545/

Accounts
========
Account #0: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 (10000 ETH)
Private Key: 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
...
```

Task TWO: run deploy script in the localhost:

```bash
yarn hardhat run scripts/deploy.ts --network localhost
//Lock with 0.001ETH and unlock timestamp 1679119754 deployed to 0x5FbDB2315678afecb367f032d93F642f64180aa3
```

In the other terminal, we can see output of the testnet:

```
eth_sendTransaction
  Contract deployment: Lock
  Contract address:    0x5fbdb2315678afecb367f032d93f642f64180aa3
  Transaction:         0x26b0d85de3bf5fa7530264fef2edfc89bd9eaba89730b9c338d4c5b7583ac11f
  From:                0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266
  Value:               0.001 ETH
  Gas used:            326016 of 326016
  Block #1:            0x24288deb19e27e3ba6aa08dec267d4091c228984ec939ea2a9161cb872dbf905
```

If you would like to interact with the smart contract from Hardhat console or MetaMask wallet, you need to run a stand-alone local blockchain and deploy the smart contract to it. 

---

### Note on mnemonic and default accounts

The [default accounts](https://hardhat.org/hardhat-network/reference/#initial-state) with Hardhat are generated with this mnemonic:

```
"test test test test test test test test test test test junk"
```

If you want to use your mnemonic, add it in Hardhat configuration:

```json
    hardhat: {
      accounts:{mnemonic: "your mnemonic"}
    },
```

See more about hardhat configuration at: https://hardhat.org/config/

---

Stand-alone local blockchain testnet serves JSON PRC at http://127.0.0.1:8545/. If you would like to use the Ethereum mainnet, public testnet Sepolia, sidechain like Polygon/BSC or L2 like Optimism/Arbitrum, you may need a RPC provider like [Alchemy](https://www.alchemy.com/ethereum). 

For example, if you would like to use Sepolia, you can add this network in config(via [hardhat docs](https://hardhat.org/hardhat-runner/docs/config)): 

```
module.exports = {
  networks: {
    sepolia: {
      url: "https://eth-sepolia.g.alchemy.com/v2/<apikey>",
      accounts: [privateKey1, privateKey2, ...]
    }
  },
};
```

Change the <apikey> and <privatekeys> to your own.

---

### Step 6: Interact with the deployed smart contact from Hardhat console

Hardhat console is an interactive Javascript console.

To open Hardhat console connecting to localhost blockchain at http://127.0.0.1:8545/ , run:

```bash
yarn hardhat console --network localhost
```

In Hardhat console, you can interact with smart contract using `Ethers.js`. What we use here is the plugin version: [hardhat-ethers](https://hardhat.org/plugins/nomiclabs-hardhat-ethers.html).

```ts
const address = '0x5FbDB2315678afecb367f032d93F642f64180aa3';
const contract = await ethers.getContractAt("Lock", address);

//call withdraw
await contract.withdraw()
```

Response is the transaction receipt:

```
{
  hash: '0x3a0269dc290e47e4001b9a8fd1c0e7a93f4443f6673c62f21d1960e3894fcca2',
  type: 2,
  accessList: [],
  blockHash: '0x24b49f383d7cd24704595ece03abeb9e848b3b0f15fb1484db06c717c73185f3',
  blockNumber: 2,
  transactionIndex: 0,
  confirmations: 1,
  from: '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
  gasPrice: BigNumber { value: "768002200" },
  maxPriorityFeePerGas: BigNumber { value: "0" },
  maxFeePerGas: BigNumber { value: "972002784" },
  gasLimit: BigNumber { value: "36493" },
  to: '0x5FbDB2315678afecb367f032d93F642f64180aa3',
  value: BigNumber { value: "0" },
  nonce: 1,
  data: '0x3ccfd60b',
  r: '0x0ab5399e355a4795535827edb08c55efc63a412176b1fd3977b02923607c4b57',
  s: '0x528706dd1b049ec0ad6ff85d3746e24a4dfbef4447e2b572b0d053ec0be8f28c',
  v: 1,
  creates: null,
  chainId: 31337,
  wait: [Function (anonymous)]
}
```

---

### Note on console.log

You can modify the contract and use `console.log`.

```solidity
// Uncomment this line to use console.log
import "hardhat/console.sol";

    function withdraw() public {
        // Uncomment this line, and the import of "hardhat/console.sol", to print a log in your terminal
        console.log("Unlock time is %o and block timestamp is %o", unlockTime, block.timestamp);
...
   }
```

Run the previous steps again. You may found that there is a console log in the terminal:

```
  console.log:
    Unlock time is '1679121200' and block timestamp is '1679121264'
```

---


### Last Step

At the end of this section, let's terminate the localhost blockchain. 

I usually clean up the project which means to delete cache files and compiling artifacts by running: 

```bash
yarn hardhat clean
```

You can also delete the `node_modules` directory as you can install dependencies by running `yarn` again.

To read the Contract / Unit Test / Deploy files is a good start to understand solidity and hardhat.

```
.
├── contracts
│   └── Lock.sol
├── package.json
├── scripts
│   └── deploy.ts
├── test
│   └── Lock.ts
```

If needed, you can delete the sample contract as well as test and deploy scripts in the corresponding directories. You now have a blank hardhat project to start with.

---

This is Part 1 of a 3-section hardhat tutorial "A Concise Hardhat Tutorial". How to write ERC20 and ERC721 smart contract will be covered in Part 2 and Part 3.

---


### Tutorial List:

#### 1. A Concise Hardhat Tutorial(3 parts) 
https://dev.to/yakult/a-concise-hardhat-tutorial-part-1-7eo

#### 2. Understanding Blockchain with `Ethers.js`(5 parts)
https://dev.to/yakult/01-understanding-blockchain-with-ethersjs-4-tasks-of-basics-and-transfer-5d17

#### 3. Tutorial : build your first DAPP with Remix and Etherscan (7 Tasks)
https://dev.to/yakult/tutorial-build-your-first-dapp-with-remix-and-etherscan-52kf

#### 4. Tutorial: build DApp with Hardhat, React and Ethers.js (6 Tasks)
https://dev.to/yakult/a-tutorial-build-dapp-with-hardhat-react-and-ethersjs-1gmi

#### 5. Tutorial: build DAPP with Web3-React and SWR
https://dev.to/yakult/tutorial-build-dapp-with-web3-react-and-swr-1fb0

#### 6. Tutorial: write upgradeable smart contract (proxy) using OpenZeppelin(7 Tasks)
https://dev.to/yakult/tutorial-write-upgradeable-smart-contract-proxy-contract-with-openzeppelin-1916

#### 7. Tutorial: Build a NFT marketplace DApp like Opensea(5 Tasks)
https://dev.to/yakult/tutorial-build-a-nft-marketplace-dapp-like-opensea-3ng9

---

If you find this tutorial helpful, follow me at Twitter [@fjun99](https://twitter.com/fjun99)