火星链 火星链
Ctrl+D收藏火星链
首页 > 币赢 > 正文

SOLID:智能合约解构(2):创建与运行时间代码解析

作者:

时间:1900/1/1 0:00:00

本文是系列文章的第二部分。如果您还没有阅读本文的前言,请先看一下,第一部分·引言我们正在解构一个简单的solidity智能合约的EVM字节码。今天,让我们开始用“分而治之”的策略来拆解智能合约的复杂代码吧。我在介绍性的前言中说过,这个反汇编的代码其实非常低级,但与原始字节码相比会比较易读。请确保已在遵循了我在前言中介绍的操作,把BasicToken的代码在remix编译器中进行了部署。免责声明:本文中提供的所有说明均受我自己对transaction运作方式的解释,不代表以太坊官方意见。现在,让我们聚焦在JUMP、JUMPI、JUMPDES、RETURN和STOP操作吗,并忽略所有其他的操作。每当我们发现不是其中之一的操作码时,我们就忽略它,并跳到下一条指令,不要被他们干预。当EVM执行代码时,是自上而下的顺序,代码中没有其他入口点,始终从顶部开始执行。JUMP和JUMPI可以让代码跳转。JUMP获取堆栈中的最上面的值,并将执行移动到该位置的指令。但是,目标位置必须包含JUMPDEST操作码,否则执行将失败。这样做的唯一目的是:JUMPDEST将位置标记为有效的跳转目标。JUMPI也完全相同,但堆栈的第二个位置一定不能有“0”,否则就没有跳转。所以这是一个有条件的跳转,STOP是让智能合约完全停止的指令,RETURN则是暂停智能合约的执行,但返回EVM内存的一部分数据,这很方便。所以,让我们开始解释代码时考虑到所有这些。在Remix的调试器中,将“transaction”的滑块滑到最左边。你可以使用StepInto按钮并按照说明进行操作。前面的指令可以忽略,直接到第11条指令,我们找到了第一条JUMPI。如果它没有跳转,它将继续通过指令12到15并最终进入REVERT,接着将停止执行。但如果跳转,它将跳过这些指令到位置16。指令16是一个JUMPDEST。继续单步执行操作码,直到“transaction”滑块一直向右。刚刚发生了很多等等,但只有在68的位置才能找到RETURN操作码。这很奇怪。如果您考虑一下,本智能合约的控制流程将始终在指令15或68结束。我们刚刚完成它并确定没有其他可能的流程,那么剩下的指令是什么?。我们刚刚遍历的指令集就是所谓的合约的“创建代码”。它永远不会成为智能合约代码本身的一部分,但仅在创建智能合约的交易期间由EVM执行一次。我们很快就会发现,这段代码负责设置创建的合约的初始状态,以及返回其运行时代码的副本。剩下的497条指令,正如我们所见,执行流程永远不会达到的,正是这些代码将成为已部署智能合约的一部分。接下来,我们对代码进行第一次拆分:把创建时的代码与运行时的代码区分开。创建部分

德国Auto1 FinTech推出欧洲区块链汽车融资智能合约:10月7日消息,Auto1 FinTech正在取消其核心业务汽车融资中的所有手动输入和纸质流程,其与融资汽车相关的所有文件、文件和流程都将基于智能合约,通过智能合约最大限度地提高数据安全性和效率,并将汽车融资所涉及的总支出和文件减少到最低限度,这些智能合约包含车辆所有相关信息和流程。

Auto1 Fintech为二手车市场提供快速简便的数字融资解决方案。该公司宣布的目标是为移动的所有领域提供创新融资和支持。Auto1 FT成立于2017年底,目前在德国和法国开展业务,总部位于柏林和阿姆斯特丹。[2021/10/7 20:11:00]

