Testing Smart Contracts with Ownable Inheritance in Typescript & Hardhat

Testing with ethers.js & Waffle & Typescript & Hardhat

yuichiro aoki
2 min readJul 18, 2021
Photo by Karl Pawlowicz on Unsplash

Today, I will show you some testing examples of smart contracts with ownable inheritance from openzeppelin using Typescript and Hardhat. If you are new to hardhat, this tutorial might help!

A Simple Smart Contract

This is a simple smart contract with ownable inheritance from openzeppelin.

Contracts need the receive function (line 19~ 21) in order to receive ether.

If neither a receive Ether nor a payable fallback function is present, the contract cannot receive Ether through regular transactions and throws an exception.

From solidity documentation

The noReentrant modifier prevent the contract from a known re-entrancy attack. For more info, you can refer to this tutorial.

Let’s Test the Contact!

The example test for above contract is as follows:

Typechain

As I explained in the previous story, you can add typescript bindings for your smart contracts with typechain. This is pretty useful and all you have to do is to install the dependencies and import @typechain/hardhat at hardhat.config.ts. Then when you compile contracts, it will automatically create typescript bindings in typechain folder in the root directory.

ethers.js

You don’t have to import ethers.js because you can get it from hardhat runtime environment (line 3). This is something I like about hardhat😊

Also, if you want to send 1 ether, you do like this.

const transactionHash = await owner.sendTransaction({
to: base.address,
value: ethers.utils.parseEther("1.0"), // Sends exactly 1.0 ether
});

About sendTransaction (ethers.js)

Please make sure you always use BigNumber(data type) to specify the amount of ether in Typescript. Without this, it would return errors because of overflow.

const transactionHash = await owner.sendTransaction({
to: base.address,
value: 1.0 * 10**18, // Don't do this.
});
overflow error

Sending Transactions from different accounts

Here is how you can call functions from different accounts. The withdraw function has onlyOwner modifier, so when addr1(non-owner) call this function, the transaction will fail.

await expect(base.connect(addr1).withdraw(owner.address, ethers.utils.parseEther("1.0")))
.to.be.reverted;

For more: hardhat tutorial

--

--

yuichiro aoki
yuichiro aoki

Written by yuichiro aoki

Ethereum Enthusiast & Software Developer

No responses yet