# 发送以太币（transfer、send、call）

By [kaiming](https://paragraph.com/@kaiming) · 2022-07-28

---

发送以太币（transfer、send、call）
=========================

在以太坊中send, transfer, call都可以进行转账操作，那么他们究竟有什么区别呢？

### 那么如何发送以太币呢？

*   transfer(2300gas，如果失败则throw)
    
*   send(2300gas，如果失败则返回false)
    
*   call(默认情况下将所有可用的gas传输过去，gas传输量可调，如果失败则返回false)
    

### 如何接收以太币？

接收以太币的合约必须至少具有以下功能之一：

*   receieve() external payable
    
*   fallback() external payable
    

如果发送方的msg.data为空，那么将调用receive()，否则调用fallback()。

### send与transfer对比简析

相同之处

1.  均是向目标地址发送以太币（以Wei为单位）
    
2.  发送以太币，都需要消耗固定的2300gas（gas数量少，只允许接收方合约执行最简单的操作）
    

不同之处

1.  send执行失败会返回false，不阻碍程序的运行。transfer执行失败后会抛出异常。
    

    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.10;
    
    contract ReceiveEther {
        /*
        Which function is called, fallback() or receive()?
    
               send Ether
                   |
             msg.data is empty?
                  / \
                yes  no
                /     \
    receive() exists?  fallback()
             /   \
            yes   no
            /      \
        receive()   fallback()
        */
    
        // Function to receive Ether. msg.data must be empty
        receive() external payable {}
    
        // Fallback function is called when msg.data is not empty
        fallback() external payable {}
    
        function getBalance() public view returns (uint) {
            return address(this).balance;
        }
    }
    
    contract SendEther {
        function sendViaTransfer(address payable _to) public payable {
            // This function is no longer recommended for sending Ether.
            _to.transfer(msg.value);
        }
    
        function sendViaSend(address payable _to) public payable {
            // Send returns a boolean value indicating success or failure.
            // This function is not recommended for sending Ether.
            bool sent = _to.send(msg.value);
            require(sent, "Failed to send Ether");
        }
    
        function sendViaCall(address payable _to) public payable {
            // Call returns a boolean value indicating success or failure.
            // This is the current recommended method to use.
            (bool sent, bytes memory data) = _to.call{value: msg.value}("");
            require(sent, "Failed to send Ether");
        }
    }
    

参考资料

[Solidity by Example v 0.8.10](https://web3dao-cn.github.io/solidity-example/)

[细究以太坊中send/transfer/call/delegatecall](https://zhuanlan.zhihu.com/p/35292014)

---

*Originally published on [kaiming](https://paragraph.com/@kaiming/transfer-send-call)*
