[ad_1]
In this article I will go through my first experience testing with Hardhat, how to connect and interact with the deployed contract in your tests.
In Smart Contract development like in any other development, when your knowledge is basic you depend a lot on the research you make online to solve the issues you are having in order to make it work on your machine.
That’s the everyday for devs, right? Nothing new.
The problem for us noobs is that we read a stack overflow answer or any other piece of documentation that seems right and we are most likely going to accept it as the potential solution to our question.
Well, I had to create a few tests for a Smart Contract that I created and deployed (see how to deploy it in my previous article https://medium.com/coinmonks/hardhat-1-deploying-smart-contracts-f35af00726d9).
I’m sure we can agree that when you are on your own it’s hard
Let’s be frank, I had a lot of issues and I am going to share the problems I had and what actually worked, so I can save you some time.
So, as mentioned in the previous article, I wrote an ERC20 smart contract, so in order to test it I need a few accounts in order to be able to transfer ether, etc.
Wait, accounts? So, do I need to connect somehow Metamask to my code and somehow use it from there?
Not really, here is where our dive into Ethers.js docs starts. First stop Signers.
A Signer in Ethers.js is an object that represents an Ethereum account. It’s used to send transactions to contracts and other accounts.
In order to create your account objects you need to write the following:
[deployer, user1, user2, user3] = await ethers.getSigners()
where deployer and user1, etc are our defined Signers with which we will interact with our ERC20 contract.
Speaking of ERC20 contract, how about I show you the mint()
function I’ve implemented in my Token.sol
?
function mint(address _to, uint _amount) external {
require(msg.sender == owner);
_mint(_to, _amount);
}
Would you know how to call this function in our test?
Well, I didn’t (either).
Remember from the previous post where I mentioned how important it is to deploy the contract to a this.token
variable? So, this is what we need to access the functions inside our contract.
But wait a minute, it is the owner only the one that can mint!!??!?! How, where should I specify that? How to call this function as the owner?
I can tell you that it is kind of complicated to figure this out from the documentation, but I was lucky to find out thanks to the exercise from the Smart Contract Hacking course by Johnny Time (feel free to find out more about it here).
Where to specify the owner? Inside ethers.getContractFactory()
. How? Like this:
let TokenFactory = await ethers.getContractFactory(
'Token',
deployer
);
in this case our deployer (Signer) is specified as contract owner. (Leave some claps if this was useful for you, let’s make this more visible to others).
So, to answer the above question, how to call mint()
function from our tests? Like this:
await this.token.mint(deployerAddress, DEPLOYER_MINT)
Fantastic. Right?
Now, considering the fact that calling the function like that it will always be executed by one specific address (the owner), we get to the following issue.
What if I want to test that user2 makes a transfer to user3?
That’s where Ethers.js helps us again providing connect()
. So, without further ado, this is how you would call it:
this.token.connect(user2).transfer(user3.address, FIRST_TRANSFER)
Easy and beautiful, right? mmm.. right???
Do you want to know a secret? That line there will not work because it needs a special keyword. It comes from javascript async functions and it’s called await
. Yes, you will have to remember this. You have to, please, because I didn’t already a few times, and it’s a pain to find out after a few hours.
await this.token.connect(user2).transfer(user3.address, FIRST_TRANSFER)
Every time we make a call to the contract we have to make sure we wait for it to finish before proceeding further.
[ad_2]
Source link