本文详细介绍了Solidity中的错误处理机制,涵盖了如何使用assert、require和revert函数来管理错误和确保合约的原子性。
Solidity使用状态回退异常来处理错误,这种异常将撤消当前调用所做的所有状态更改,同时向调用者标记错误。
Solidity是一种面向对象的编程语言,用于在以太坊等区块链上实现智能合约,它有许多功能来解决可能在编译时或运行时发生的潜在问题。虽然语法错误检查发生在编译时,但运行时错误难以捕捉,主要发生在合约执行过程中。一些运行时错误的示例包括除以零类型的错误、数组下标超出范围错误等。
实际上,Solidity中的错误处理确保原子性作为一种特性。当智能合约调用以错误终止时,所有状态更改(即对变量、余额等的更改)都会被回退,直到合同调用链的顶端。
重要的一点是,开发者可以通过声明接口直接与其他合约交互。在以太坊区块链上,交易是原子的,意味着交易要么完全完成,要么对状态没有影响,并且被完全回退。
在Solidity中,错误处理原则上由三个 特殊函数 管理:assert、require和revert。 在版本0.4.10之前,Solidity中只有一个throw语句。
Solidity的设计目标是以太坊虚拟机(EVM),受到C++、JavaScript和Python的影响。使用Solidity,开发者可以创建用于投票、众筹、多重签名钱包甚至盲拍的合约。
在实践中,这意味着开发者必须编写多个测试函数来检查基础值并抛出错误,这并不是为gas优化的。在Solidity 0.4.10版本中,引入了新的错误处理构造,asset、require和revert,throw被淘汰。
_require_函数用于在执行之前验证输入和条件。例如,如果条件为false,则require函数立即停止执行。换句话说,require充当一个门控检查修饰符,防止逻辑继续访问函数的进一步执行,从而生成错误。Require非常适合逻辑流门控和验证用户输入。
Require语句声明了运行函数所需满足的先决条件,这些条件应在代码执行之前满足。_require_函数接受一个参数,经过评估后,_require_返回true或false的布尔值。如果因为条件为false而终止执行,未使用的gas会退还给调用者,状态将恢复到原始状态。还可以添加客户字符串消息。
以下是Solidity中require语句的示例:
基本示例展示了如何使用require语句
出于实用原因,开发者可以在以下场景中使用require:
验证来自外部合约的响应
在最终执行之前验证状态条件
验证用户输入
Revert 不会评估任何条件,也不依赖于任何状态或语句。 _revert_语句类似于require语句,因为_revert_函数可以处理与_require_函数相同的错误类型,但更适合复杂的逻辑门控。
如果调用_revert_语句,未使用的gas将被退还,状态会恢复到其原始状态。添加自定义消息的功能与_require_函数相同。
以下是Solidity中_revert_语句的示例:
revert("Something funky has occured");
Assert 是一个检查应该永远不为false的代码的函数,并在防止不可能的场景中发挥重要作用。 如果assert函数返回true的布尔值,则将显示终端错误,程序不会执行。
与_require_和_revert_函数不同,_assert_不会退还任何未使用的gas,相反,_assert_函数将在程序恢复到原始状态之前消耗gas供应。有趣的是,在拜占庭分叉之前,_require_和_assert_函数的行为是相同的,但编译成不同的操作码。
一个值被模或除以零
调用一个零初始化的变量的函数
将一个负值或大值转换为枚举
访问负数或超出预期的索引数组
_assert_语句示例:
assert(num >= 0);
在理论上,_assert_应该比_require_更少使用。开发者应考虑在以下用例中使用_assert_函数:
在进行更改后验证合约状态
避免不可能发生的条件
检查溢出和下溢参数
检查不变量
以下是对所有三种Solidity错误处理函数:require、_revert_和_assert_的简要描述:
用于函数的开始
验证非法输入
在执行之前验证状态条件
退还剩余gas
与require相同
对于更复杂的逻辑流门控(即复杂的if-then块)很有用
退还剩余gas
用于函数的结束
验证不可能的事情
对静态代码分析工具至关重要
不退还剩余gas
- 原文链接: alchemy.com/overviews/so...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!