Solidity Minimalist Guide: Sending ETH via Transfer, Send, and Call

·

Introduction

In this guide, we'll explore the three primary methods for sending ETH between contracts in Solidity: transfer(), send(), and call(). Each method has distinct characteristics, making them suitable for different scenarios. We'll focus on best practices and security considerations while ensuring you understand their practical applications.


ReceiveETH Contract

First, let's deploy a ReceiveETH contract to test our ETH transfers. This contract logs incoming ETH transactions and allows us to check its balance.

contract ReceiveETH {
    event Log(uint amount, uint gas); // Logs received ETH and remaining gas

    receive() external payable {
        emit Log(msg.value, gasleft()); // Triggered when ETH is received
    }

    function getBalance() public view returns (uint) {
        return address(this).balance; // Returns the contract's ETH balance
    }
}

After deployment, getBalance() will return 0 since no ETH has been sent yet.


Sending ETH Using Transfer, Send, and Call

1. transfer()

function transferETH(address payable _to, uint256 amount) external payable {
    _to.transfer(amount);
}

2. send()

function sendETH(address payable _to, uint256 amount) external payable {
    bool success = _to.send(amount);
    if (!success) {
        revert SendFailed(); // Custom revert on failure
    }
}

3. call()

function callETH(address payable _to, uint256 amount) external payable {
    (bool success, ) = _to.call{value: amount}("");
    if (!success) {
        revert CallFailed(); // Custom revert on failure
    }
}

👉 Learn more about ETH transfers in Solidity


Key Differences

MethodGas LimitReverts on FailureRecommended Use Case
transfer2300YesSimple transfers
send2300NoLegacy code
callNoneNoComplex interactions

Best Practices

  1. Prefer call(): No gas restrictions and maximum flexibility.
  2. Use transfer() for Simplicity: When you need automatic reverts.
  3. Avoid send(): Manual error handling makes it prone to mistakes.

👉 Explore advanced Solidity techniques


FAQ

Q: Why is call() preferred over transfer()?

A: call() offers no gas restrictions, allowing recipient contracts to execute complex logic. However, always handle its return value to manage failures.

Q: Does transfer() guarantee transaction reverts on failure?

A: Yes, unlike send and call, transfer() automatically reverts, simplifying error handling.

Q: When should I use send()?

A: Almost never—its lack of auto-revert and gas restrictions make it inferior to call() and transfer().


Conclusion

Always test ETH transfer methods in a controlled environment before deploying to mainnet. For further reading, check out our detailed Solidity guides!