现在,我们将深入研究代码的创建部分。图1.解构BasicToken.sol的创建时EVM字节码这是本文中要理解的最重要的概念。创建代码在事务中执行,该事务返回运行时代码的副本,该副本是智能合约的实际代码。正如我们将看到的,构造函数是创建代码的一部分,而不是运行时代码的一部分。智能合约的构造函数是创建代码的一部分;一旦部署,它将不会出现在智能合约的代码中。这种魔力是如何发生的?这就是我们现在要逐步分析的内容。好的。所以现在我们的问题被简化为理解这些与创建时代码相对应的70条指令。让我们重新采用自上而下的方法,这次了解所有指令,而不是跳过任何指令。首先,让我们关注使用PUSH1和MSTORE操作码的指令0到2。图2.空闲内存指针EVM字节码结构PUSH1只需将一个字节压入堆栈顶部,而MSTORE从堆栈中抓取最后两个项并将其中一个存储在内存中:mstore(0x40,0x80)|||Whattostore.Wheretostore.(inmemory)注意:上面的代码片段是Yul-ish代码。注意它是如何从左到右消耗堆栈中的元素,总是首先消耗堆栈顶部的元素。这是将数字0x80存储在位置0x40的位置。在我们现在讨论的问题中,不用去管它,如果必须有一个原因,我后面会解释。现在,在Remix的Debugger选项卡中打开Stack以及Memory的面板,以便在逐步查看这些指令时可以可视化。你可能想知道:指令1和3发生了什么?PUSH是唯一由两个或多个字节组成的EVM指令。所以,PUSH80是两条指令。所以我们揭开了谜底:指令1是0x80,而指令3的0x40。接下来我会说明从5到15的指令。图3.non-payable检查EVM字节码结构。在这里,又有一大堆的新的操作码:CALLVALUE,DUP1,ISZERO,PUSH2,和REVERT。CALLVALUE推送创建事务中涉及的wei的数量,DUP1复制堆栈中的第一个元素,如果堆栈的最高值为零,ISZERO则将1推送到堆栈,PUSH2就像PUSH1,但它将两个字节推送到堆栈,而REVERT则是停止执行。那么这里发生了什么?在Solidity中,我们可以像这样编写这个汇编:ifrevert;这段代码实际上不是我们原始Solidity源的一部分,而是由编译器注入的,因为我们没有将构造函数声明为payable。在Solidity的最新版本中,未明确声明为payable的函数不能接收以太。返回到汇编代码,在指令11的JUMPI将跳过指令12到15,如果没有相关的以太币,则跳转到16。否则,REVERT将以两个参数执行为0。好的!让我们中场休息一下,来杯咖啡。如果您想要另一种方式来可视化我们刚刚完成的工作,请尝试使用我构建的这个简单工具:solmap。它允许您实时编译Solidity代码,然后单击EVM操作码以突出显示相关的Solidity代码。反汇编与Remix有点不同,但你应该能够通过比较来理解它。咖啡时间到!准备继续前进了吗?接下来是指令16到37。请继续使用Remix的调试器。。图4.EVM字节码结构,用于从智能合约字节码末尾附加的代码中检索构造函数参数前四个指令读取位置在存储器中的任何内容0x40,并将其推送到堆栈。如果你能回忆起来,那应该是数字0x80。下面是推0x20到堆栈,并拷贝该值,压栈0x0217,最后拷贝第四个值,这应该是0x80。在查看这样的EVM指令时,可以暂时不了解发生了什么。别担心,它会时不时出现在你的脑海。在指令28,执行了CODECOPY,它接受三个参数:目标内存位置,用来存储复制代码,从中复制的指令编号,以及要复制的代码的字节数。因此,在这种情况下,0x80从位于代码中的字节位置开始。如果查看整个反汇编代码,有566条指令。为什么这段代码试图复制最后32个字节的代码呢?实际上,在部署包含参数的构造函数的合约时,参数作为原始十六进制数据附加到代码的末尾。在这种情况下,构造函数接受一个uint256参数,因此所有这些代码所做的就是将参数从附加在代码末尾的值复制到内存中。这些32条指令作为反汇编代码没有意义,但是它们用原始的十六进制表示:0x0000000000000000000000000...0000000000000000000002710。当然,这是我们在部署智能合约时传递给构造函数的十进制值10000!你可以一步一步地在Remix中重复这一部分,确保您了解刚刚发生的事情。最终结果应该是0x00..002710的位置,看到在内存中的数字0x80。好,开始下一部分之前,我建议来一杯威士忌休息一下。威士忌时光!为什么建议你来一杯威士忌,因为从这里开始,都是下坡路了。下一组指令是29到35,更新内存地址0x40的值0x80到值0xa0,可以看到,它们将值偏移了0x20字节。现在我们可以开始理解指令0到2了。Solidity追踪称为“空内存指针”的东西:即内存中我们可以用来存储东西的地方,保证没有人会覆盖它。因此,由于我们将数字10000存储在旧的空闲内存位置,我们通过向前移动32个字节来更新空闲存储器指针。即使是经验丰富的Solidity开发人员在看到“空闲内存指针”或代码时也会感到困惑,mload(0x40,0x80),这些只是说,“每当我们写一个新条目时,我们将从这一点开始写入内存并保留偏移记录”。Solidity中的每个函数,当编译为EVM字节码时,将初始化此指针。在0x00到0x40之间的内存有什么,你可能不知道。没有。Solidity保留的一段内存,计算哈希值,我们很快就会看到,这对于映射和其他类型的动态数据是必需的。现在,在指令37中,MLOAD从存储器读取位置0x40并基本上将我们10000的值从内存下载到堆栈中,在那里它将是新的,并且可以在下一组指令中使用的。这是由Solidity生成的EVM字节码中的常见模式:在执行函数体之前,函数的参数被加载到堆栈中,以便即将到来的代码可以使用它们-这正是接下来会发生的事情。让我们继续说明38至55。图5.构造函数的主体EVM代码。这些指令只不过是构造函数的主体:也就是Solidity代码:totalSupply_=_initialSupply;balances=_initialSupply;前四条指令非常明显,首先,0被压入堆栈,然后堆栈中的第二项被复制,然后数字0被复制并被推送到堆栈,这是存储中的位置槽totalSupply_。现在,SSTORE可以使用这些值,并且仍然保持10000个以下以备将来使用:sstore(0x00,0x2710)|||Whattostore.Wheretostore.(instorage)瞧!我们将数字10000存储在变量中totalSupply_。是不是很神奇??一定要在Remix的Debugger选项卡中可视化这个值。你可以在存储完全加载的面板中找到它。下一组指令有点棘手,但基本上会处理在balances映射中存储10000的密钥msg.sender。在继续之前,请确保您了解Solidity文档的这一部分,该文档说明了如何在内存中保存映射。简而言之,它将连接映射值的槽与使用的键,然后用SHA3操作码取摘要并使用它作为在内存中的目标位置。最后,存储只是一个简单的字典或哈希表。继续执行指令43至45,将msg.sender地址存储在内存中,然后在指令46至50中,将值1存储在内存位置0x20。最后,SHA3操作码计算从位置0x00到位置0x40的内存中的任何内容的Keccak256散列-即映射的插槽/位置与所使用的键的串联。这正是值10000将存储在我们的映射中的位置:sstore(hash...,0x2710)|||Whattostore.Wheretostore.此时,构造函数的主体已完全执行。所有这些起初可能有点压倒性,但它是存储在Solidity中工作的基本部分。如果你没有得到它,我建议你跟着Remix的调试器重复几次,保持堆栈和内存面板。另外,请随时提出以下问题。此模式在Solidity生成的EVM字节码中普遍使用,您将很快学会轻松识别它。最后,它只是计算在内存中保存映射的某个键的值的位置。图6.运行时代码复制结构在指令56至65中,我们再次执行代码复制。只有这一次,我们不会将代码的最后32个字节复制到内存中;我们从位置0x0046开始复制0x01d1字节到位置0的内存。这是要复制的一大块代码!如果您再次将滑块一直向右滑动,您将注意到位置70正好在我们的创建时EVM代码之后,执行停止的地方。运行时字节码包含在那些465个字节中。这是代码的一部分,它将作为智能合约的运行时代码保存在区块链中,该代码将是每次有人或某事与智能合约交互时执行的代码。。这正是指令66到69所做的:返回我们复制到内存的代码。图7.运行时代码返回EVM字节码结构。RETURN抓取复制到内存的代码并将其交给EVM。如果此创建代码在对0x0地址的事务的上下文中执行,则EVM将执行代码并将返回值存储为创建的智能合约的运行时代码。到现在为止,我们的BasicToken代码将创建和部署智能合约实例,并准备好使用其初始状态和运行时代码。如果退后一步并查看图2,您将看到我们分析的所有EVM字节码结构都是通用的,除了以紫色突出显示的那个:也就是说,它们将是由Solidity编译器生成的创建时字节码。构造函数与构造函数的区别仅在于紫色部分-构造函数的实际体。获取嵌入在字节码末尾的参数的结构,以及复制运行时代码并将其返回的结构,可以被认为是样板代码和通用EVM操作码结构。您现在应该能够查看任何构造函数,在按指令学习之前,您应该对构成它的组件有一个大概的了解。在本系列的下一篇文章中,我们将介绍实际的运行时代码,首先介绍如何在不同的入口点与智能合约的EVM代码进行交互。现在,给自己一个当之无愧的轻拍,因为你刚刚消化了系列中最困难的部分。你还应该具有强大的能力来读取和调试EVM字节码,理解通用结构,最重要的是,了解创建时和运行时EVM字节码之间的区别。这就是使得合约的构造函数在Solidity中如此特殊的原因。我们将在下一篇的系列文章中继续解构!*本文由AlejandroSantander首发于medium,由猎豹区块链安全翻译并整理*猎豹区块链安全以金山霸的技术为依托,结合人工智能、nlp等技术,为区块链用户提供合约审计、情感分析等生态安全服务。Ratingtoken官网https://www.ratingtoken.net/?from=z

