Loading...
Hardhat is a development environment for Ethereum applications. It provides a set of tools and libraries for building, testing, and deploying Ethereum applications. Hardhat is built on top of the Solidity compiler and the Web3.js library, and it integrates with popular testing frameworks such as Mocha and Chai.
One of the main features of Hardhat is its ability to easily spin up a local Ethereum blockchain for testing purposes. This allows developers to test their applications in a realistic environment without the need for a live blockchain.
Hardhat also provides a number of utility functions for deploying and interacting with smart contracts, as well as tools for working with the Ethereum Virtual Machine (EVM). Overall, Hardhat is a powerful and flexible tool for Ethereum development that can help developers build and test their applications more efficiently.
Testing smart contracts is an essential part of the development process, as it helps ensure that the contracts are working as intended and are free of errors. Hardhat is a development environment for Ethereum applications that provides a range of tools and libraries for testing smart contracts.
Testing smart contracts with Hardhat has a number of benefits, including:
Overall, testing smart contracts with Hardhat is a fast, cost-effective, and flexible way to ensure that your contracts are working as intended.
To install hardhat and create a project, you will need Node.js and an IDE to run and tests your smart contracts, preferably VS CODE.\
After downloading and installing both of them, open your terminal and type the below command to install hardhat
npm install -g hardhat
npx hardhat
The hardhat framework consists of the following folders:-
The default folder structure of a Hardhat project is as follows:
The first step, before writing testing scripts will be to write smart contract which we will test. I will take a very basic smart contract so that even beginners can follow but will include all sort of testable parameters like events, and requirements in it.
//SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract ValueContract {
uint public balance;
address public owner;
event AddValue(uint value, uint balance);
event SubValue(uint value, uint balance);
constructor(uint _balance) {
balance = _balance;
owner = msg.sender;
}
function add(uint _value) public {
// this function will ADD value to the balance
balance += _value;
emit AddValue(_value, balance);
}
function subtract(uint _value) public {
// this function will SUBTRACT value from the balance ONLY IF it is called by the owner
require(msg.sender == owner, "You are not the owner");
balance -= _value;
emit SubValue(_value, balance);
}
function getOwner() public view returns (address) {
// this function will return the owner
return owner;
}
}
Let's break down the above code for you.
The contract has the following variables and functions:
Let's start writing our TESTING SCRIPT.
const { expect } = require("chai");
const { ethers } = require("hardhat");
const { loadFixture } = require("@nomicfoundation/hardhat-network-helpers");
describe("ValueContract", () => {
async function deployFunction() {
// we will call this function in our tests to deploy a new contract and add an owner
let contractFactory = await ethers.getContractFactory("ValueContract");
let contract = await contractFactory.deploy(100);
// (await contract).deployed();
const [owner, otherAccount] = await ethers.getSigners();
return { contract, owner, otherAccount };
}
deployFunction();
The code is defining a describe block for a group of tests related to a contract called ValueContract. Within this block, it defines an async function called deployFunction.
The deployFunction function does the following:-
We will write script to test our add() function in our smart contract. The function should take a value and add that to our balance
it("should add value to balance", async () => {
const { contract } = await loadFixture(deployFunction);
await contract.add(50);
const balance = await contract.balance();
expect(balance.toNumber()).to.equal(150);
});
This code defines an it block, which is a single test within the describe block for the ValueContract contract.
The test does the following:
In summary, this test is checking that the add method of the ValueContract contract correctly increments the contract's balance by the specified amount.
TESTING
Go to your terminal and type:-
npx hardhat test
You will see the following result:-
let's move ahead
We will write scripts to test the subtract() function that we declared in the smart contract.
*Note that this subtract function can only be called by the owner
it("should subtract value from balance", async () => {
const { contract, owner } = await loadFixture(deployFunction);
await contract.subtract(25, { from: owner.address });
const balance = await contract.balance();
expect(balance.toNumber()).to.equal(75);
});
The test does the following:
In summary, this test is checking that the subtract method of the ValueContract contract correctly decrements the contract's balance by the specified amount when called by the owner.
TESTING
Go to your terminal and type:-
npx hardhat test
You will see the following result:-
This means BOTH your tests are passing.
We will now write test again for our subtract() function but this time we will call it from ANOTHER account (NOT OWNER ACCOUNT) to verify that the require function is working
it("should not allow non-owners to subtract value from balance", async () => {
const { contract, otherAccount } = await loadFixture(deployFunction);
await expect(
contract.connect(otherAccount).subtract(25)
).to.be.rejectedWith("You are not the owner");
});
The test does the following:
In summary, this test is checking that the subtract method of the ValueContract contract will not allow non-owners to decrement the contract's balance.
TESTING
Go to your terminal and type:-
npx hardhat test
You will see the following result:-
This means all three of your tests are passing successfully
Let's write another script to test whether the ADDVALUE event that we defined is getting triggered or not when we call the add() function.
it("should emit ADDVALUE event", async () => {
const { contract, owner } = await deployFunction();
await contract.add(50);
const balance = await contract.balance();
expect(balance.toNumber()).to.emit(50, balance, "ADDVALUE");
});
The test does the following:
In summary, this test is checking that the ADDVALUE event of the ValueContract contract will be triggered when add function is called.
TESTING
Go to your terminal and type:-
npx hardhat test
You will see the following result:-
This means all four of your tests are passing successfully
Let's write another script to test whether the ADDVALUE event that we defined is getting triggered or not when we call the add() function.
it("should emit SUBVALUE event", async () => {
const { contract, owner } = await deployFunction();
await contract.subtract(25, { from: owner.address });
const balance = await contract.balance();
expect(balance.toNumber()).to.emit(25, balance, "SUBVALUE");
});
The test does the following:
In summary, this test is checking that the SUBVALUE event of the ValueContract contract will be triggered when add function is called.
TESTING
Go to your terminal and type:-
npx hardhat test
You will see the following result:-
This means all five of your tests are passing successfully
Let's check if our getOwner() function is returning the owner
it("should return the owner", async () => {
const { contract, owner } = await deployFunction();
expect(await contract.getOwner()).to.equal(owner.address);
});
The test does the following:
In summary, this test is checking that the getOwner() event of the ValueContract contract will be returning the owner correctly.
TESTING
Go to your terminal and type:-
npx hardhat test
You will see the following result:-
This means ALL of your tests are passing successfully
Here is the link:- https://github.com/moayaan1911/hardhat-testing-dapp-world
Make you you code more smart contracts and test them via hardhat. TESTING is the MOST IMPORTANT part of dapp development. I am saying it again. All the DeFi hacks are happening because of bugs in smart contracts so as a developer you need to make sure that you test your smart contracts for any bugs if possible.
Hello reader, myself MOHAMMAD AYAAN SIDDIQUI from India. I hope you liked the guide. Thank you 🙏🙏 for reading this and if you want a "VIDEO" version of the same, let me know 👍👍
If you want to connect with me, you can find ALL my socials on my linktree:-