Writing tests for your smart contracts is essential to ensure their functionality and security. Hardhat provides a robust framework for testing, allowing you to write automated tests using JavaScript or TypeScript.

Setting Up Your Hardhat Project

  • First, create a new directory for your project and navigate into it:
  • mkdir my-hardhat-project
    cd my-hardhat-project
  • Initialize a new npm project:
  • npm init -y
  • Install Hardhat:
  • npm install --save-dev hardhat
  • Run Hardhat to create a new project:
  • npx hardhat

    Select "Create an empty hardhat.config.js" when prompted.

Creating Your Smart Contract

In the contracts directory, create a new Solidity file, for example, Token.sol, and define your smart contract:

pragma solidity ^0.8.0;

contract Token {
string public name = "MyToken";
string public symbol = "MTK";
uint256 public totalSupply;
mapping(address => uint256) public balanceOf;

constructor(uint256 _initialSupply) {
totalSupply = _initialSupply;
balanceOf[msg.sender] = _initialSupply;
}

function transfer(address _to, uint256 _amount) public {
require(balanceOf[msg.sender] >= _amount, "Not enough tokens");
balanceOf[msg.sender] -= _amount;
balanceOf[_to] += _amount;
}
}

Writing Tests for Your Smart Contract

Next, create a test directory in your project root and add a new file called Token.js to write your tests:

const { expect } = require("chai");
const { ethers } = require("hardhat");

describe("Token contract", function () {
let hardhatToken;
let owner;
let addr1;
let addr2;

beforeEach(async function () {
const Token = await ethers.getContractFactory("Token");
hardhatToken = await Token.deploy(1000);
[owner, addr1, addr2] = await ethers.getSigners();
});

it("Should assign the total supply of tokens to the owner", async function () {
const ownerBalance = await hardhatToken.balanceOf(owner.address);
expect(await hardhatToken.totalSupply()).to.equal(ownerBalance);
});

it("Should transfer tokens between accounts", async function () {
await hardhatToken.transfer(addr1.address, 50);
expect(await hardhatToken.balanceOf(addr1.address)).to.equal(50);
await hardhatToken.connect(addr1).transfer(addr2.address, 50);
expect(await hardhatToken.balanceOf(addr2.address)).to.equal(50);
});

it("Should fail if sender doesn't have enough tokens", async function () {
const initialOwnerBalance = await hardhatToken.balanceOf(owner.address);
await expect(hardhatToken.connect(addr1).transfer(owner.address, 1)).to.be.revertedWith("Not enough tokens");
expect(await hardhatToken.balanceOf(owner.address)).to.equal(initialOwnerBalance);
});
});

Running Your Tests

To run your tests, execute the following command in your terminal:

npm init -y0

You should see output indicating whether your tests passed or failed. A successful output will look something like this:

npm init -y1

Conclusion

Testing your smart contracts in Hardhat is straightforward and essential for ensuring their reliability. By following the steps outlined above, you can create a robust testing suite for your contracts.