Learning Objectives – after this chapter you will be able to:
  • Explain when receive() and fallback() are executed.
  • Write both functions with the correct syntax.
  • Explain the 2300 gas stipend and what happens when a contract has neither function.
Special Functions for Receiving Calls and Ether

A contract can declare two special functions that have no name (they are not called by name) and are triggered automatically: receive() for plain Ether transfers and fallback() for calls that do not match any function. Since Solidity 0.6.0 these replace the old unnamed function() payable syntax.

receive()
receive() external payable {
    // runs when Ether is sent with EMPTY calldata
}
  • Called for plain Ether transfers – calls with empty calldata, such as .send(), .transfer() or sending Ether from a wallet.
  • Must be external payable, takes no arguments and returns nothing.
  • A contract can have at most one receive function.
fallback()
fallback() external [payable] {
    // runs when no function matches the call
}
// or, to read the input and return data:
fallback(bytes calldata input) external [payable] returns (bytes memory output) { }
  • Executed when a call does not match any function signature, or when Ether is sent with empty calldata and no receive() exists.
  • Must be external; it is declared with fallback(), either with no parameters or with (bytes calldata) and returning (bytes memory).
  • Must be marked payable if it should accept Ether; otherwise Ether sent to it is rejected.
  • Can be defined only once per contract.
Which Function Runs?
Call arrivesDoes calldata match a function?
YesThat function runs
No – calldata empty?Yes + receive() exists → receive()
Otherwisefallback() (if defined) else the call reverts
Key Points
  • 2300 gas stipend: when Ether is sent with transfer() or send(), only 2300 gas is forwarded – enough to emit a log, but not to write storage. Keep receive/fallback logic very small, or have senders use call.
  • If a contract has neither receive nor a payable fallback, it cannot receive Ether through normal transactions or calls; such transfers revert.
  • A contract can still receive Ether without running code in rare cases – as the recipient of block rewards/fees or of selfdestruct – so never assume address(this).balance equals what your functions recorded.
  • A fallback function is also used by proxy contracts, which forward every unknown call to an implementation contract.
Example : receive and fallback
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

contract Receiver {
    event Received(address from, uint amount);
    event FallbackCalled(address from, uint amount, bytes data);

    receive() external payable {                       // plain Ether, empty calldata
        emit Received(msg.sender, msg.value);
    }

    fallback() external payable {                      // unknown function or data
        emit FallbackCalled(msg.sender, msg.value, msg.data);
    }

    function balance() external view returns (uint) {
        return address(this).balance;
    }
}

contract Sender {
    function sendPlain(address payable to) external payable {
        (bool ok, ) = to.call{value: msg.value}("");               // triggers receive()
        require(ok, "Failed");
    }

    function callUnknown(address payable to) external payable {
        (bool ok, ) = to.call{value: msg.value}(abi.encodeWithSignature("doesNotExist()"));
        require(ok, "Failed");                                      // triggers fallback()
    }
}
Key Takeaways
  • receive() external payable handles plain Ether with empty calldata.
  • fallback() external [payable] handles unmatched calls (and plain Ether when receive is missing).
  • transfer/send forward only 2300 gas – keep these functions minimal.
Download | Print      E-Notes

The PDF E-Notes are the earlier printable version of this chapter. The notes on this page are the latest, revised version.

Question / Answer (15 questions)

Answer : A special unnamed function, declared with fallback() external [payable], that runs when a call does not match any function in the contract, or when Ether is sent with empty calldata and no receive function exists.

Answer : A special function declared as receive() external payable that runs when the contract receives plain Ether with empty calldata, for example via send, transfer or a wallet transfer.

Answer : receive() handles plain Ether transfers with empty calldata and must be payable. fallback() handles calls with data that match no function (and empty-calldata Ether if receive is missing) and is payable only if declared so.

Answer : It must be external and payable, with no arguments and no return value.

Answer : At most one of each.

Answer : The transfer reverts; the contract cannot accept Ether through normal transactions or calls.

Answer : The call reverts, because a fallback that is not marked payable rejects any Ether.

Answer : When Ether is sent with transfer() or send(), only 2300 gas is forwarded to the recipient’s receive or fallback function – enough to log an event but not to write to storage.

Answer : They may be called with only 2300 gas, and complex logic could fail or open security risks such as reentrancy.

Answer : An unnamed function such as function() external payable { }. Since 0.6.0 it is split into receive() and fallback().

Answer : Yes, with the form fallback(bytes calldata input) external returns (bytes memory output); otherwise msg.data can be read inside a fallback with no parameters.

Answer : Yes, in special cases such as being the recipient of selfdestruct or of block rewards/fees. Therefore address(this).balance should not be assumed to equal internally recorded deposits.

Answer : A proxy’s fallback receives every call that does not match its own functions and forwards it (usually with delegatecall) to an implementation contract, enabling upgradeable contracts.

Answer : Receiver’s fallback(), because the calldata encodes doesNotExist(), which matches no function in Receiver.

Answer : Receiver’s receive(), because the call has empty calldata and carries Ether.
MCQ Test : Check Your Understanding (5 questions)

Select an option and press Check Answer, or answer all questions and press Submit Test to see your score. Each answer comes with an explanation.

Q1. A plain Ether transfer with empty calldata to a contract that has receive() runs:

Show Answer

Correct Answer : A. receive()
Empty calldata + Ether goes to receive().

Q2. A call to a function name that does not exist in the contract runs:

Show Answer

Correct Answer : C. fallback()
Unmatched calls go to fallback().

Q3. receive() must be declared as:

Show Answer

Correct Answer : D. external payable
receive() external payable is mandatory.

Q4. How much gas do transfer() and send() forward to the recipient?

Show Answer

Correct Answer : D. 2300
They forward a 2300 gas stipend.

Q5. If a contract has neither receive() nor a payable fallback(), sending it plain Ether will:

Show Answer

Correct Answer : B. Revert
The contract cannot accept Ether normally.

Bibliography/References

The notes, questions and MCQs on this page are original explanations written for this course. The works listed below were consulted and are cited for attribution and further reading. Product names, logos and trademarks belong to their respective owners. Short quotations, where used, are marked and attributed.

  1. Solidity Team. (n.d.). Contracts (creating contracts, visibility and getters, function modifiers, constant and immutable, functions, events, custom errors, inheritance, abstract contracts, interfaces, libraries). Solidity Documentation. https://docs.soliditylang.org/en/latest/contracts.html
  2. Solidity Team. (n.d.). Security Considerations. Solidity Documentation. https://docs.soliditylang.org/en/latest/security-considerations.html
  3. GeeksforGeeks. (n.d.). Solidity – Fall Back Function. https://www.geeksforgeeks.org/solidity-fall-back-function/
  4. Modi, R. (2018). Solidity Programming Essentials: A beginner’s guide to build smart contracts for Ethereum and blockchain. Packt Publishing. ISBN 978-1-78883-138-3.