Ran Neuner:Flare并非在XRP协议上构建智能合约:CNBC主持人Ran Neuner发推称,太多的XRP持有者认为Flare正在XRP协议上构建智能合约。并不是这样的。这是一条全新的技术链,与现有协议无关。据此前消息,Coinbase宣布支持Flare Networks即将于12月12日为XRP持有人空投Spark(FLR)代币。[2020/12/7 14:22:46]

Cardano创始人回应BM的质疑:Cardano不是DPoS 智能合约和本地资产将在今年推出:8月1日,网友@crypto_spaced发推称Cardano是DPoS,且EOS创始人Daniel Larimer(BM)在其很早前就称Cardano是DPoS。Cardano创始人Charles Hoskinson回复称:“我们不是DPoS。Ouroboros是一种全新的协议。”“BM说谎了,他还说我们的协议不起作用。他称这是一件800磅重、挡不住子弹的防弹背心。我很抱歉,不管你信不信他,他说谎了,他把我们的协议说成DPoS是大错特错。”8月3日,BM回复Hoskinson称:“你的协议不适用于货币以外的应用程序,对于大多数DeFi而言,确认等待时间太长,并且完全不适用于大多数用例。”Hoskinson对此表示:“智能合约和本地资产将在今年推出,我们的延迟比以太坊的更低。占主导地位的DeFi平台hydra将把它带到次秒级。引用中本聪的话:对不起,我没有时间向你解释。”[2020/8/3]

