Contract Balance and Withdrawal Not Updating from Within Unit Test

Hey guys, I'm trying to implement a function that will withdraw funds from an ERC721 contract. The issue I'm having is that it does not look like the user's balance is changing after withdrawing funds, neither is the contract's balance. I'm not sure if this is typical behavior for unit tests. I've added hardhat logging within the contract's withdraw function and it looks to be withdrawing successful. I'm not sure why this isn't being reflected within the unit test. Might this have something to do with provider = ethers.getDefaultProvider() might I need to use a different provider?

:1234: Code to reproduce

Contract Code

  uint256 public _basePrice = 5 * 10**18;
  function userMint() external payable {
    require(_msgSender() != owner(), "Minter cannot be owner");
    require(msg.value >= _basePrice, "Not enought Matic sent");
    require(_totalSupply < _maxSupply, "Max supply reached");

    uint256 tokenId = _tokenIdCounter.current();
    string memory strTokenId = Strings.toString(tokenId);
    string memory tokenUri = string(abi.encodePacked(_baseUri, strTokenId));
    _safeMint(_msgSender(), tokenId);
    _setTokenURI(tokenId, tokenUri);

  function withdraw() external onlyOwner returns (bool) {
    require(address(this).balance > 0, "Withdrawal exceeds balance.");
    uint256 balance = address(this).balance;
    console.log("balance pre withdraw: %s", balance);
    (bool success, ) ={value: address(this).balance}("");
    console.log("success?: %s", success);
    console.log("balance post withdraw: %s", address(this).balance);
    emit Withdraw(balance);
    return success;

Unit Test

    it("should allow user to mint", async () => {
      console.log('contract balance pre deposit: ', await provider.getBalance(soulables.address))
      tx = await soulables.connect(accounts[1]).userMint({value: ethers.utils.parseEther('50')})
      await tx.wait()

      console.log('contract balance post deposit: ', await provider.getBalance(soulables.address))
      tx = await soulables.getTokenIds(accounts[1].address);
      tx.forEach(async tid => {
      tx = await soulables.tokenURI(1)
      expect(base_uri + '/1').to.equal(tx)

    it("should withdraw funds", async () => {
      console.log('user balance: ', await provider.getBalance(accounts[0].address))
      console.log('contract balance: ', await provider.getBalance(soulables.address))
      tx = await soulables.connect(accounts[0]).withdraw()
      let xtx = await tx.wait()
      console.log(await provider.getBalance(accounts[0].address))

Unit Test Output

      ✓ should mint a token (95ms)
contract balance pre deposit:  BigNumber { value: "42278041630000000001" }
contract balance post deposit:  BigNumber { value: "42278041630000000001" }
      ✓ should allow user to mint (1472ms)
user balance:  BigNumber { value: "11745" }
contract balance:  BigNumber { value: "42278041630000000001" }
balance pre withdraw: 50000000000000000000
success?: true
balance post withdraw: 0
  BigNumber { value: "50000000000000000000" },
  _amount: BigNumber { value: "50000000000000000000" }
BigNumber { value: "11745" }
      ✓ should withdraw funds (1751ms)

:computer: Environment

Solidity: 0.8.7
Framework: Hardhat
Contract Packages:

import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Pausable.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol";
import "@openzeppelin/contracts/utils/Context.sol";
import "@openzeppelin/contracts/utils/Counters.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "@openzeppelin/contracts/utils/Strings.sol";
import "./meta-transactions/ContextMixin.sol";
import "./meta-transactions/NativeMetaTransaction.sol";

I figured it out. The issue is with the provider I was using for the test. Instead of using const provider = ethers.getDefaultProvider() as the provider I use ethers.provider.getBalance(address) and this returns the correct balance. I'm not sure what defaultProvider is doing but if anyone can shed some light on that it would be much appreciated!

ethers.getDefaultProvider() gives you a provider connected to mainnet!

Your tests are running against a local development network.

1 Like

Thanks for the answer! That makes sense. After running the test script several time I got a message about being rate-limited. That was one of the things that made me think I was using the wrong provider.