Overview
When we talk about “Hardhat” the first thing that comes to our mind is “A protective gear we wear for safety purposes” Similarly In Blockchain “Hardhat” is the development environment for Ethereum software which is secure and Impenetrable. Hardhat is a development environment that is built with Nodejs. In Ethereum, blockchain developers create a smart contract that enables to build of complex applications. So when we want to test, create and debug our applications how can we do it? So the solution is “Hardhat” that is a development environment for developers to test, create, deploy and debug their contract easily.
What is hardhat?
A Hardhat is a tool launched by Nomic Foundation in 2019 and supported by Ethereum Foundation. HardHat is open source but for users who don’t want to experience performance issues it is actively maintained.Therefore It has a massive community.HardHat consists of discrete components for the testing, compiling, deploying, and debugging of smart contracts and decentralized apps which all work together to generate a perfect development component. In Hardhat most important part is Hardhat Runner which is CLI(Command Line Interface) which is interact with Hardhat. Hardhat Runner is an flexible and extensible task runner that helps us to provide as well as automate the rotative tasks Underlying developing smart contracts and dApps. When working with Hardhat, Developers don’t need to switch to Nodejs and Javascript individually.
What makes Hardhat different from Truffle?
HardHat is flexible when running tests and deploying contracts because we can create our own personalized scripts.Hardhat has several plugins which extend plugin functionality. Hardhat has a console.log method for error handling and testing and with the help of Truffle we should create our events to test our contract. In Truffle smart contracts interact with the web3.js library whereas Ethers.js is the default library for Hardhat. Hardhat is a bit more user-friendly and easier to use that is why most developers are using Ethers.js over to Web3.js.
How to install Hardhat?
Before creating a project you first need to install hardhat. In a Developer Project, HardHat is used through a local installation. Hardhat takes a few minutes for the installation. Let’s start to install the hardhat package one by one.
Step 1: Create an empty folder and initialize the npm project and run:
npm init
npm install --save-dev hardhat
Step 2: once the installation is done just run the command:
npx hardhat
- select Create a JavaScript project
Step 3: Now folder structure looks like this:
Deploy Smart contract on HardHat
Step 1. Create Demo project using HardHat:
Now as we can see above all the commands are successfully running Let’s head to our next step of Hard Hat.
- The hardhat environment is almost ready only & we need to install other dependencies in hardhat.config.js :
npm i --save-dev @nomiclabs/hardhat-ethers ethers chai
Ethers.js is used to connect with the smart contract and chai is a library of hardhat and open hardhat.config.js and writes a code below:
2. In our contract directory first create a solidity contract with file named ERC20.sol
pragma solidity ^0.8.0; import "hardhat/console.sol"; contract ERC20 { string public name = "ERC20"; string public symbol = "ER"; uint256 public decimal = 100; uint256 public totalSupply_ = 1000; mapping(address => uint256) balances; event Transfer(address indexed from, address indexed to, uint256 tokens); constructor() { balances[msg.sender] = totalSupply_; } // show total supply function totalSupply() external view returns (uint256) { console.log("total supply %d is token", totalSupply_); return totalSupply_; } // show details of balance in your account function balanceOf(address account) external view returns (uint256) { console.log("balance of account %d is :", balances[account]); return balances[account]; } // after some time if you add amount in total supply function mint(uint256 _qty) public returns (uint256) { totalSupply_ += _qty; // increase token balances[msg.sender] += _qty; console.log("Qty is %d :", _qty); console.log("totalSupply_ is %d", totalSupply_); console.log("balance [msg.sender] is %d", balances[msg.sender]); return totalSupply_; } // transfer the amount to recipient at that time balance is minus from total balance in sender and receiver's balance increment function transfer(address recipient, uint256 amount) external returns (bool) { require(amount <= balances[msg.sender]); console.log("sender balance %s token is:", balances[msg.sender]); console.log("sender balance %s address is:", amount, recipient); balances[msg.sender] -= amount; balances[recipient] += amount; emit Transfer(msg.sender, recipient, amount); return true; } }
Run this file command:
npx hardhat compile
3. Testing of contract createERC20.js file in test directory:
- [owner, address1, address2, …address] = await ethers.getSigners();
In ethers.js signer is an object that represents an Ethereum account. It is used to send transactions from one account to another account.
- const { ethers } = require(“hardhat”);
ethers is a variable in global scope.
- Token = await ethers.getContractFactory(“ERC20”);
getContractFactory is used to deploy the smart contract. so here token is an object of our token contract.
- hardhatToken = await Token.deploy();
deploy() calling on the contract factory will start deployment. An object that has a method for each smart contract function.
const { expect } = require("chai"); const { ethers } = require("hardhat"); describe("ERC20", function () { let Token,hardhatToken,owner; let address1,address2,address; beforeEach(async function () { Token = await ethers.getContractFactory("ERC20"); [owner, address1, address2, ...address] = await ethers.getSigners(); hardhatToken = await Token.deploy(); }); describe("Deployment", function () { it("Right TotalSupply ", async function () { const supply = await hardhatToken.balanceOf(owner.address); expect(await hardhatToken.totalSupply()).to.equal(supply); }); }); describe("Transfer between 2 address", function () { it("transfer data between 2 address", async function () { await hardhatToken.transfer(address1.address, 100); const addressBalance = await hardhatToken.balanceOf(address1.address); expect(addressBalance).to.equal(100); await hardhatToken.connect(address1).transfer(address2.address, 100); // address 2 const addressBalance2 = await hardhatToken.balanceOf(address2.address); expect(addressBalance2).to.equal(100); // Sender not have much balance it("Sender not have much balance", async function () { const startOwnerBalance = await hardhatToken.balanceOf(owner.address, 1); await expect(hardhatToken.connect(address1).Transfer(owner.address, 1).to.be.revertdWith("not enough")); expect(await hardhatToken.balanceOf(owner.address)).to.equal( startOwnerBalance); }); it("update balance after transfer token", async function () { const startOwnerBalance = await hardhatToken.balanceOf(owner.address); await hardhatToken.Transfer(address1.address, 100); await hardhatToken.Transfer(address2.address, 50); const finalOwnerBalance = await hardhatToken.balanceOf(owner.address); expect(finalOwnerBalance).to.equal(startOwnerBalance - 50); const addBalance1 = await hardhatToken.balanceOf(address1.address); expect(addBalance1).to.equal(50); const addBalance2 = await hardhatToken.balanceOf(address2.address); expect(addBalance2).to.equal(100); }); }); }); describe("Transaction", function () { it("transfer token between 2 address", async function () { await hardhatToken.transfer(address1.address, 50); // owner account to address1 const addBalance = await hardhatToken.balanceOf(address1.address); expect(addBalance).to.equal(50); await hardhatToken.connect(address1).transfer(address2.address, 50); const add2Balance = await hardhatToken.balanceOf(address2.address); expect(add2Balance).to.equal(50); // when the sender doesn't have much balance it("sender not have much more balance", async function () { const startOwnerBalance = await hardhatToken.balanceOf(owner.address); await expect( hardhatToken.connect(address1).Transfer(owner.address, 1),to.be.revertdWith("not enough")); expect(await hardhatToken.balanceOf(owner.address)).to.equal(startOwnerBalance ); }); it("Mint token", async function () { const startOwnerBalance = await hardhatToken.Mint(owner.address); await hardhatToken.Mint(address1.address, 50); const finalOwnerBalance = await hardhatToken.Mint(100); expect(finalOwnerBalance).to.equal(startOwnerBalance + 50); const addBalance1 = await hardhatToken.Transfer(address1.address); expect(addBalance1).to.equal(0); }); }); }); });
A command for running this file:
npx hardhat test
4. Deploy the deploy.js file in the scripts directory:
async function main() { const [deployer] = await ethers.getSigners(); const Token = await ethers.getContractFactory("ERC20"); const token = await Token.deploy(); console.log("ERC20 Token ADDRESS", token.address); } main() .then(() => process.exit(0)) .catch((error) => { console.log(error); process.exit(1); });
A command for running this file:
npx hardhat run scripts/deploy.js
So, the contract is deployed, and above is the token address. In this way, we can write, test, deploy and compile the smart contract using Hardhat
Blockchain SolutionsGet Expert Assistance
Conclusion
In this blog, we have discovered HardHat, What makes Hardhat different from Truffle, and how to create, debug, deploy and test our smart contract using hardhat with the command line.