Solidity
支援兩種特殊的回調函數,receive()
和fallback()
,他們主要在兩種情況下被使用:
-
接收ETH
處理合約中不存在的函數呼叫(代理合約proxy contract)
注意
⚠️ :在Solidity 0.6.x版本之前,語法上只有fallback()函數,用來接收用戶發送的ETH時調用以及在被調用函數簽名沒有匹配到時,來調用。0.6版本之後,Solidity才將fallback()函數拆分成receive()和fallback()兩個函數。
receive()
函數是在合約收到ETH轉帳時被呼叫的函數。一個合約最多有一個receive()函數
,宣告方式與一般函數不一樣,不需要function關鍵字:receive() external payable { ... }。
receive()
函數不能有任何的參數,不能傳回任何值,必須包含external和payable。🧑💻 當合約接收ETH的時候,
receive()
會被觸發。receive()
最好不要執行太多的邏輯因為如果別人用send和transfer方法發送ETH的話,gas會限制在2300,receive()
太複雜可能會觸發Out of Gas報錯;如果用call就可以自訂gas執行更複雜的邏輯(這三種發送ETH的方法我們之後會講到)。
範例:
// 定义事件
event Received(address Sender, uint Value);
// 接收ETH时释放Received事件
receive() external payable {
emit Received(msg.sender, msg.value);
}
-
回退函數
fallback()
函數會在呼叫合約不存在的函數時被觸發。
可用於接收ETH,也可用於代理合約proxy contract
。fallback()
聲明時不需要function關鍵字,必須由external修飾,一般也會用payable修飾,用於接收ETH: fallback() external payable { ... }
我們定義一個fallback()函數,被觸發時候會釋放fallbackCalled事件,並輸出msg.sender,msg.value和msg.data:
event fallbackCalled(address Sender, uint Value, bytes Data);
// fallback
fallback() external payable{
emit fallbackCalled(msg.sender, msg.value, msg.data);
}
觸發 receive()
和 fallback()
函數的條件:
接收ETH
|
msg.data是空?
/ \
是 否
/ \
receive()存在? fallback()
/ \
是 否
/ \
receive() fallback()
🧑💻 如果你有定義 receive
, fallback
請記得不管有沒有呼叫成功執行了錢都送了喔。沒定義就是報錯誤。
Solidity
有三種方法向其他合約發送ETH,他們是
transfer()
send()
call()
,(被鼓勵的用法)