unitimes.media
全球视角,独到见解
“本文介绍了调试智能合约的方法以及几种常见合约错误场景。”
调试智能合约
学习目标:
1. 了解智能合约调试
2. 掌握智能合约调试的方法
以太坊的智能合约就是代码。与你在其他地方找到的“纸质”合同不同,此合约需要以非常精确的方式说明问题。
这是一件好事,想象一下如果我们的合约编写不正确,我们的交易会失败,进而导致ether的丢失,更别提浪费的时间和精力了。
幸运的是,Truffle(v4.0)有一个内置的调试器来调试你的代码。所以当发生错误时,你能准确的找出并解决它。
在本教程中,我们将基础合约迁移到测试区块链,向其中引入一些错误,并通过使用内置的Truffle调试器来解决每个问题。
一个基础的智能合约
最基础的智能合约是一个简单的存储合约。
这个合约做了两件事:
1. 允许你给myVariable设置一个整形变量
2. 允许你查询变量的值
这是一个十分有趣的合约,但这不是我们的侧重点。我们关心的是的是当出错时会发生什么。
首先,让我们构建我们的环境:
部署最基础的智能合约
1. 创建一个新目录,我们将在本地安装我们的合约
这将创建诸如contracts /和migrations /的目录,并将它们填充到我们将合同部署到区块链时将使用的文件中。
3. 在contracts/目录下使用如下内容创建一个叫做Store.sol的文件
这是我们将要调试的合同。尽管此文件的全部细节超出了本教程的范围,但请注意,有一个名为SimpleStorage的合同,其中包含数值变量myVariable和两个函数:set()和get():第一个函数将值存储在该变量中,而第二个函数查询存储的值。
4. 在migrations/目录,使用下面的内容创建一个名为2_deployed_contract.js的文件
这个文件是允许我们将SimpleStorage合约部署到区块链上的指令。
5. 在终端上,编译智能合约
6. 打开第二个终端并运行truffle develop命令来直接构建一个开发区块链到Truffle,以便我们用来测试我们的合约:
控制台将显示truffle(develop)>的提示.从这开始,除非特别指定,所有的命令将在此提示符下键入
7. 随着控制台的启动和运行,我们现在能通过运行我们的migrations来将合约部署到区块链上:
响应应该如下所示,但是具体ID会有所不同:
与基础的智能合约进行交互
现在,智能合约已经通过truffle develop 部署到测试网络了,truffle develop启动了一个基于Ganache的控制台,这是一种内置于Truffle中的本地开发区块链。
我们接下来想通过和智能合约交互来看当正确运行时它是怎么工作的.我们将使用truffle develop控制台.
注意:如果您想知道为什么我们不需要挖矿来获取交易以确保交易安全,Truffle开发控制台已经为我们处理了这个问题。如果使用不同的网络,则需要确保您通过区块链获取交易。
1. 在truffle develop运行的终端,执行如下命令:
该命令使用SimpleStorage合同,然后调用其中定义的get()函数。然后将它返回的字符串输出转换为数字:
这表明我们的变量myVariable被设置为0,即使我们尚未将此变量设置为任何值。这是因为具有整数类型的变量会自动使用Solidity中的零值填充.
2. 现在,让我们在我们的合约上执行一笔交易.我们将通过set()函数完成这步操作,通过set()函数我们能将变量设置成一些整数.运行如下命令:
这将变量设置为4.输出显示交易相关的一些信息,包括交易ID(hash),交易接收以及交易过程中触发的所有事件日志:
对我们来说最重要的是交易ID(这里列出的tr和transactionHash).在我们调试的时候我们需要复制改值。
3. 为了验证这个变量的值已经改变,我们再次执行get()函数:
输出如下:
调试错误
上面显示了合约应该如何工作。现在,我们将向合约中引入一些小错误并重新部署。我们将看到问题本身如何呈现,并使用Truffle的内置调试功能来解决问题。
我们将看看以下问题:
1. 无限循环
2. 无效的错误检查
3. 没有错误,但功能没有按照需要运行
问题(一):无限循环
在以太坊区块链中,不能将交易设置为永久运行。交易可以运行直到达到gas限制。一旦发生这种情况,交易将出错,并且将返回“out of gas”错误。由于gas的价格在以太网中,这可能会对现实世界产生影响。所以修复一个“out of gas”的错误至关重要.
错误介绍
1. 用编辑器打开contracts/目录下的Store.sol文件.
2. 用下面内容替代set()函数:
由于while(true)条件,这个语句永远不会终止
测试合约
Truffle开发控制台能够迁移更新的合同,而无需退出并重新启动控制台。由于迁移命令可以一步完成编译和迁移,因此我们可以一步重置我们的区块链合约。
1. 在Truffle开发控制台,更新合约:
你将看到编译和迁移输出
2. 为了便于查找错误,我们将打开另一个日志记录控制台。例如,这可以让我们在交易失败时查看交易ID。在另一个终端窗口中,运行以下命令:
现在离开当前窗口,回到第一个控制台
3. 现在,我们准备执行交易.运行set()函数:
一个错误将显示出来:
而且,在有日志的控制台中,你将看到更多信息:
由于我们的失败和交易ID,现在我们可以调试交易了.
调试问题
Truffle包含一个内置的调试器。启动此命令的命令是从Truffle Develop控制台debug ,或者从终端truffle debug .现在开始吧.
1. 在Truffle Develop控制台中,从日志控制台复制交易ID并将其作为参数粘贴到debug命令中:
你将看到如下输出:
这是一个交互式控制台。您可以使用列出的命令以不同的方式与代码交互。
1. 与代码交互的最常见方式是“下一步”,该步骤一次执行代码一条指令。按Enter或n来执行此操作:
输出如下:
请注意,该程序已转到位于第6行的下一条指令。(该指示符指向发生指令的确切部分。)
2. 再次按Enter键跳到下一条指令:
3. 一直按Enter
请注意,这些步骤最终会重复。事实上,反复按下回车键将永远重复这些交易(或者至少在交易用完之前)。这会告诉你问题在哪里。
4. 按q退出调试器
案例(二):一个无效的错误检查
智能合约可以使用像assert()这样的语句来确保满足某些条件。但这也可能会与合约状态以不可调和的方式发生冲突。
这里我们将介绍这样一个条件,然后看看调试器如何找到它。
错误介绍
1. 打开Store.sol
2. 将set()函数替换为以下内容:
这与原始版本相同,但添加了assert()函数,进行测试以确保x == 0.当我们将该变量设置为其他值,我们就会遇到问题。
测试合约
和之前一样,我们将重置合约.
1. 在Truffle开发控制台,将合约重置为初始部署状态:
2. 现在我们准备测试新的交易了.运行和上面相同的命令:
你将看到一个错误:
这意味着我们的操作有问题。
调试错误
1. 复制交易ID并将其用作debug命令的参数
现在,我们回到调试器
1. 按Enter键几次以逐句通过代码。最终,调试器将停止并显示错误消息:
这是触发错误的最后一个事件。你可以看到它是assert()引发的错误。
案例(三):功能没有按需运行
有时候,错误并不是真正的错误,因为它不会在运行时造成问题,而只是做一些你不打算做的事情。
以一个事件为例,如果我们的变量很奇怪,另一个事件会在我们的变量是偶数时运行。如果我们意外地交换了这个条件以便相反的函数能够运行,那么它不会导致错误;不过,合同会出乎意料。
再次,我们可以使用调试器来查看出错的地方。
错误介绍
1. 再次打开Store.sol文件
2. 将set()函数替换为以下内容:
该代码引入了两个虚拟事件,Odd()和Even(),它们是基于一个条件触发的,该条件检查x是否可以被2整除。
但请注意,我们已将结果反转过来。如果x可以被2整除,Odd()事件将会运行。
测试合约
开始之前,我们同样重置区块链上的合约
1. 在Truffle开发控制台,重置合约
你将看到编译和迁移的输出
2. 现在我们准备测试新的交易。运行与上面相同的命令:
注意:这里并没有错误,如期返回交易ID及其详情:
但请注意交易记录显示事件Odd。这是错误的,所以我们的工作是找出为什么被调用。
测试合约
1. 复制该事务ID并将其用作debug命令的参数:
2. 按Enter键多次循环执行步骤。最终你会看到是什么原因导致了Odd()事件:
问题很明显。是条件语句出了问题。
总结
凭借在Truffle中直接调试合约的能力,你可以使你的智能合约变得坚如磐石,随时可以部署。
来源:区块链兄弟
http://www.blockchainbrother.com/article/2373
本文转载于网络,版权归原作者所有,其内容与观点不代表unitimes立场。转载文章仅为传播更有价值的信息,如采编人员采编有误或者版权原因,欢迎与我们联系,我们将核实后修改或删除。
国际金融科技新媒体和社区平台
UNITIMES
网址 : unitimes.media
新浪微博:@Unitimes
领取专属 10元无门槛券
私享最新 技术干货