Search code examples
ethereumsoliditytruffle

Cannot empty balance of Solidity contract using Truffle and Ganache


I'm having issues with using Truffle to test that I can withdraw from my contract. It's a very simple test but after the below withdrawBalance function is called. The balance remains the same when I later use web3.eth.getBalance.

I can also see that in Ganache the owner does not receive the ETH.

If I however return the balance from the withdrawBalance method. It is actually 0.

contract Room {
    address public owner = msg.sender;

    function withdrawBalance() public {
        require(msg.sender == owner);
        owner.transfer(this.balance);
    }
}

The test file:

it('should allow withdrawls to original owner', function () {
        var meta;
        return Room.deployed()
            .then(instance => {
                meta = instance;
                return web3.eth.getBalance(meta.address);
            })
            .then((balance) => {
                // Assertion passes as previous test added 6 ETH
                assert.equal(balance.toNumber(), ONE_ETH * 6, 'Contract balance is incorrect.');
                return meta.withdrawBalance.call();
            })
            .then(() => {
                return web3.eth.getBalance(meta.address);
            })
            .then((balance) => {
                // Assertion fails. There is still 6 ETH.
                assert.equal(balance.toNumber(), 0, 'Contract balance is incorrect.');
            });
    });

My questions are:

  1. Is this some sort of race condition with my test? How can I get the balance check to be correct?
  2. Why doesn't the contract owner show the ETH balance in Ganache? Or is it really that the ETH is not being withdrawn.

Solution

  • You are using return meta.withdrawBalance.call(); instead of return meta.withdrawBalance.sendTransaction();.

    .call() is running locally in your EVM and is free. You run all the computations on your own machine and any changes after execution get reverted to the initial state.

    To actually change the state of the blockchain you need to use .sendTransaction(). It costs gas, because miners get rewarded for the computations which they make during execution of your transaction.


    Summarizing:

    ETH is not being withdrawn.