Hardhat: An Ethereum Development Environment.

Hardhat: An Ethereum Development Environment.

This article explains Hardhat and how it can be used to create smart contracts. Will also take a look at a simple tutorial to help you get started.

Introduction.

Hardhat is a development environment for Ethereum smart contracts. It allows you to create, debug, test, and deploy smart contracts. It provides all the tools you need to help you debug and test your smart contracts, such as setting up a local node for testing and the ability to write tests within the project quickly.

Need for a development environment.

Deploying smart contracts is a very complex task and can cost you a lot of money if you do it wrong, that's why you need to use a development environment like Hardhat.

It comes with lots of tools out of the box which makes your life easier and increases your productivity as a dApp developer. Hardhat debugging and testing tools allow you to weed out bugs and vulnerabilities in your smart contract before deploying it to a live network.

Creating a Hardhat Project.

There are a few technical requirements before we start. Please install the following:

Once we have those installed, you need to create an npm project by going to an empty folder, running npm init, and following its instructions to install Hardhat. Once your project is ready, you should run:

npm install --save-dev hardhat

To create your Hardhat project, run npx hardhat in your project folder. Let’s create the sample project and go through these steps to try out a sample task and compile, test and deploy the sample contract.

Creating a project.

To create a sample project, run npx hardhat in your project folder. You should see the following prompt:

Choose the JavaScript project and go through these steps to compile, test and deploy the sample contract.

Creating a Contract.

The contracts folder contains Lock.sol, which is a sample contract that consists of a simple digital lock, where users can only withdraw funds after a given period.

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9;

// Import this file to use console.log
import "hardhat/console.sol";

contract Lock {
    uint public unlockTime;
    address payable public owner;

    event Withdrawal(uint amount, uint when);

    constructor(uint _unlockTime) payable {
        require(
            block.timestamp < _unlockTime,
            "Unlock time should be in the future"
        );

        unlockTime = _unlockTime;
        owner = payable(msg.sender);
    }

    function withdraw() public {
        console.log("Unlock time is %o and block timestamp is %o", unlockTime, block.timestamp);

        require(block.timestamp >= unlockTime, "You can't withdraw yet");
        require(msg.sender == owner, "You aren't the owner");

        emit Withdrawal(address(this).balance, block.timestamp);

        owner.transfer(address(this).balance);
    }
}

Setting up the Contract.

  • Go to hardhat.config.js

  • Update the hardhat-config with matic-network-credentials

  • Create .env file in the root to store your private key

  • Go to a node-service provider get a URL link and paste it to the .env file so that your app can interact with the Node of a particular blockchain and help deploy the smart contract. You can generate the HTTPS link by using various Node providers like Alchemy, Infura and more.

require('dotenv').config();
require("@nomiclabs/hardhat-toolbox");
require("@nomiclabs/hardhat-ethers");

const ALCHEMY_API_KEY_URL = process.env.ALCHEMY_API_KEY_URL;
const MUMBAI_PRIVATE_KEY = process.env.MUMBAI_PRIVATE_KEY;

/**
 * @type import('hardhat/config').HardhatUserConfig
 */

module.exports = {
  defaultNetwork: "mumbai",
  networks: {
    hardhat: {
    },
    mumbai: {
      url: ALCHEMY_API_KEY_URL ,
      chainID: 80001,
      accounts: [MUMBAI_PRIVATE_KEY],
    }
  },
  solidity: {
    version: "0.8.9",
    settings: {
      optimizer: {
        enabled: true,
        runs: 200
      }
    }
  },
  paths: {
    sources: "./contracts",
    tests: "./test",
    cache: "./cache",
    artifacts: "./artifacts",
  },
  mocha: {
    timeout: 40000,
  },
};

Compiling the Contract.

To compile the contract, you first need to install the Hardhat Toolbox:

npm install --save-dev @nomicfoundation/hardhat-toolbox

Then, simply run to compile:

npx hardhat compile

Testing the Contract

To run tests with Hardhat, you need to type the following:

npx hardhat test

And this is the expected output you will get:

Deploying on Polygon Network.

Run this command in the root of the project directory:

npx hardhat run scripts/deploy.js --network mumbai

The contract will be deployed on Polygon's Mumbai Testnet, and you can check the deployment status here: https://mumbai.polygonscan.com/.

Congratulations! You have successfully deployed the Smart Contract. Now you can interact with the Smart Contract by building a frontend dApp.

Hardhat Plugins.

Hardhat plugins are extensions that add new functionalities to Hardhat.

