常见异常
异常类型
执行合约时,会出现四种类型的异常:
- Assert-style 异常(断言异常)
- Require-style 异常
- Validation-style 异常
- VM illegal-style 异常
Assert-style 异常
下列情况将会产生一个 assert-style 异常,会抛出 invalid opcode 错误,消耗所有的 Entropy(包括当前为止已经消耗的 Entropy 和未消耗的 Entropy, 即 fee_limit)
- 访问数组的索引太大或为负数(例如 x[i] 其中 i >= x.length 或 i < 0)
- 访问固定长度 bytesN 的索引太大或为负数
- 用零当除数做除法或模运算(例如 5 / 0 或 23 % 0 )
- 移位负数位
- 将一个太大或负数值转换为一个枚举类型
- 调用未被初始化的内部函数类型变量
- 调用assert的参数(表达式)最终结果是false
- 合约执行过程中超时
- 发生JVMStackOverFlowException
- 发生OutOfMem异常,即内存超过了3M
- 合约运行过程中,发生了加法等溢出
Require-style 异常
下列情况将会产生一个 require-style 异常,会抛出 revert 错误,仅仅消耗当前为止已经消耗的Entropy,不包括未消耗的 Entropy(fee_limit). 典型错误信息 "REVERT opcode executed".
- 调用throw
- 如果你调用require的参数(表达式)最终结果为false
- 如果你通过消息调用某个函数,但该函数没有正确结束(比如该函数耗尽了 Entropy,或者本身抛出一个异常)。如果调用函数时没有指定Entropy,会把所有Entropy都传进去,表面看来会消耗所有Entropy,只有设置了Entropy值,才能看出差别。该函数不包括低级别的操作call、send、 delegatecall或者callcode 。低级操作不会抛出异常,而通过返回 false 来指示失败。
- 如果你使用new关键字创建合约,但合约没有正确创建(因为创建合约时无法指定Entropy,会把所有Entropy都传进去,表面看来会消耗所有Entropy)
- 如果你的合约通过一个没有payable修饰符的公有函数(包括构造函数、fallback函数和一般的公有函数)接收VS
- transfer() 失败
- 调用revert()
- 到达最大函数栈深64
注:assert-style 和 require-style 这两种情况下,都会导致VVM 回退。回退的原因是不能继续安全地执行,因为没有实现预期的效果。 因为我们想保留交易的原子性,所以最安全的做法是回退所有更改。但是会进行 Entropy扣费。
Validation-style 异常
下列情况将会产生 validation-style 异常,由于这些异常是虚拟机执行前的检测,该类异常交易不会上链,也不会消耗任何 Entropy或 Photon.
- 当前版本不支持虚拟机
- 创建合约的时候,合约名字超出32字节
- 创建合约的时候,消耗调用者资源的比例不在[0, 100]之间
- 创建合约的时候,新生成的合约地址发生了hash冲突,即合约地址已经生成过
- callvalue不为0,如果发生余额不足
- feeLimit不在合法范围之内
- 向不支持constant的节点发送了constant的请求
- trigger的合约在数据库中不存在
VM illegal-style 异常
下列情况会发生一个 VMillegal-style 异常,该类异常交易不会上链,但是会在网络层惩罚发送该交易的节点,断开连接一段时间。
- 创建合约的时候,OwnerAddress 和 OriginAddress 不相等
- 广播了 constant 请求
Updated almost 3 years ago