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 月后推荐使用与重入防护结合使用的方法。
通过以下方式防止重新进入
在调用其他合约之前进行所有状态更改
使用重入保护修饰符
<codeclass="language-solidity"><spanclass="hljs-comment">// SPDX-License-Identifier: MIT</span><spanclass="hljs-meta"><spanclass="hljs-keyword">pragma</span><spanclass="hljs-keyword">solidity</span> ^0.8.13;</span><spanclass="hljs-class"><spanclass="hljs-keyword">contract</span><spanclass="hljs-title">ReceiveEther</span></span>{
<spanclass="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><spanclass="hljs-comment">// Function to receive Ether. msg.data must be empty</span><spanclass="hljs-function"><spanclass="hljs-keyword">receive</span>() <spanclass="hljs-title"><spanclass="hljs-keyword">external</span></span><spanclass="hljs-title"><spanclass="hljs-keyword">payable</span></span></span>{}
<spanclass="hljs-comment">// Fallback function is called when msg.data is not empty</span><spanclass="hljs-function"><spanclass="hljs-keyword">fallback</span>() <spanclass="hljs-title"><spanclass="hljs-keyword">external</span></span><spanclass="hljs-title"><spanclass="hljs-keyword">payable</span></span></span>{}
<spanclass="hljs-function"><spanclass="hljs-keyword">function</span><spanclass="hljs-title">getBalance</span>() <spanclass="hljs-title"><spanclass="hljs-keyword">public</span></span><spanclass="hljs-title"><spanclass="hljs-keyword">view</span></span><spanclass="hljs-title"><spanclass="hljs-keyword">returns</span></span> (<spanclass="hljs-params"><spanclass="hljs-keyword">uint</span></span>) </span>{
<spanclass="hljs-keyword">return</span><spanclass="hljs-keyword">address</span>(<spanclass="hljs-built_in">this</span>).<spanclass="hljs-built_in">balance</span>;
}
}
<spanclass="hljs-class"><spanclass="hljs-keyword">contract</span><spanclass="hljs-title">SendEther</span></span>{
<spanclass="hljs-function"><spanclass="hljs-keyword">function</span><spanclass="hljs-title">sendViaTransfer</span>(<spanclass="hljs-params"><spanclass="hljs-keyword">address</span><spanclass="hljs-keyword">payable</span> _to</span>) <spanclass="hljs-title"><spanclass="hljs-keyword">public</span></span><spanclass="hljs-title"><spanclass="hljs-keyword">payable</span></span></span>{
<spanclass="hljs-comment">// This function is no longer recommended for sending Ether.</span>
_to.<spanclass="hljs-built_in">transfer</span>(<spanclass="hljs-built_in">msg</span>.<spanclass="hljs-built_in">value</span>);
}
<spanclass="hljs-function"><spanclass="hljs-keyword">function</span><spanclass="hljs-title">sendViaSend</span>(<spanclass="hljs-params"><spanclass="hljs-keyword">address</span><spanclass="hljs-keyword">payable</span> _to</span>) <spanclass="hljs-title"><spanclass="hljs-keyword">public</span></span><spanclass="hljs-title"><spanclass="hljs-keyword">payable</span></span></span>{
<spanclass="hljs-comment">// Send returns a boolean value indicating success or failure.</span><spanclass="hljs-comment">// This function is not recommended for sending Ether.</span><spanclass="hljs-keyword">bool</span> sent <spanclass="hljs-operator">=</span> _to.<spanclass="hljs-built_in">send</span>(<spanclass="hljs-built_in">msg</span>.<spanclass="hljs-built_in">value</span>);
<spanclass="hljs-built_in">require</span>(sent, <spanclass="hljs-string">"Failed to send Ether"</span>);
}
<spanclass="hljs-function"><spanclass="hljs-keyword">function</span><spanclass="hljs-title">sendViaCall</span>(<spanclass="hljs-params"><spanclass="hljs-keyword">address</span><spanclass="hljs-keyword">payable</span> _to</span>) <spanclass="hljs-title"><spanclass="hljs-keyword">public</span></span><spanclass="hljs-title"><spanclass="hljs-keyword">payable</span></span></span>{
<spanclass="hljs-comment">// Call returns a boolean value indicating success or failure.</span><spanclass="hljs-comment">// This is the current recommended method to use.</span>
(<spanclass="hljs-keyword">bool</span> sent, <spanclass="hljs-keyword">bytes</span><spanclass="hljs-keyword">memory</span> data) <spanclass="hljs-operator">=</span> _to.<spanclass="hljs-built_in">call</span>{<spanclass="hljs-built_in">value</span>: <spanclass="hljs-built_in">msg</span>.<spanclass="hljs-built_in">value</span>}(<spanclass="hljs-string">""</span>);
<spanclass="hljs-built_in">require</span>(sent, <spanclass="hljs-string">"Failed to send Ether"</span>);
}
}