Hi @Giupi,
This certainly got me thinking and experimenting!!
@mcgrane5 & @thecil : Do you agree with my conclusion, below? Or have I missed something?
Through a process of elimination, I’ve worked out that the line of code that is causing the transaction to revert in Remix (with the error message: out of gas
) is the one setting the withdrawer’s individual balance in the mapping to zero …
However, as far as I could see, there was nothing wrong with this line of code. In fact, quite the opposite: you have correctly set the user’s individual balance in the mapping to zero before transferring their full Ether balance out of the contract to their external address.
I thought, maybe, one or two of the other lines of code in this function could be pushing the gas consumption over the gas limit (which can be adjusted in the Gas Limit field below the Account field in the Deploy & Run Transactions panel in Remix). But this isn’t the case, and no matter how much the gas limit is increased, this doesn’t seem to make any difference.
What’s more, I also couldn’t see any reason why setting balances[msg.sender]
to 1 instead of zero should make any difference to the gas cost.
Out of interest, I tried changing …
balances[msg.sender] = 0;
// to
delete balances[msg.sender];
…which should produce the same effect. But this also triggers the out of gas
error in Remix.
So, I tested your complete function (within a larger Bank contract) using Truffle and Ganache, instead of Remix … and it worked! I used Solidity compiler v.0.8.9. So, this suggests to me that there is most probably a bug in the current version of Remix.
Even the following function triggers the out of gas
error in Remix. This is very strange and makes me even more convinced that there is some kind of bug causing this…
function setBalanceToZero() public {
balances[msg.sender] = 0;
}
Once you’ve completed the section on using Truffle in the 201 course, you’ll be able to see that your withdrawAll() function works fine. However, I would suggest you also make the following amendments, which will also save a small amount of gas…
function withdrawAll() public /*returns (bool _success)*/ {
// Do you use this return value? If not, you should remove it.
require(balances[msg.sender] > 0, "Insufficient funds");
uint _amountToWithdraw = balances[msg.sender];
balances[msg.sender] = 0;
payable(msg.sender).transfer(_amountToWithdraw);
assert(balances[/*payable(*/msg.sender/*)*/] == 0);
// msg.sender doesn't need to be payable to look up the balance in the mapping
emit withdrawSuccessful(/*payable(*/msg.sender/*)*/, _amountToWithdraw);
// msg.sender doesn't need to be payable to emit/log this address as event data
// _success = true;
// Do you use this return value? If not, you should remove it.
}
Let us know if you have any questions