[Ethereum] Fallback function uses too much gas

fallback-functionremixsolidity

I wrote this contract but Remix complains that it uses too much gas. What am I doing wrong?

"Fallback function of contract browser/SplitBalance.sol:SplitBalance requires too much gas (40612).
If the fallback function requires more than 2300 gas, the contract cannot receive Ether."

pragma solidity ^0.4.10;

contract SplitBalance{

    address a1;
    address a2;
    uint account1;
    uint account2;

    function SplitBalance(address _a1, address _a2) public{
        a1 = _a1;
        a2 = _a2;
    }

    function withdraw(address _addr) public {
        if (_addr == a1)   
        {
            account1 = 0;
            a1.transfer(account1);
        }
        else if (_addr == a2)   
        {
            account2 = 0;
            a2.transfer(account2);
        }
    }

    function updateAddress1(address newAddress) public {
        if(msg.sender != a1)
           revert();
        a1 = newAddress;
    }

    function updateAddress2(address newAddress) public {
        if(msg.sender != a2)
           revert();
        a2 = newAddress;
    }

    function() payable public { 
        uint amount = msg.value/2;
        account1 = account1 + amount;
        account2 = account2 + amount;
    }
}

Best Answer

The fallback (default/unnamed) function in Solidity only has by default a gas allowance of 2300 gas - which is about enough to create an event log:

If a contract receives Ether (without a function being called), the fallback function is executed. ... During the execution of the fallback function, the contract can only rely on the “gas stipend” (2300 gas) being available to it at that time. This stipend is not enough to access storage in any way.

source solidity documentation

Adding logic like updating Ethereum storage variables in that function will, therefore, not work unless the caller explicitly supplies more gas; as the documentation point out, you can not rely on this extra gas being available during the execution.

One solution would be to move your logic into a new payable function - that is instead called when a user wants to send Ether to the contract; this would replace having the logic in the fallback function (you could then have the fallback function throw if Ether was sent to the contract incorrectly).

Related Topic