调试代码

本章学习在 Solidity 中如何调试代码。

视频Bilibili  |  Youtube
官网binschool.app
推特@BinSchool    DiscordBinDAO   微信:bkra50 

使用 Solidity 编写智能合约,在开发过程中需要不断调试,以确保代码按照预设的逻辑执行,并能产生期望的结果。

在完成各个函数或模块之后,还需要进行单元测试和集成测试。充分的测试是非常必要的,可以避免上线后不必要损失。

Solidity 中,有几种常见的调试手段可以帮助开发者进行调试和排错:

1. 打印日志

Solidity 中没有专门的打印日志的语,但有一个变通的方法,就是使用 event 关键字来定义事件,并在合约中适当的位置触发事件,以输出相关变量的值。

我们可以通过查看 event  输出的日志,跟踪程序的执行路径和变量值的变化,帮助分析问题所在。

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Debug {
  event TransferLog(address); // 定义事件

  function transfer() public {
    // 调用事件
    emit TransferLog(msg.sender);
  }
}

我们把合约代码复制到 Remix,进行编译,并部署到区块链上:

 

点击调用函数 transfer后,在右边下方的控制台中就输出调试信息,这也是在 Remix 中常用的调试方法之一。

2. 使用断言

使用 assertrequire 断言来检查条件是否满足。

通过在关键位置添加断言语句,可以用来验证假设和条件,确保代码执行到指定的位置,并检查变量值是否符合预期。

断言失败时,合约将立即停止执行,并回滚所有状态变化。

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Require {
  // 转账函数  
  function transfer(address to, uint256 amount) public pure {
    require(to != address(0), "address `to` is zero");
    // 执行转账操作
  }
}

转账函数 transfer,在调用的时候,需要首先检测接收地址 to 是否为0,如果为 0 ,就会输出日志:address `to` is zero",终止转账。

所以,我们可以通过断言 require 输出的日志调试代码。

3. 使用 Remix 调试器

Remix 是一个基于 WebSolidity 集成开发环境,它提供了一个内置的调试器。

使用 Remix 调试器,可以逐行调试合约代码,观察变量值的变化,并检查执行路径。

它还提供了断点设置、单步执行、查看堆栈等功能,方便进行调试和排错。

 

Remix 调试器并不是很友好,需要开发者非常熟悉 EVMOpCode,以及了解一些汇编语言的知识。

非专业开发者,无需进行深入研究,有关知识将在以后的章节中详细讲解。

4. 使用测试框架

Solidity 的测试框架,例如 TruffleHardhatFoundry,提供了一系列的工具和函数,用于编写和运行测试用例。

这些测试框架通常包含断言库和调试工具,可用于验证合约的预期行为,并帮助定位和修复问题。

有关 TruffleHardhatFoundry 等测试框架的知识,我们会有单独的教程。