Solidity語言學習筆記————26、回退函式

FLy_鵬程萬里發表於2018-07-02

回退函式(Fallback Function)

一個合約可以有一個匿名函式。此函式不能有引數,不能返回任何值。如果沒有其他函式與給定的函式識別符號匹配,或者如果根本沒有提供資料,將執行一個合約的呼叫。

此外,每當合同接收沒有資料的純Ether時,會執行回退函式。此外,為了接收Ether,回退函式必須標記為payable。如果沒有這樣的函式,合約不能通過常規transactions接收Ether。

在這種情況下,函式呼叫通常只有2300gas可用,所以使回退函式儘可能便宜是很重要的。注意,呼叫回退函式的事務與內部呼叫相比,所需的gas要高得多,因為每個事務都收取額外的21000gas或更多的用於簽名檢查之類。

以下操作將比回退函式消耗更多的gas

  • 寫入storage
  • 建立合約
  • 呼叫一個消耗大量gas的外部函式
  • 傳送Ether

請徹底測試回退函式,以確保在部署合約之前執行消耗小於2300gas

註解
雖然回退函式不能有引數,仍然可以使用msg.data來檢索檢索呼叫的任何payload
警告
直接接收Ether的合約(沒有函式呼叫,即使用sendtransfer),不定義回退函式將丟擲異常並返回Ether(這與Solidity v0.4.0之不同)。因此,如果您希望合約接收Ether,則必須實現回退函式。
警告
沒有payable回退函式的合約可以作為一個coinbase transaction的接收者來接收Ether(又名挖礦獎勵)或selfdestruct的目的地。合約不能對這樣的Ether轉賬作出反應,因此也不能拒絕它們。這是EVM和Solidity的設計選擇。這也意味著,this.balance可以高於合約中實現的一些手工記賬的總和(即有一個計數器在回退函式中更新)。
pragma solidity ^0.4.0;

contract Test {
    // This function is called for all messages sent to
    // this contract (there is no other function).
    // Sending Ether to this contract will cause an exception,
    // because the fallback function does not have the `payable`
    // modifier.
    function() public { x = 1; }
    uint x;
}


// This contract keeps all Ether sent to it with no way
// to get it back.
contract Sink {
    function() public payable { }
}

contract Caller {
    function callTest(Test test) public {
        test.call(0xabcdef01); // hash does not exist
        // results in test.x becoming == 1.

        // The following will not compile, but even
        // if someone sends ether to that contract,
        // the transaction will fail and reject the
        // Ether.
        //test.send(2 ether);
    }
}


相關文章