Hardhat: How to Test ETH Balance Change.

turboza

Turbo Panumarch

Posted on April 7, 2022

Hardhat: How to Test ETH Balance Change.

UPDATED: May 23, 2022

We can use this quick way to do it. Read more here: https://ethereum-waffle.readthedocs.io/en/latest/matchers.html

expect(() => contract.connect(owner).withdrawAllETH())
  .to.changeEtherBalance(owner, parseEther(10));
Enter fullscreen mode Exit fullscreen mode

Let's say you are implementing the NFT selling contract. And the owner can withdraw the ETH to herself.

Something like this.

// solidity
function withdrawAllETH() onlyOwner {
    uint256 balance = address(this).balance;
    Address.sendValue(payable(owner()), balance);
}
Enter fullscreen mode Exit fullscreen mode

What do we want to test? šŸ§‘ā€šŸ”§

One of them is to check if the owner receive the ETH correctly! šŸ¤‘

Let's do it together! šŸ”„

Note: I am using Hardhat here as a sample of testing.

// javascript
it('owner can withdraw all ETH', async () => {
  // let's say contract has 5 ETH, owner has 10 ETH

  // 1. let's do a withdrawal
  await contract.connect(owner).withdrawAllETH()

  // 2. Now owner should have 15 ETH, right?
  expect(await owner.getBalance()).to.eq(parseEther(15))
})
Enter fullscreen mode Exit fullscreen mode

And when we run it.

āŒ AssertionError: Expected "14999957824852287212" to be equal 15000000000000000000
Enter fullscreen mode Exit fullscreen mode

What the bug!? šŸžšŸžšŸž

The test says the actual balance is 14.999.. ETH not 15 ETH. Well... I forgot to check about the gas spent. But how do we do it?

Thanks to our beloved StackOverflow thread (as always šŸ˜‚), we got a solution.

Gas Spent = Gas Used x Effective Gas Price
Enter fullscreen mode Exit fullscreen mode

And we can get the data from the transaction receipt!

Note: we can use cumulativeGasUsed instead of gasUsed if you want to get the gas spent from the whole block.

The Solution šŸŒŸ

Ok, now I know it, let's do this instead.

// 2nd attempt
it('owner can withdraw all ETH', async () => {
  // let's say contract has 5 ETH, owner has 10 ETH

  // 1. let's do a withdrawal
  const tx = await contract.connect(owner).withdrawAllETH()

  // 2. Let's calculate the gas spent
  const receipt = await tx.wait()
  const gasSpent = receipt.gasUsed.mul(receipt.effectiveGasPrice)

  // 3. Now we know, it is 15 ETH minus by gasSpent! 
  expect(await owner.getBalance()).to.eq(parseEther(15).sub(gasSpent))
})
Enter fullscreen mode Exit fullscreen mode

And when we run it.

āœ” owner can withdraw all ETH
Enter fullscreen mode Exit fullscreen mode

Yey! And now it works! šŸ„³šŸ„³šŸ„³

šŸ’– šŸ’Ŗ šŸ™… šŸš©
turboza
Turbo Panumarch

Posted on April 7, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related