The fallback function is just like any other function: it gets as much gas as you pass to it.
What's different about the fallback function is that it's the one invoked when someone does a simple ether transfer, e.g. msg.sender.transfer(amount)
in a smart contract, or a transfer from an exchange, etc. In those cases, very little gas is sent along, so if you want those cases to succeed, you should be careful about what you put in the fallback function.
I think there are other reasons to avoid the fallback function, notably around helping to prevent mistakes. See https://programtheblockchain.com/posts/2017/12/16/be-careful-when-using-the-solidity-fallback-function/.
As an aside, you can simplify that and add a little standards conformance that can be handy in debugging situations.
Remove this
function query() public constant returns (uint balance) {
return balances[msg.sender];
}
function query(address id) public constant returns (uint balance) {
return balances[id];
}
and add public
to mapping(address => uint) public balances;
You'll get a "free" getter function called balances(address)
. You don't get the fancy overload, but you don't really need it for a client to ask about itself.
You can add event logs
event LogDeposit(address sender, uint amount);
event LogRefund(address receiver, uint amount);
(after the mapping would be "normal").
Then you could update your fallback a little (there just be just enough gas).
function() public payable {
balances[msg.sender] += msg.value;
LogDeposit(msg.sender, msg.value);
}
And the other state-changing function:
function refund(uint amountRequested) public returns(bool success) {
require(amountRequested > 0);
require(amountRequested <= balances[msg.sender]);
balances[msg.sender] -= amountRequested;
LogRefund(msg.sender, amountRequested);
msg.sender.transfer(amountRequested);
return true;
}
I took the liberty of breaking the require
up into two blocks and returning a bool. Just a few ideas that can help you and others troubleshoot what's going on.
Hope it helps.
Best Answer
Anyone can call any public function on your contract, by sending a transaction to that contract and including "data" that names that function.
If someone sends a transaction with ether to a function, and the contract did not mark the function as payable, then the call will be rejected. If the contract did mark the function as payable, though, that ether will be deposited into the contract's control. (and whatever code is in the function will run)
The fallback function is called when you send a transaction to a contract, and don't identify any function (in other words, "data" is empty). All the payable rules in the previous paragraph apply. Nothing prevents you from sending 0 ether to the fallback function.