DEV Community

Turbo Panumarch
Turbo Panumarch

Posted on • Edited on

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! 🥳🥳🥳

Top comments (1)

Collapse
 
fernbryant profile image
FernBryant

informative concept you are sharing with us . i appreciate your work . its helpful for me . lal kitab remedies to control husband