# ALL about sending Ether - Transfer, Call , Send

By [IAMOTI](https://paragraph.com/@iamoti) · 2024-08-30

---

Sending Ether in Solidity: A Comprehensive Technical Guide
==========================================================

Introduction
------------

Sending Ether is a fundamental operation in Ethereum smart contracts. Over time, the recommended methods for transferring Ether have evolved due to security considerations and changes in the Ethereum protocol. This article will explore the three main methods of sending Ether: `transfer()`, `send()`, and `call()`, discussing their technical aspects, pros, cons, and current best practices.

The Three Methods of Sending Ether
----------------------------------

### 1\. transfer()

The `transfer()` function was introduced in later versions of Solidity as a safer alternative for sending Ether.

**Syntax:**

    receivingAddress.transfer(amount);
    

**Key Features:**

*   Has a fixed gas stipend of 2300 gas
    
*   Automatically reverts the transaction if the transfer fails
    
*   Throws an exception on failure, allowing the calling contract to handle the error
    

**Initial Appeal:**

1.  Automatic reversion: If the transfer failed, the transaction would automatically revert.
    
2.  Fixed gas stipend: It forwarded a fixed amount of 2300 gas to the receiving contract.
    

**Limitations and Issues:**

*   The fixed gas stipend can cause problems if gas costs change
    
*   May fail if the receiving contract's fallback function requires more than 2300 gas
    
*   Relies on fixed gas costs, making it vulnerable to network upgrades that change opcode gas costs
    

**Current Status:** No longer recommended due to its reliance on fixed gas costs.

### 2\. send()

The `send()` function is similar to `transfer()` but with slightly different behavior.

**Syntax:**

    bool success = receivingAddress.send(amount);
    

**Key Features:**

*   Also has a fixed gas stipend of 2300 gas
    
*   Returns a boolean indicating success or failure
    
*   Does not automatically revert the transaction on failure
    

**Limitations:**

*   Shares the same gas stipend limitations as `transfer()`
    
*   Requires manual checking of the return value and error handling
    

**Current Status:** Not recommended due to the same issues as `transfer()`.

### 3\. call()

The `call()` function is currently the recommended method for sending Ether.

**Syntax:**

    (bool success, bytes memory data) = receivingAddress.call{value: amount}("");
    

**Key Features:**

*   Allows for customizable gas limits
    
*   Returns a boolean for success/failure and any return data
    
*   More flexible, allowing for function calls along with Ether transfers
    

**Advantages:**

*   Not limited by fixed gas stipends
    
*   Can adapt to changes in gas costs
    
*   Provides more control over the transaction
    
*   Allows transfer of data with ether
    

**Considerations:**

*   Requires careful implementation to prevent re-entrancy attacks
    
*   Needs manual checking of the return value and error handling
    

The Impact of Changing Opcode Gas Costs
---------------------------------------

The fundamental issue with `transfer()` and `send()` lies in their reliance on a fixed gas stipend, which becomes problematic when gas costs for opcodes change. The Ethereum network periodically undergoes upgrades that can alter the gas costs of various operations, including storage operations (SSTORE and SLOAD).

### The Constantinople Upgrade: A Case Study

The Constantinople upgrade in 2019 provides a clear example of how network changes can affect existing smart contracts. This upgrade aimed to optimize the network by reducing gas costs for certain SSTORE operations. While this change was beneficial in many ways, it had an unexpected consequence for contracts relying on `transfer()` and `send()`.

Prior to the upgrade, the 2300 gas stipend was insufficient to perform storage operations, which was seen as a security feature preventing reentrancy attacks. However, the reduced gas costs meant that this stipend could now potentially allow for storage modifications, opening up new attack vectors.

Best Practices for Sending Ether
--------------------------------

Given the lessons learned from the `transfer()` and `send()` deprecation, here are some best practices for sending Ether:

1.  **Use** `call()` instead of `transfer()` or `send()`: This is the current recommendation from the Ethereum community.
    
2.  **Implement reentrancy guards:** When using `call()`, always protect against reentrancy attacks.
    
3.  **Check return values:** Always check the success boolean returned by `call()` and handle failures appropriately.
    
    1.  \*\*Follow the checks-effects-interactions patternn                     \*\*
        

Example Implementation
----------------------

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.0;
    
    contract SafeEtherSender {
        // Reentrancy guard
        bool private locked = false;
    
        modifier noReentrant() {
            require(!locked, "No reentrancy");
            locked = true;
            _;
            locked = false;
        }
    
        function sendEther(address payable _to, uint256 _amount) public payable noReentrant {
            // Perform any necessary checks
            require(_amount <= address(this).balance, "Insufficient balance");
    
            // Use call to send Ether
            (bool success, ) = _to.call{value: _amount}("");
            require(success, "Failed to send Ether");
    
            // Emit an event or perform any post-send operations
            emit EtherSent(_to, _amount);
        }
    
        event EtherSent(address indexed to, uint256 amount);
    }
    

Conclusion
----------

The evolution of Ether sending methods in Solidity serves as an important reminder of the dynamic nature of blockchain networks. While `transfer()` and `send()` were once considered safe methods for sending Ether, changes in the Ethereum protocol have made them less reliable.

The current best practice is to use `call()` with proper safeguards against reentrancy and other potential vulnerabilities. This method offers more flexibility and resilience to network changes, but it requires developers to implement additional security measures.

As the Ethereum ecosystem continues to evolve, it's crucial for developers to create flexible, adaptable smart contracts that can withstand changes in the underlying protocol. By understanding the reasons behind the shift away from `transfer()` and `send()`, and adopting best practices, developers can create more robust and future-proof smart contracts.

Always stay updated with the latest Ethereum security recommendations and be prepared to adapt your code as the ecosystem evolves. Regular audits and updates to smart contracts are essential to ensure they remain secure and functional in the face of network changes.

Reference
---------

[https://solidity-by-example.org/sending-ether/](https://solidity-by-example.org/sending-ether/)

[https://blockchain-academy.hs-mittweida.de/courses/solidity-coding-beginners-to-intermediate/lessons/solidity-2-sending-ether-receiving-ether-emitting-events/topic/sending-ether-send-vs-transfer-vs-call/](https://blockchain-academy.hs-mittweida.de/courses/solidity-coding-beginners-to-intermediate/lessons/solidity-2-sending-ether-receiving-ether-emitting-events/topic/sending-ether-send-vs-transfer-vs-call/)

[https://www.immunebytes.com/blog/transfer-in-solidity-why-you-should-stop-using-it/](https://www.immunebytes.com/blog/transfer-in-solidity-why-you-should-stop-using-it/)

[https://github.com/ethereum/solidity/issues/7455](https://github.com/ethereum/solidity/issues/7455)

2.

---

*Originally published on [IAMOTI](https://paragraph.com/@iamoti/all-about-sending-ether-transfer-call-send)*
