深入理解Solidity——回退函数

回退函数(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);
    }
}

上一篇:深入理解Solidity——纯函数

下一篇:深入理解Solidity——函数重载

你可能感兴趣的:(Solidity文档翻译系列,以太坊去中心化应用开发)