声音 | 中国人保执行副总裁:智能合约能将金融交易变简单:据新浪消息,中国人保财险执行副总裁王和近日发文表示,区块链技术之所以重要,就在于其具有极强的特殊结构能力。这种结构力能够将一种简单的关系结构进化为一种复杂的利益结构,结构力决定了未来“分布式社会”的秩序与管理。他同时称,金融科技的未来形态将体现为智能终端和区块链技术,智能合约能够使复杂的金融交易变得简单,这就是未来金融的场景。[2018/10/26]

全国首款金交所区块链智能合约产品落地:在供应链金融这个具有万亿级别规模的市场,天津金融资产交易所联合恒生电子,实现了国内首例金交所区块链业务场景的落地。这款产品的研发成功,标志着供应链金融已经进入了技术引领的金融科技时代,提供了由点到段,再到整个供应链链条的金融解决方案。[2018/6/20]

标签:SOLSOLIDLIDDIT1SOLSOLID币BLID价格SMARTCREDIT币

币赢热门资讯
ROC:矿圈深坑都在这:被钱,被坑电,还被迫做了接盘侠

最火热的时候,币圈滚滚的暴利,让想要抢占挖矿“风口”的人们来不及细思究竟,便纷纷跳入了挖矿大潮.

1900/1/1 0:00:00
比特币:A16Z女合伙人 Vs. 诺奖经济学家:传统精英对区块链的不同选择和论辩

论战双方背景A16ZCrypto合伙人KathrynHaunA16ZCrypto有两位普通合伙人,ChrisDixon和KathrynHaun,ChrisDixon已经非常有名了.

1900/1/1 0:00:00
USD:数字经济行业报告之五:“称提”稳定币

作者Fabric.FengChiefAnalystE-Mail:Fabric.feng@bncapital.one报告概要本文从“称提”的视角,结合货币基础理论.

1900/1/1 0:00:00
区块链:案例详解 Reg A+ 的 STO 解决方案

中国和美国的监管和募资环境,经过标准共识的相关探索和知识普及,目前的环境已相对明晰:全球范围来说,区块链的泡沫正在破灭,各国的的相关监管更加严格.

1900/1/1 0:00:00
ITA:熊市之下,华尔街大鳄还会入场加密货币吗?

据彭博社12月23日报道,由于近期接连不断的熊市,比特币价格跌跌不休,加密货币整体市值缩水,之前强势入场的华尔街巨头正在放慢入场加密货币的脚步.

1900/1/1 0:00:00
加密货币:星球日报 | 徐明星收购港股上市公司;ETH升级讨论将于北京时间今晚22时进行

头条雄安考察见闻:区块链等高科技智能平台追溯树木生命周期管理1月16日,2019年首次国内考察第一站来到了河北雄安新区。在这次考察的路线上,一些智能环保“神器”随处可见.

1900/1/1 0:00:00