Track 4 · Solidity foundations · lesson 11
Receiving and sending ETH
11 min
Track 4 · Solidity foundations · lesson 11
11 min
Until now your contracts have moved numbers. This one moves money.
Notice what the second test checks: the contract's actual ETH balance. The deposit is not bookkeeping — real value moved.
A contract's ETH balance goes up the instant a payable call succeeds, whether or
not you write anything down. Forgetting deposits[msg.sender] += msg.value;
does not lose the ETH — it loses the record of who owns it, which means
nobody can ever withdraw it.
Money in a contract with no way out is the most common form of permanent loss on Ethereum.
Three ways to send ETH, and the differences matter:
payable(who).transfer(amount); // 2300 gas, reverts on failure
payable(who).send(amount); // 2300 gas, returns false
(bool ok, ) = who.call{value: amount}(""); // all gas, returns false
Use call, and check the result. transfer and send forward only 2300
gas, which was once a reentrancy safeguard but now breaks legitimately — any
recipient that is a contract doing more than the bare minimum will fail.
(bool ok, ) = msg.sender.call{value: amount}("");
require(ok, "transfer failed");
Predict
A plain ETH transfer with no data goes to receive(). A call to a function that
does not exist goes to fallback().
receive() external payable {}
fallback() external payable {}
Without one of these, sending plain ETH to your contract reverts. That is usually the right default — it stops funds arriving somewhere nothing is prepared to handle them.
Check