solidity错误处理

官方文档:

https://solidity.readthedocs.io/en/develop/control-structures.html#error-handling-assert-require-revert-and-exceptions

 

require和assert方法的区别:

https://ethereum.stackexchange.com/questions/15166/difference-between-require-and-assert-and-the-difference-between-revert-and-thro

 

程序示例:

pragma solidity ^0.4.0;

contract Sharer {
    function sendHalf(address addr) public payable returns (uint balance) {
        require(msg.value % 2 == 0); // Only allow even numbers
        uint balanceBeforeTransfer = this.balance;
        addr.transfer(msg.value / 2);
        // Since transfer throws an exception on failure and
        // cannot call back here, there should be no way for us to
        // still have half of the money.
        assert(this.balance == balanceBeforeTransfer - msg.value / 2);
        return this.balance;
    }
}

 

 

require和assert适用范围:

An assert-style exception is generated in the following situations:

  1. If you access an array at a too large or negative index (i.e. x[i] where >= x.length or 0).
  2. If you access a fixed-length bytesN at a too large or negative index.
  3. If you divide or modulo by zero (e.g. 0 or 23 0).
  4. If you shift by a negative amount.
  5. If you convert a value too big or negative into an enum type.
  6. If you call a zero-initialized variable of internal function type.
  7. If you call assert with an argument that evaluates to false.

require-style exception is generated in the following situations:

  1. Calling throw.
  2. Calling require with an argument that evaluates to false.
  3. If you call a function via a message call but it does not finish properly (i.e. it runs out of gas, has no matching function, or throws an exception itself), except when a low level operation callsenddelegatecall or callcode is used. The low level operations never throw exceptions but indicate failures by returning false.
  4. If you create a contract using the new keyword but the contract creation does not finish properly (see above for the definition of “not finish properly”).
  5. If you perform an external function call targeting a contract that contains no code.
  6. If your contract receives Ether via a public function without payable modifier (including the constructor and the fallback function).
  7. If your contract receives Ether via a public getter function.
  8. If a .transfer() fails.

Internally, Solidity performs a revert operation (instruction 0xfd) for a require-style exception and executes an invalid operation (instruction 0xfe) to throw an assert-style exception. In both cases, this causes the EVM to revert all changes made to the state. The reason for reverting is that there is no safe way to continue execution, because an expected effect did not occur. Because we want to retain the atomicity of transactions, the safest thing to do is to revert all changes and make the whole transaction (or at least call) without effect. Note that assert-style exceptions consume all gas available to the call, while require-style exceptions will not consume any gas starting from the Metropolis release.

 

总得来说,两者都会使EVM回滚交易,不会造成任何变更。require适用于做输入检查,assert用来检查运行时内部错误(比如数组下标越界和除零错误)。require在Solidity Metropolis版本后将不消耗gas,而assert会消耗完所有的gas(gaslimit)。

https://medium.com/taipei-ethereum-meetup/%E6%AF%94%E8%BC%83-require-assert-%E5%92%8C-revert-%E5%8F%8A%E5%85%B6%E9%81%8B%E4%BD%9C%E6%96%B9%E5%BC%8F-30c24d534ce4

posted @ 2018-03-13 12:43  huahuayu  阅读(849)  评论(0编辑  收藏  举报