Web3现在正在蓬勃发展。仅仅使用以太坊智能合约就能做的事情是完全不同的;开发者已经在以太坊区块链上为多种用例创建智能合约,包括NFT、加密货币、收集付款,以及以去中心化的方式管理数据。
像其他每一种编程语言一样,Solidity(用于制作智能合约的语言)也需要调试,以使应用程序正常工作。使用Remix IDE,你可以找到适当的调试工具,这样你就可以跟踪智能合约的状态如何随着代码的执行而变化,看到任何时候的变量值,以及更多。今天,我们将讨论如何正确调试Solidity合约。
要求
- 对Solidity有一定的了解--我不会向完全的初学者推荐这个教程。
- 能够使用Remix。我们不会在本教程中使用Visual Studio Code这样的代码编辑器。
创建一个智能合约
当您打开Remix时,导航到contracts 文件夹,并创建一个名为Debugging.sol 的新文件。在其中添加以下内容。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
contract Debugging {
uint256 counter;
constructor(uint256 _counter) {
counter = _counter;
}
function _setCounter(uint256 _counter) internal {
counter = _counter;
}
function increment(uint256 value) public {
uint256 newValue = counter + value;
_setCounter(newValue);
}
function decrement(uint256 value) public {
uint256 newValue = counter - value;
_setCounter(newValue);
}
function getCounter() public view returns(uint256) {
return counter;
}
}
以上是用Solidity编写的基本智能合约的代码。它保持着对一个计数器的跟踪。我做了比严格要求更多的函数,以便在调试时演示合约的流程。
请注意,我们在本教程中使用的是v0.8.4版本,但如果你想的话,可以随意改变编译器的设置以匹配该版本,或者使用一个完全不同的版本。
编译和部署智能合约
现在进入编辑器的编译器标签,也就是侧边栏的第二个图标,你应该看到编译器设置。
继续并点击编译调试.sol。现在进入部署选项卡,也就是侧边栏上的第三个图标。你会看到部署标签,如下图所示。
确保环境被设置为JavaScript虚拟机之一,我们不会在本教程中涉及部署到实际的网络,但它的工作原理应该是差不多的。在靠近部署按钮的构造器字段中添加一个计数器。我把它设置为零,这将设置计数器的初始值。
一旦你点击部署,你应该在部署的合约部分看到你的智能合约。
这些是我们在智能合约中公开的功能,可以通过这些按钮访问。使用按钮附近的文本框,你可以用函数传递参数。
调试智能合约
现在让我们进入有趣的部分,对智能合约进行调试。为了调试,我们首先需要创建一个交易,这意味着我们需要与我们想要调试的智能合约的部分进行交互。
在这种情况下,我将使用increment 函数作为例子,并传递1 作为参数,使计数器增加1。按下increment 函数来运行智能合约。当交易完成或失败时,你会在Remix终端看到类似这样的东西。
现在,按下Debug按钮,我们将看到调试器。
在这个面板上有很多按钮和信息。让我们看看这里的按钮是什么意思。
下面是标签的说明。
- 返回到上一个步骤。函数调用将被忽略,调试器将不进入该函数。
- 后退一步回到上一步。函数不会被忽略,调试器将进入该函数。
- Step into进入下一步,如果有函数调用,调试器将进入函数。
- 跨步前进进入下一步,但是函数调用将被忽略,调试器不会进入函数。
- 跳到上一个断点,使调试器进入最后访问的断点。可以通过点击代码的行号来设置断点
- 跳出将调试器带到函数的末端
- 跳到下一个断点会使调试器跳到编辑器中的下一个设定的断点。
你也可以使用滑块,随着滑块的移动模拟交易。
现在我们来调试一下,看看increment 函数的流程是如何移动的。当你第一次在这个事务上启动调试器时,你应该看到这部分代码高亮显示。
这意味着newValue 这个变量正在被创建。当我们按步骤进入时,你应该看到在counter 和value 附近的代码被高亮显示,模拟了加法的工作情况。
最终,在几步之后,你会看到Solidity Locals面板像这样变化。
这意味着newValue (在代码的这一点上)的当前值是1。再往前走几步,你会看到自己在一个内部函数中,会像这样突出显示。
这意味着控制被传递到内部函数_setCounter 。现在您会看到之前的 Solidity locals 已经消失了,因为它们是increment 函数的局部变量,在_setCounter 中是无效的。
再走几步,你会看到你的Solidity状态面板像这样将初始计数器改变为新值。
在这一点上,我们可以确定,这一行特定的代码改变了状态。这就是你调试Solidity智能合约的方法!这是非常基本的合约,所以调试起来相当容易。在相对较大的合约中,你可能需要一直跟踪变量和状态。
还有几个调试功能
下面还有几个面板可能对你有用。
函数栈
你可以从这个面板上得到很多信息,比如哪个函数目前正在执行,哪个函数调用了它。如果有多个函数,它将以堆栈的形式显示。
全局变量
你可以跟踪交易中的全局变量,以备你需要知道交易中的发件人或其他数据。
步骤细节
你可以在这里得到一些额外的步骤数据,如已用气体和剩余气体。
操作码
使用操作码,你可以得到关于合同当前步骤的高级信息。你可以了解程序何时执行步骤,如JUMP 。
总结
知道如何调试是很重要的,我相信这篇文章让你了解了如何以适当的方式调试智能合约。你还是应该尝试尝试一些复杂的程序,比如通过合约发送Ethereum,看看流程是如何进行的。