Some of the popular Hardhat plugins are:

  • @nomiclabs/hardhat-toolbox: Nomic Foundation's recommended bundle of Hardhat plugins.

  • @nomiclabs/hardhat-ethers: injects ethers.js into Hardhat Runtime Environment.

  • @nomiclabs/hardhat-web3: injects Web3 into Hardhat Runtime Environment.

  • @typechain/hardhat: Zero-config Typechain support for hardhat.

You can explore hardhat plugins on the Hardhat Plugins homepage.

To add a new plugin simply run:

// Go to the terminal of your hardhat project directory.
npm install @nomiclabs/hardhat-ethers

// And then add it by putting the command in "hardhat.config.js" file.
require("@nomiclabs/hardhat-ethers");

Hardhat Folder Structure.

Hardhat has the following folders:

  • artifacts: Folder where smart contract compilation artifacts are stored.

  • cache: Folder used for caching internal data.

  • contracts: Folder for smart contract source code.

  • scripts: Folder where scripts that interact with Hardhat Runtime Environment are stored including script for deploying your smart contracts.

  • test: Folder to store tests.

Hardhat Config.

Hardhat config is stored in hardhat.config.js . Config defines which network and accounts hardhat will use, which version of compiler it will run and can be used to configure custom folder structure or configure tests.

Here is an example of a hardhat config:

module.exports = {
  defaultNetwork: "sepolia",
  networks: {
    hardhat: {
    },
    sepolia: {
      url: "https://eth-sepolia.g.alchemy.com/v2/<key>",
      accounts: [privateKey1, privateKey2, ...]
    }
  },
  solidity: {
    version: "0.8.19",
    settings: {
      optimizer: {
        enabled: true,
        runs: 200
      }
    }
  },
  paths: {
    sources: "./contracts",
    tests: "./test",
    cache: "./cache",
    artifacts: "./artifacts"
  },
  mocha: {
    timeout: 20000
  }
}
  • defaultNetwork: A network that is used by default when you run hardhat.

  • networks: List of blockchain networks you will use,

    • url: URL of the node.

    • accounts: List of accounts you will use to interact with the network.

  • solidity: Solidity compiler configuration.

    • version: Compiler version.

    • settings: An object with the same schema as the settings entry in the Input JSON.

  • path: You can customize the different paths that Hardhat uses by providing an object to the paths field.

    • sources: The directory where your contracts are stored. This path is resolved from the project's root.

    • tests: The directory where your tests are located. This path is resolved from the project's root.

    • cache: The directory used by Hardhat to cache its internal stuff. This path is resolved from the project's root.

    • artifacts: The directory where the compilation artifacts are stored. This path is resolved from the project's root.

  • mocha: You can configure how your tests are run using the mocha entry, which accepts the same options as Mocha.

    • timeout: Timeout in ms for requests sent to the JSON-RPC server. If the request takes longer than this, it will be canceled.

You can read more about Hardhat configuration here: Hardhat Configuration.

Hardhat Tasks.

Hardhat task is a command that automates things like deploying, compiling, testing and more. Hardhat comes with some tasks out of the box, but you can always define your tasks using the same Hardhat API.

// Open hardhat console:
npx hardhat console

// Compile contracts:
npx hardhat compile

// Running tests:
npx hardhat test

//Running scripts (deploying)
npx hardhat run scripts/deploy.js --network mumbai

// Clears cache and deletes all artifacts
npx hardhat clean

// To flatten your smart contract in case it uses imports:
npx hardhat flatten > Contract_flat.sol

// You can explore more built-in tasks by running:
npx hardhat help

// To get full information on a specific task by running
npx hardhat help taskName

Hardhat Debugger.

You can print messages when testing your smart contracts by using console.log().

To do this by importing hardhat/console.sol in your project:

// SPDX-License-Identifier: UNLICENSED
pragma solidity^0.8.9;

import "hardhat/console.sol";
contract Token{
    //...
}

And then add console.log anywhere in your code:

...
function hello() public {
    console.log("Hello World");
}
...

Now add:

await Token.hello();

in your test code and once it reaches this line of code in smart contracts it will print Hello World in the console.

Conclusion

More people will become interested in creating decentralized applications as the demand for dApps rises. Several innovative solutions have emerged as a result of the creation of tools to facilitate blockchain development, including Hardhat.

It only takes a few minutes to install the Hardhat environment, and getting started with a Hardhat project is straightforward. Users have various jobs at their disposal as well as the ability to deploy, compile, and test contracts with just the standard version of the development environment without any plugins.

If you enjoyed this article ❤️, recommend sharing this article with your peers and don't forget to check my social-media handles.

Did you find this article valuable?

Support Mrinmoy Porel by becoming a sponsor. Any amount is appreciated!