https://solidity-by-example.org/sending-ether/

How to send Ether?

You can send Ether to other contracts by

  • transfer
    (2300 gas, throws error)

  • send
    (2300 gas, returns bool)

  • call
    (forward all gas or set gas, returns bool)

How to receive Ether?

A contract receiving Ether must have at least one of the functions below

  • receive() external payable

  • fallback() external payable

receive()
is called if
msg.data
is empty, otherwise
fallback()
is called.

Which method should you use?

call
in combination with re-entrancy guard is the recommended method to use after December 2019.

Guard against re-entrancy by

  • making all state changes before calling other contracts

  • using re-entrancy guard modifier

如何发送以太币?

您可以通过以下方式将以太币发送到其他合约

  • transfer
    (2300 gas,抛出错误)
  • send
    (2300 气体,返回布尔值)
  • call
    (转发所有气体或设置气体,返回布尔值)

如何接收以太币?

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

  • receive() external payable
  • fallback() external payable

receive()
被称为如果
msg.data
为空,否则
fallback()
叫做。

您应该使用哪种方法?

call
2019 年 12 月后推荐使用与重入防护结合使用的方法。

通过以下方式防止重新进入

  • 在调用其他合约之前进行所有状态更改

  • 使用重入保护修饰符

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