本文介绍了以太坊智能合约中常见的运行时错误(如执行回滚、gas不足、无效跳转等)和逻辑错误(如重入攻击),并详细介绍了如何使用Tenderly Debugger工具来调试这些错误,包括查找错误代码行、分析变量值、追踪函数调用等,旨在帮助开发者更有效地识别和解决智能合约中的问题。
想知道一些最常见的智能合约错误是什么,以及如果它们发生在你身上该怎么办吗?深入了解运行时和逻辑错误,并学习如何使用 Tenderly Debugger 修复它们。
与 Web2 中的调试过程不同,在 Web3 中处理代码错误和找到根本原因非常耗时。这不仅让工程师感到疲惫,而且对以太坊社区来说也代价高昂。幸运的是,随着以太坊的采用持续增长,可以大大简化和加速调试的选项数量也在增加。
借助用于调试 Solidity 智能合约的先进工具,你可以轻松识别特定交易或合约执行失败的原因。一旦你确定了导致特定问题的错误类型,并收集了有关错误性质的深入信息,你就可以实施适当的解决方案。
🔥 最新动态
使用具有实际链上数据的 Tenderly Virtual TestNets 构建和测试真实的合约和协议集成。在几毫秒内启动托管的、协作的开发环境。在来自 80 多个网络的生产数据之上构建,并内置了浏览器和调试工具。
对于 Solidity 智能合约而言,运行时和逻辑错误是工程师在编写或执行代码时最常遇到的问题。
运行时错误发生在以太坊区块链上部署智能合约代码之后。在运行时错误的情况下,以太坊虚拟机 (EVM) 可能会将你的代码识别为有缺陷的,或者认为你正在运行与智能合约逻辑相悖的交易。运行时错误发生在智能合约执行期间。
典型的运行时错误包括以下几种:
1. 执行回滚 错误:当被调用的智能合约决定阻止进一步执行与其业务逻辑相悖的交易时,会发生这种错误。智能合约代码通常包含对各种所需条件的检查。如果交易未能满足哪怕一个条件,合约会认为其无效并回滚其执行。
在这些错误的情况下,智能合约的作者会故意引入它们,以此作为拒绝无效交易的一种方式。通过使用 requirement 语句,开发人员可以确保交易满足某些逻辑标准。这样,他们可以防止更严重的问题发生。
例如,只有在调用时转移了特定数量的以太币时,智能合约才会执行。如果交易包含不同的金额,它将被回滚。从交易发送者的角度来看,这是一个错误,但从合约的角度来看,这实际上是对无效交易的有效响应。
当你尝试转移代币,即使你没有任何代币时,你也会遇到这种类型的错误。在智能合约代码中,这些错误以以下方式实现:`require(myTokens >=0, “Insufficient amount of tokens”)`。
2. Gas耗尽 错误:当你没有足够的 ETH/Gwei 来支付运行交易的 gas 费用时,会发生这种错误。
3. 无效 JUMP 错误:是另一种类型的运行时错误。如果你尝试调用被调用合约中不存在的函数,或者如果你在编写内联汇编时跳转到不是有效 JUMP 目的地的地址,则会发生这种情况。
5. 堆栈溢出 错误:最常见的是在你尝试递归调用函数且永远无法满足终止条件时发生。在 Solidity 智能合约的情况下,由于 Solidity 堆栈帧的限制,递归函数只能发生 1024 次。如果你执行递归函数的次数超过这个限制,将发生堆栈溢出错误。
6. 堆栈下溢 错误:将发生在执行汇编代码时。如果内联汇编代码尝试在空堆栈上执行 POP,则会发生此错误。
7. 最后,还有不太常见的 无效操作码错误。当 EVM 在遇到与智能合约不兼容的情况时变得“困惑”时,会发生这种错误。例如,当使用与网络期望的版本不同的编译器版本时,就会发生这种情况。
处理调试过程的一个简单方法是使用 Tenderly Debugger。此工具简化了智能合约的调试,因为它允许你轻松识别发生错误的确切代码行,并分析局部变量和状态变量的值。这可以帮助你提出甚至尝试可能的解决方案,以修复代码中的错误或将你的交易更改为将成功执行的新交易。
你可以通过 注册 Tenderly 并设置你的帐户来轻松访问 Debugger。注册后,你会在左侧找到 Transaction 选项卡,你可以从中访问此功能。访问 Tenderly Debugger 的另一种快速方法是 安装 Chrome 扩展程序,这将使你能够直接从区块浏览器在 Tenderly 中打开任何交易。
进入 Tenderly 后,你可以开始剖析代码并调试 Solidity 智能合约。
Tenderly Debugger 将清楚地显示导致交易失败的错误类型。在这种情况下,将显示“执行错误”消息。你将获得易于理解但详细的信息,说明错误发生的原因。
当你打开我们的 Solidity Debugger 时,堆栈跟踪 部分概述了导致错误发生的函数调用序列以及发生错误的确切代码行。你可以使用 执行跟踪 将错误追溯到其根源,从而更深入地了解原因。
在这里,你可以在 函数跟踪 和 调用跟踪 之间切换以过滤相关调用。最后,底部的部分允许你完全理解你正在检查的 EVM 指令。
单击 Debug Error 按钮后,你可以开始分析代码并确定可能的解决方案。对于执行回滚错误,上面导航菜单中的 State Changes 选项卡也可能很有用,因为它显示了智能合约中所有状态更改的概述。
Gas耗尽错误也已明确标记,并提供了有关交易 gas 使用情况的精确信息。
进入 Tenderly 后,你可以轻松采取措施优化你的智能合约并 降低 gas 费用 以用于将来的交易。为此,你可以使用 Gas Profiler 准确了解你的交易中每个函数调用花费了多少 gas。
火焰图为你提供了一个可视化表示,因此你可以轻松浏览交易函数成本。在获得深入信息后,你将确切地知道要优化哪些函数以减少 gas 使用量。
你可以使用 Tenderly Debugger 来理解这些错误,就像你使用它来调试执行回滚错误一样——该工具的工作方式完全相同。唯一的区别是这些类型的错误是由 EVM 触发的,因为它们违反了 EVM 规范。
当智能合约存在漏洞并且代码以意想不到且最有可能是不需要的方式(没有失败)执行时,会发生逻辑错误。这使得智能合约容易受到可能的黑客攻击。这些错误通常是由于开发过程中出现的错误和疏忽造成的。
在逻辑错误的情况下,EVM 甚至不会将智能合约代码注册为有缺陷的,因为它可以在链上正确执行它。实际上,这些错误来自具有不良且通常无法预测的结果的成功交易。
此类错误的一个例子是众所周知的 DAO 重入攻击,由于开发错误,黑客能够窃取价值 7000 万美元的以太币。智能合约逻辑背后的工程师在转移 ETH 之前没有更新用户余额。虽然 重入攻击基于一个简单的错误,但恶意的 编码人员仍然使用它来窃取有价值的资产。
另一个例子是 Cream Finance 攻击,其中包含更复杂的逻辑错误。在此次黑客攻击中,攻击者能够窃取价值 1.3 亿美元的资产。
如果你建立一个高效的调试框架,就有可能避免如此巨大的损失。Tenderly Debugger 使你可以快速响应黑客攻击,识别根本原因并朝着可能的解决方案努力。你可以通过组合以下功能来调试使你的智能合约容易受到攻击的逻辑错误:
函数跟踪:当需要深入了解代码逻辑时,这是你的首选工具。
它按顺序地列出了智能合约中的内部和外部调用,使你可以逐步完成交易。函数跟踪使你可以深入了解每段代码的执行方式。
你还可以轻松识别调用者和合约、每个单独调用的输入和输出,以及交易在其交互的每个合约中所做的累积状态更改。这大大简化了调试过程。
调用跟踪:此功能仅按顺序地列出外部调用。这样,你可以将执行调用列表缩小到那些调用了特定函数并且可能是攻击原因的函数。
评估表达式:无需进行耗时的计算即可获得所需的信息,而是使用评估表达式。你可以轻松地评估涉及函数参数、局部变量和合约状态变量的复杂和简单表达式,只需点击几下即可获得表达式结果。要充分利用此功能,请学习 如何使用评估表达式来简化调试。
优先级排序:使用此功能,你可以标记可疑的代码行以进行优先处理。
你可以分配不同的优先级,将你的团队成员引导到最有可能导致攻击的代码行。这为你和你的团队提供了清晰度和速度,尤其是在你同时找出智能合约中的逻辑错误时。
注释:为了进一步简化调试过程,请使用注释选项向代码添加注释。这使你可以加快与团队成员的协作,或者为自己留下注释,以便以后解决某些问题。
状态更改:你可以检查特定交易中的状态更改并检查任何已更改的值。在下面的示例中,你将看到两个地址的余额发生了多少变化(第一个地址增加,第二个地址减少)。
无论你处理哪种类型的智能合约错误,建立高效的调试过程非常重要,这样你就可以在潜在问题出现时立即解决。借助 Tenderly Debugger,你可以获得一种用于调试 Solidity 智能合约的先进工具,该工具将指导你完成整个调试流程。找到适合你的方法,并防止简单的智能合约错误演变成重大问题或潜在的黑客攻击。
- 原文链接: blog.tenderly.co/how-to-...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!