5

I want to use the transfer function to send value to another contract from a contract, however it fails if I set a state variable in the called contract as seen below:

contract Sender {
    function() payable {
    }

    function sendTo(address receiverAddr) {
        var receiver = Receiver(receiverAddr);
        receiver.transfer(this.balance); // This fails
    }
}

contract Receiver {
    bool public received;

    function() payable {
        received = true; 
    }
}

Doing other stuff doesn't cause an error. What is the problem with setting a state variable in the fallback function?

1 Answer 1

5

The problem is that when the fallback function is called by doing receiver.transfer() it will not have the necessary gas to modify the state variable.

According to Solidity docs:

In such a context, there is usually very little gas available to the function call (to be precise, 2300 gas), so it is important to make fallback functions as cheap as possible. Note that the gas required by a transaction (as opposed to an internal call) that invokes the fallback function is much higher, because each transaction charges an additional amount of 21000 gas or more for things like signature checking.

In particular, the following operations will consume more gas than the stipend provided to a fallback function:

Writing to storage
Creating a contract
Calling an external function which consumes a large amount of gas
Sending Ether

If you wanted to have your Sender contract to transfer ether to the Receiver contract, instead of calling receiver.transfer you should implement a function in Receiver that receives ether, like so:

contract Sender {

    function() payable{

    }

    function sendTo(address receiverAddr) payable {
        var receiver = Receiver(receiverAddr);
        receiver.payMe.value(msg.value)();
    }
}

contract Receiver {
    bool public received;

    function() payable{

    }

    function payMe() payable returns(bool success) {
        received = true;
        return true;
    }
}
2
  • In your example the function payMe returns bool, right ? What is the purpose of a transaction to return bool. I thought that transactions would ignore returns since they are async by nature. Commented Oct 19, 2017 at 0:40
  • Actually, other Solidity functions can read a return value even if it's a transaction. In my example above you could do if(receiver.payMe.value(msg.value)()) to do something depending if the payMe function returned true or false. Commented Oct 19, 2017 at 1:13

Your Answer

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

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