34

Solidity has a receive keyword. What is it and how do I use it?

1 Answer 1

58

TL;DR

receive is a new keyword in Solidity 0.6.x that is used as a fallback function that is only able to receive ether.

  • receive() external payable — for empty calldata (and any value)
  • fallback() external payable — when no other function matches (not even the receive function). Optionally payable.

Long Answer

Solidity 0.6.x introduced the receive keyword in order to make contracts more explicit when their fallback functions are called. The receive method is used as a fallback function in a contract and is called when ether is sent to a contract with no calldata. If the receive method does not exist, it will use the fallback function.

From the docs:

A contract can have at most one receive function, declared using receive() external payable { ... } (without the function keyword). This function cannot have arguments, cannot return anything and must have external visibility and payable state mutability. It is executed on a call to the contract with empty calldata. This is the function that is executed on plain Ether transfers (e.g. via .send() or .transfer()). If no such function exists, but a payable fallback function exists, the fallback function will be called on a plain Ether transfer. If neither a receive Ether nor a payable fallback function is present, the contract cannot receive Ether through regular transactions and throws an exception.

To use it, you can include it in your contract in the following way:

pragma solidity ^0.6.0;

// This contract keeps all Ether sent to it with no way
// to get it back.
//  This is example code. Do not use it in production.
contract Sink {
    event Received(address, uint);
    receive() external payable {
        emit Received(msg.sender, msg.value);
    }
}

When evaluating whether to use receive or fallback, consider the following:

This is why in version 0.6.x, the fallback function was split into two separate functions:

  • receive() external payable — for empty calldata (and any value)
  • fallback() external payable — when no other function matches (not even the receive function). Optionally payable.

This separation provides an alternative to the fallback function for contracts that want to receive plain ether.

Edit based on Ismael's comment: The 2300 gas stipend required by .send() and .transfer() apply to receive() in the same way that they apply to .transfer(). Additionally, contracts compiled with pre-0.6.0 solc versions are able to interact with the receive() function.

Additional information can be found in the Ethereum blog post here.

7
  • 2
    Are these functions subject to gas stipend of 2300 gas? Are they compatible with previous versions of solidity? ie a contract compiled with an old version solc will be able to make a transfer to contracts compiled with 0.6?
    – Ismael
    Mar 30, 2020 at 20:55
  • 3
    The 2300 gas stipend is a limitation of send and transfer, not of the fallback function. With that said, the 2300 gas stipend behaves the same from the perspective of both fallback() and receive(). Mar 31, 2020 at 15:42
  • 1
    And yes, older contracts (pre 0.6.x) can interact with new contracts that have the receive function. The following gist is what I used to test your questions: gist.github.com/shanefontaine/5bd2a40f6d967748710850d61ebf1bbf Mar 31, 2020 at 15:49
  • 1
    It should be noted that if fallback() gets triggered because no receive() method exists, then in that case fallback() is restricted to 2300 gas, even if .call() was used to send ether.
    – erwaman
    Apr 24, 2020 at 18:18
  • 4
    still confused about when we should use receive or fallback :v
    – Ender
    May 26, 2021 at 1:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.