Skip to content

Latest commit

 

History

History
80 lines (55 loc) · 2.64 KB

File metadata and controls

80 lines (55 loc) · 2.64 KB

19. 接收ETH receive和fallback

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 contractfallback()聲明時不需要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 請記得不管有沒有呼叫成功執行了錢都送了喔。沒定義就是報錯誤。

20. 發送 ETH

Solidity有三種方法向其他合約發送ETH,他們是

  • transfer()
  • send()
  • call(),(被鼓勵的用法)