在Remix IDE中调试Ethereum交易

1,105 阅读6分钟

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版本,但如果你想的话,可以随意改变编译器的设置以匹配该版本,或者使用一个完全不同的版本。

编译和部署智能合约

现在进入编辑器的编译器标签,也就是侧边栏的第二个图标,你应该看到编译器设置。

Screenshot of Solidity compiler

继续并点击编译调试.sol。现在进入部署选项卡,也就是侧边栏上的第三个图标。你会看到部署标签,如下图所示。

Solidity deployment tab

确保环境被设置为JavaScript虚拟机之一,我们不会在本教程中涉及部署到实际的网络,但它的工作原理应该是差不多的。在靠近部署按钮的构造器字段中添加一个计数器。我把它设置为零,这将设置计数器的初始值。

一旦你点击部署,你应该在部署的合约部分看到你的智能合约。

deployed contracts section

这些是我们在智能合约中公开的功能,可以通过这些按钮访问。使用按钮附近的文本框,你可以用函数传递参数。

调试智能合约

现在让我们进入有趣的部分,对智能合约进行调试。为了调试,我们首先需要创建一个交易,这意味着我们需要与我们想要调试的智能合约的部分进行交互。

在这种情况下,我将使用increment 函数作为例子,并传递1 作为参数,使计数器增加1。按下increment 函数来运行智能合约。当交易完成或失败时,你会在Remix终端看到类似这样的东西。

Screenshot of pending transaction debugging

现在,按下Debug按钮,我们将看到调试器。

Solidity debugger panel

在这个面板上有很多按钮和信息。让我们看看这里的按钮是什么意思。

Slider with numbered arrow buttons

下面是标签的说明。

  1. 返回到上一个步骤。函数调用将被忽略,调试器将不进入该函数。
  2. 后退一步回到上一步。函数不会被忽略,调试器将进入该函数。
  3. Step into进入下一步,如果有函数调用,调试器将进入函数。
  4. 跨步前进进入下一步,但是函数调用将被忽略,调试器不会进入函数。
  5. 跳到上一个断点,使调试器进入最后访问的断点。可以通过点击代码的行号来设置断点
  6. 跳出将调试器带到函数的末端
  7. 跳到下一个断点会使调试器跳到编辑器中的下一个设定的断点。

你也可以使用滑块,随着滑块的移动模拟交易。

现在我们来调试一下,看看increment 函数的流程是如何移动的。当你第一次在这个事务上启动调试器时,你应该看到这部分代码高亮显示。

Highlighted Solidity code

这意味着newValue 这个变量正在被创建。当我们按步骤进入时,你应该看到在countervalue 附近的代码被高亮显示,模拟了加法的工作情况。

最终,在几步之后,你会看到Solidity Locals面板像这样变化。

Solidity locals panel

这意味着newValue (在代码的这一点上)的当前值是1。再往前走几步,你会看到自己在一个内部函数中,会像这样突出显示。

Highlighted internal functions

这意味着控制被传递到内部函数_setCounter 。现在您会看到之前的 Solidity locals 已经消失了,因为它们是increment 函数的局部变量,在_setCounter 中是无效的。

再走几步,你会看到你的Solidity状态面板像这样将初始计数器改变为新值。

Solidity state counter one

在这一点上,我们可以确定,这一行特定的代码改变了状态。这就是你调试Solidity智能合约的方法!这是非常基本的合约,所以调试起来相当容易。在相对较大的合约中,你可能需要一直跟踪变量和状态。

还有几个调试功能

下面还有几个面板可能对你有用。

函数栈

你可以从这个面板上得到很多信息,比如哪个函数目前正在执行,哪个函数调用了它。如果有多个函数,它将以堆栈的形式显示。

全局变量

Global variables

你可以跟踪交易中的全局变量,以备你需要知道交易中的发件人或其他数据。

步骤细节

Step details

你可以在这里得到一些额外的步骤数据,如已用气体和剩余气体。

操作码

List of OPcodes

使用操作码,你可以得到关于合同当前步骤的高级信息。你可以了解程序何时执行步骤,如JUMP

总结

知道如何调试是很重要的,我相信这篇文章让你了解了如何以适当的方式调试智能合约。你还是应该尝试尝试一些复杂的程序,比如通过合约发送Ethereum,看看流程是如何进行的。