Fallback functions are called when a contract is sent a message with no arguments (or when no function matches), and only has access to 2,300 gas when called from a .send() or .transfer(). If you wish to be able to receive Ether from a .send() or .transfer(), the most you can do in a fallback function is log an event.
This is anti-reentrancy mechanism. What the reentrancy is, here is an entertaining video from DEFCON:
// bad
function() payable { balances[msg.sender] += msg.value; }
// good
function deposit() payable external { balances[msg.sender] += msg.value; }
function() payable { LogDepositReceived(msg.sender); }
When you send ETH to a contract, the fallback function is called...
I need to check what happens if a smart contract calls the fallback function...
contract Fallback {
mapping(address => uint) public contributions;
event LogDepositReceived(address sender, uint value);
function() public payable {
//contributions[msg.sender] = contributions[msg.sender] + msg.value; // THAT THROWS AN ERROR ! ! ! !
emit LogDepositReceived(msg.sender, msg.value);
}
}
contract CallingFallback {
Fallback fallback;
constructor(address _fallback) public {
fallback = Fallback(_fallback);
}
function callFallback() public payable {
address(fallback).transfer(msg.value);
}
}
This is the thing - ask the computer ! ! !
It took me 6 months of effort to reach this stage, where I can simply create a simple demo case... Simple, easy, verified... Don't trust. Verify.