1

I am trying to play with very simple contract on testnet (ropsten). My contract code is as follows.

contract Bank11{
   mapping(address=>uint) userBalances;
   function getUserBalance(address user) constant returns(uint) {
     return userBalances[user];
   }

   function addToBalance() payable {
     userBalances[msg.sender] = userBalances[msg.sender] + msg.value;
   }
   function withdrawBalance() {
     uint amountToWithdraw = userBalances[msg.sender];
     if (msg.sender.call.value(amountToWithdraw)() == false) {
         throw;
     }
     userBalances[msg.sender] = 0;
   }
}

No problem when I try with run on remix. (Javascript VM Mode) But I've got error every time when I try to call withdrawBalance.

transaction to Bank11.withdrawBalance errored: gas required exceeds allowance or always failing transaction.

I set Gas limit, 3000000. What am I doing wrong??

1
  • What is msg.sender.call.value(amountToWithdraw)() supposed to be? Mar 9, 2018 at 8:43

2 Answers 2

1

what about writing the function in this way?

   function withdrawBalance() {
     uint amountToWithdraw = userBalances[msg.sender];
     userBalances[msg.sender] = 0;

     msg.sender.transfer(amountToWithdraw);
   }

transfer will fail in case you don't have enough balance or any other error and will revert the transaction.

http://solidity.readthedocs.io/en/develop/common-patterns.html

3
  • Thanks..but I already tried this.. transfer, send..also.
    – Kronos
    Mar 9, 2018 at 10:07
  • how you're calling the contract
    – qbsp
    Mar 9, 2018 at 10:10
  • I used remix with web3 provider (Ropsten) network.
    – Kronos
    Mar 9, 2018 at 14:51
1

It seems that the problem is setting the value part of the mapping to 0.

contract Bank11{
   mapping(address=>uint) userBalances;
   function getUserBalance(address user) constant returns(uint) {
     return userBalances[user];
   }

   function addToBalance() payable {
     userBalances[msg.sender] = userBalances[msg.sender] + msg.value;
   }
   function withdrawBalance() {
     uint amountToWithdraw = userBalances[msg.sender];
     if (msg.sender.call.value(amountToWithdraw)() == false) {
         throw;
     }
     userBalances[msg.sender] = 1;
   }
}

This works fine, 1 wei is nothing even compared to gas fees. It's a quick and dirty fix but your contract needs a lot of cleaning anyway, so if you need a quick fix use that, if you want to make something good and robust there's a few things you should change.

  • You shouldn't use if(...){throw;}, use require or assert instead.

  • You didn't do anything to send back the ether to the caller, you should add msg.sender.transfer(amountToWithdraw);

  • You should let the user specify the amount he wants to withdraw, shouldn't you? In case he doesn't want to withdraw everything or nothing

And more generally, you don't need to reinvent the wheel, if you're looking for a banking contract there are tutorials here and here.

6
  • I changed zero to 1 wei. But still I got same error. Am I doing something wrong??
    – Kronos
    Mar 9, 2018 at 15:26
  • @Kronos Well it works fine for me so I don't know what to tell you. I really recommend you try the second tutorial though, it has basically your contract but it works. Mar 9, 2018 at 15:55
  • Thank you for reply. The second tutorial works fine for me. But my code didn't work, even though I changed userBalances[msg.sender] = 1. Do I have to use this.balance always instead of using custom mapping table to handle with ether?
    – Kronos
    Mar 10, 2018 at 1:03
  • @Kronos If I'm not wrong, this.balance returns the balance of the contract, so you still need to map balances to users. Mar 10, 2018 at 1:10
  • Finally, withdraw function is working with injected Web3(Ropsten) environment. The error is occurred with Web3 provider(Ropsten). I am running Ropsten node(geth) on my computer. Something wrong with my node???
    – Kronos
    Mar 10, 2018 at 8:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.