区块链系列二十:错误处理

优雅处理错误, 节省gas!

EVM里遇到错误会抛异常, 回滚所有修改。

不要用throw

以前用throw, 现在已经deprecated了, throw会烧光所有gas!

From version 0.4.13 the throw keyword is deprecated and will be phased out in the future.
if(msg.sender != owner) { throw; }

现在可以改成

if(msg.sender != owner) { revert(); }

assert(msg.sender == owner);

require(msg.sender == owner);

require/revert vs assert

require主要用于检查inputs,判断调用外部contracts的返回值等。 revert跟require语义一致, 可以自己用if/else处理更复杂的情况, 一般而言require足够了。

assert表示断言, 一般用于内部检查, 表示绝对不可能(不管input是啥)都不可能发生的事情, 如果发生,肯定是重大bug!

The convenience functions assert and require can be used to check for conditions and throw an exception if the condition is not met. The assert function should only be used to test for internal errors, and to check invariants. The require function should be used to ensure valid conditions, such as inputs, or contract state variables are met, or to validate return values from calls to external contracts. If used properly, analysis tools can evaluate your contract to identify the conditions and function calls which will reach a failing assert. Properly functioning code should never reach a failing assert statement; if this happens there is a bug in your contract which you should fix.

require失败抛异常, 剩下的gas会退给caller。

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.

感觉assert只是方便static analysis和formal verification等用的。

openzeppelin中的SafeMath从assert改为require了

Conclusion

尽量用require, 不要用assert!