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??

  • What is msg.sender.call.value(amountToWithdraw)() supposed to be? – Teleporting Goat Mar 9 '18 at 8:43
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

  • Thanks..but I already tried this.. transfer, send..also. – Kronos Mar 9 '18 at 10:07
  • how you're calling the contract – mirg Mar 9 '18 at 10:10
  • I used remix with web3 provider (Ropsten) network. – Kronos Mar 9 '18 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.

  • I changed zero to 1 wei. But still I got same error. Am I doing something wrong?? – Kronos Mar 9 '18 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. – Teleporting Goat Mar 9 '18 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 '18 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. – Teleporting Goat Mar 10 '18 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 '18 at 8:49

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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