想象一下,1969年,你在美国西部的高速公路上驾驶一辆野马马赫。阳光照射在华丽的镀金轮圈上。整条路只有你和沙漠。无尽的地平线见证了对你和夕阳的追逐......
心情轻松愉快的时候,突然传来一声巨响。你那匹335马力的快马被滚滚白烟吞噬,瞬间变成了蒸汽机车,你被迫停在路边。
你会发现哪里出了问题。当你打开前罩时,你发现你根本看不懂它。你不知道这个该死的机器是怎么工作的,所以你拿起手机准备求救,但是附近没有信号......
上述情况是否与您正在进行的DApp开发类似?在开发Dapp的过程中,以此类推,豪车就是你的智能合同,轮圈和改装的地方就是仔细考虑后的小细节。一旦出现问题,你需要在智能契约EVM字节码中找到答案。在大多数情况下,你不知道发生了什么。
如果你是Dapp的开发者,遇到了以上尴尬的情况,那就不要再担心了!
因为,这一系列文章的目的是解构一个简单的Solidity契约,看看它的字节码,并将其分解成可识别的结构,直到最低级别。我们将打开实度跑车的发动机罩。在本系列的最后,当您查看或调试EVM字节码时,您应该会感觉很舒服。本系列的重点是揭开由Solidity编译器生成的EVM字节码的神秘面纱,它确实比看起来简单得多。
以下是解构时要使用的智能合同代码:
务实稳健的^0.4.24;
合同基本条款{
uint 256 TotalSupply _;
映射(地址= >;uint256)余额;
构造函数(uint256 _initialSupply)公共{
totalSupply _ = _ initialSupply
balances[msg . sender]= _ initial Supply;
}
函数totalSupply()公共视图返回(uint256) {
return TotalSupply _;
}
函数转移(address _to,uint256 _value)公共返回(bool) {
要求(_to!= address(0));
要求(_ value & lt= balances[msg . sender]);
balances[msg . sender]= balances[msg . sender]-_ value;
余额[_to] =余额[_ to]+_ value;
返回true
}
函数balanceOf(address _owner)公共视图返回(uint256) {
返回余额[_所有者];
}
}
注意:此合同易受溢出攻击。我们只是想说明问题,所以尽量简单。
编译合同
为了编制合同,我们将使用Remix(地址:https://remix.ethereum.org)。
当您打开Remix编译器时,单击文件浏览器区域左上角的+按钮,创建一个新的智能合同。将文件名设置为BasicToken.sol..创建后,将上述代码粘贴到编辑器中。
在右侧,转到“设置”选项,并确保选择了“启用个人模式”。此外,请注意,选定的实度编译器版本是
版本:0 . 4 . 24+commit . e67f 0147 . Meen . clang .
这两个细节非常重要,否则您将无法查看本文中讨论的字节码。
接下来,可以输入Compile选项,点击Details按钮,会看到一个弹出窗口,里面包含了Solidity编译器生成的所有东西,其中一个是名为BYTECODE的JSON对象,它有一个“object”属性。这是编译好的合同代码,它的代码是这样的:
60806040523480156100105760080 FD 5b 5060405160208061021783398101604008152905 16008 16008 16008 1609 1609 1609 1609 1609 1609 1609 1609 1609 1609 1609 1601 1609 1609 1609 1609 1609 1609 1609 1601609 1609 16016
是的,这个代码完全不可读(至少对正常人来说)。
部署合同
接下来,转到混音中的运行部分。首先,确保您使用的是Java VM。这基本上是一个嵌入式Java EVM+网络,是以太网的理想训练场。确保在组合框中选择基本选项,并在部署输入框中输入数字10000。接下来,单击“部署”按钮进行部署。该部署是我们创建的基本智能合同实例。最初提供的10,000个令牌归当前在组合框帐户顶部选择的帐户所有,该帐户将保留我们设置的所有令牌供应。
在“运行”选项卡的“已部署合同”中,您可以看到已部署的智能合同,它包含三个与合同交互的字段:转移、平衡和总供应。在这里,我们可以与刚刚部署的智能契约实例进行交互。
但在此之前,让我们来看看合同的“部署”是什么意思:
在页面底部的控制台区域,您可以看到一个日志“创建基本知识待定...”,后面是包含各种字段的事务条目:from、to、value、data、log和hash。单击这个条目来展开事务信息,您应该会看到事务的日期和输入,以及上面提到的字节码。因此,创建一个智能契约实例,它将包含自己的地址和代码。
我们将在下一次张文会议上详细研究这一交易过程。
反汇编字节码
在控制台的中央,交易框的右边,有一个“调试”按钮。点击此按钮,您将在Remix的右侧区域激活调试器选项。我们可以一起看看说明部分。如果向下滚动,您应该会看到以下内容:
000 PUSH1 80
002 PUSH1 40
004 MSTORE
005 CALLVALUE
006 DUP1
007 ISZERO
008 PUSH2 0010
011 JUMPI
012 PUSH1 00
014 DUP1
015 REVERT
016 JUMPDEST
017 POP
018 PUSH1 40
020 MLOAD
021 PUSH1 20
023 DUP1
024 PUSH2 0217
027 DUP4
028 CODECOPY
029 DUP2
030 ADD
031 PUSH1 40
033 SWAP1
034 DUP2
035 MSTORE
036 SWAP1
037 MLOAD
038 PUSH1 00
040 DUP2
041 DUP2
042 SSTORE
043 CALLER
044 DUP2
045 MSTORE
046 PUSH1 01
048 PUSH1 20
050 MSTORE
051 SWAP2
...(缩写)
为了确保您之前的操作没有错误,您可以将您在Remix编译器中看到的内容与上面的内容进行比较。
这其实就是契约的反汇编字节码。如果你用字节扫描原始字节码(一次两个字符),EVM将识别与特定操作相关的特定操作码。例如:
0x60 =>。推
0x01 =>。模拟数字音乐制碟
0x02 =>。MUL
0x00 =>。停止
...
拆解出来的代码很低级,很难理解,但是我们可以这样开始理解。
操作码
在解构智能契约代码之前,您将需要一个基本的工具集来理解单个操作码的操作码,如推送、添加、交换、DUP等。最后,每个操作只能按下一个项目,或者从属于EVM合同的堆栈、内存或存储器中消耗一个项目。
要查看EVM可以处理的所有可用操作码,请查看Pyethereum,它显示了一个操作码列表。要了解每个操作码的工作原理,Solidity的官方汇编文档也是很好的参考。即使没有一一对应原操作码,也非常接近(其实是Yul,介于Solidity和EVM字节码之间的中间语言)。如果你能看懂技术文档,你就能看懂以太网黄皮书。其实都在上面。
虽然我跟你推荐了这么多文档,但是从头到尾看完这些资源是没有意义的。你只需要记住有这样的信息,我们会在必要的时候使用它们。
指示
上面反汇编代码的每一行都是EVM执行的操作指令,每一条指令都包含一个操作码。例如,让我们使用指令之一,指令88,将数字4推入堆栈。该特殊拆卸程序解释如下:
88 PUSH1 0x04
| | |
| |推送的十六进制值。
|操作码
指令编号
虽然反汇编的代码可以帮助我们更好的理解底层的东西,但是还是比较混乱。我们需要一种解构所有问题的方法。
策略
任何一开始看起来不可能的任务,都可以通过不断的反汇编,分解成可以解决的任务,我们遇到的问题也不例外。面对这个问题,我的策略是“分而治之”。
我们可以试着找到反汇编代码的分叉点,逐步分解,直到分解成小块,我们会在Remix调试器中逐步完成。
在下图中,我们可以看到反汇编代码的第一次拆分(我将在下一篇文章中对其进行全面分析)。
如果你不知道图表,不要担心。你不必一开始就什么都知道。我们的系列文章会一步步介绍。现在跟随我们的节奏,深入你的豪车内部结构。
1.《solidity 解构Solidity智能合约》援引自互联网,旨在传递更多网络信息知识,仅代表作者本人观点,与本网站无关,侵删请联系页脚下方联系方式。
2.《solidity 解构Solidity智能合约》仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证。
3.文章转载时请保留本站内容来源地址,https://www.lu-xu.com/jiaoyu/753467.html