木星链 木星链
Ctrl+D收藏木星链

以太坊:以太坊智能合约逆向分析与实战:(5)深入EVM之合约的部署与调用

作者:

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

当我们部署和调用合约的时候,EVM 都在做些什么?

如果你开发过以太坊智能合约,想必你应该熟悉这样的操作 (此处以remix为例) :

编写solidity代码 -> 编译 -> 部署-> 交互 。合约的编写与部署似乎并不是一件很麻烦的操作:编写阶段就不说了,Solidity语言大家都应该会;到了编译阶段,本地的 solc 编译器会把 Solidity 代码编译成字节码(bytecodes);而在部署阶段,部署者通过发起一笔特殊交易(to的地址为空)calldata 带上编译后的字节码,等交易上链之后,就完成了合约的部署;而合约交互,就是call合约里的某个函数,等待函数的响应和返回,一切就是这样的简单。

但是正如开车一样,当你踩住油门后,车辆开始前进。然而这看似简单的操作背后是汽油爆燃、活塞往复、数百个齿轮啮合传动、轮胎与地面滚动摩擦的复杂行为。部署和调用合约也是如此,它涉及到 EVM 的堆栈操作,内存读写,存储访问等一系列底层操作。当部署合约时, EVM 把收到的 calldata 翻译成操作指令,把它们按照给定的长度和参数读入内存;当调用合约时,EVM 又根据收到的 calldata ,通过函数选择器来确定调用哪一段代码,并返回数值。如果只讲理论未免过于枯燥,为了便于讲解,我们这次用 ethernaut 的一道题目作为例子,详细了解 EVM 是如何部署和运行合约的,以及如何充当人肉编译器,徒手编写智能合约。

以太坊未确认交易为174,930笔:金色财经消息,据OKLink数据显示,以太坊未确认交易174,930笔,当前全网算力为525.03TH/s,全网难度为7.18P,当前持币地址为61,934,424个,同比增加55,346个,24h链上交易量为1,880,999.84ETH,当前平均出块时间为13s。[2021/8/2 1:28:17]

这个题目是这样的:我们需要部署一个合约,当我们调用合约 **whatIsTheMeaningOfLife()**函数的时候,它需要返回一个数字 “42”。看起来很简单对吧?我们分分钟编写完毕:

慢着,题目后面还有个小小的附加要求:“所部署的合约大小不超过10个操作码”。好吧,这个要求的确够“小”,要知道连合约头部的 “函数选择器” 都不止 10 个操作码好吧?可是“函数选择器” 是什么,为什么会出现在合约里面呢?带着你的疑问,继续向下看。

我们通过 ./solc --asm --bin target.sol 来看看这个合约的最终编译结果:

比特币期权及以太坊期权未平仓合约创历史新高:金色财经报道,截至11月22日,比特币期权未平仓合约总额达到45.3亿美元,自11月15日以来增加了11.3亿美元。此外,以太坊期权的未平仓合约总额达7.8005亿美元。 据The Block Research数据,以太坊期权未平仓合约一周内增加了2.2109亿美元,涨幅为39.5%。[2020/11/24 21:50:44]

608060405234801561001057600080fd5b5060b68061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063650500c114602d575b600080fd5b60336047565b604051603e91906067565b60405180910390f35b6000602a905090565b6000819050919050565b6061816050565b82525050565b6000602082019050607a6000830184605a565b9291505056fea26469706673582212206ef8c7b5177952a701b3b46b69cb3ec296f4c54c946692e8ec901f5e43c1e78a64736f6c63430008110033

YFI社区发布以太坊期权策略yETH-PUTVault提案:yearn.finance(YFI)社区成员ramaruro在论坛发布设计YFI以太坊期权策略产品yETH-PUTVault的提案。该以太坊期权策略的设计旨在获得除了yETH以外的可获得高收益的代替策略,同时帮助发展新生的去中心化期权市场。该提案选取包括Opyn以及Hegic两个项目作为该策略使用的候选平台。[2020/9/11]

这么一大坨十六进制数据,就是上述 Solidity 程序编译之后的字节码。当我们部署合约时,把这一堆 data 发给以太坊节点,等广播完成后,合约就部署完毕了。这是 solc 编译器编译 Solidity程序得到的代码,看似杂乱无章的的数据,其实都是和 opcodes 一一对应的。我们来一段一段地看这些代码:

合约部署代码:

合约运行代码:

auxdata:

我们先简单地把这堆代码分为合约的部署代码、运行代码、auxdata 三部分,如何理解这三种代码呢?我觉得可以理解为向太空发射卫星:“部署代码” 就是运载火箭,而“运行代码”就是卫星。运载火箭只在发射卫星时才起到作用,一旦卫星进入轨道,火箭就废弃了,只留下卫星在太空中与地球通信。 部署合约也是如此,在部署合约时,部署代码把一些初始化工作作完之后,就把合约的运行代码送入EVM,只留下运行代码在链上与用户进行交互。 (至于auxdata,它是紧跟在runtime代码后面的43个字节,相当于源码的指纹,可以用来验证。这只是数据,并不会被EVM执行。)

Tether向以太坊网络增发1.2亿枚USDT(已授权未发行):金色财经报道,据Whale Alert数据,北京时间04月15日00:36,Tether向以太坊网络增发1.2亿枚 USDT,交易哈希为:0x2c7cd342d5b24e687d5a15347a44a5b1f6a6ae270ec4a9c59007c259aa562994。Bitfinex首席技术官PaoloArdoino表示,请注意,这是一笔已授权但未发行的交易,这意味着该金额将用作下一次发行请求的库存。[2020/4/15]

那么言归正传,我们题目要求我们合约运行代码的 opcedes 不超过 10 条,那么,这段代码对应的 opcodes 是多少条呢?答:71 条。(通过查看 Remix : ./artifacts/MagicNum.json 中的 bytecode 里的 opcodes 可以看到。而 deployedBytecode 里的 opcodes 却是 92 条,因为它的长度是 部署代码 + 运行代码 )

那么问题来了,如何把 71 条 opcodes 精简到 10 条以内呢? 这就需要我们对 EVM 运行智能合约的方式有着一定的了解。如果不了解也没关系,拿起你手边的 EVM 指令集 ,我们一起来看看吧:

分析 | 以太坊gas使用量创年内新高 强劲的基本面因素或继续推高价格:以太坊的交易量达到了自2019年7月以来的最高水平。今年年初以来,ETH的价值已经翻了一番,截至发稿时,其价格为272美元。以太坊的网络使用率也在上升。在活跃地址方面,以太坊达到了自2019年9月以来的最高水平。活动地址数量增加了26.7%,而交易数量也增加了20.77%。加密分析公司Glassnode指出,gas使用量强劲,达到了四个月来的最高点,分析指出强劲的基本面因素或继续推高价格。(ambcrypto)[2020/2/16]

首先我们要知道,EVM 执行代码时是按照自上而下的顺序执行的,代码中没有其他入口点,始终从顶部 (也就是第一行 opcode ) 开始执行。(这点和 Windows 软件不一样,PE文件是有固定的入口点的,而且不同的 Windows 版本或不同的 PE 文件 入口点也会有所不同)。也就是说,当我们部署合约时, EVM 会从第一个bytecode开始读起。

所以我们看字节码最前面的部分,也就是它的部署代码:608060405234801561001057600080fd5b5060b68061001f6000396000f3fe

对照 EVM 指令,我们可以识别出这段代码的含义:

然后我们看合约的运行代码:

综合以上可以发现,合约的运行代码的架构是这样的:

初始化操作、函数选择器这些,是 solc 在编译 Solidity 程序的时候自动生成的。如果我们砍掉这些复杂的东西,直接把我们想要的核心功能编码上去,不就可以在 10 条以内opcodes 实现既定功能了吗?

通过分析 图4 的 whatIsTheMeaningOfLife() 函数调用栈可以得知,让智能合约返回 “42” ( 十六进制 0x2a) 的关键在于 先用 mstore 指令将 0x2a 放入 Memory , 再用 return 指令将内存里的 0x2a 返回即可。至于那些函数名称和函数签名,只是高级语言的编译产物,直接用汇编实现的话,我们直接用这段代码读写内存,完全没有必要搞那些花里胡哨:

以上代码相当于构造了一个十分小的合约“运行代码”。前面我们说过,EVM 执行代码时是按照自上而下的顺序执行的,代码中没有其他入口点,始终从顶部 (也就是第一行 opcode ) 开始执行。而且我们编写的代码并没有函数选择器,也就是说,当外部账户调用该它时,无论传递给它什么样的参数、什么样的函数签名, EVM 都只会从它的 [00] 处开始执行,老老实实地走到 [09],然后 return 给我们一个 0x20.

但这只是运行代码,还记得本文开头说的那三段字节码吗?是的,我们还差一个“运载火箭”(部署代码),把这段运行代码给发射出去:

部署代码的结构基本没怎么变,之前已有解析,此处就不罗嗦了,唯一的区别是把复制到内存的长度由 b6 改为 0a  : 608060405234801561001057600080fd5b50600a8061001f6000396000f3fe

然后把他们拼接到一起,记得部署代码在前、运行代码在后,最后我们把这段代码发射出去就 OK了:

你将得到一个超级小巧、只有 10 个字节、无论传递什么参数都 只 会 返 回  42  的 “智能合约” (这么说看起来并不智能的样子……)

全文完。

关于作者:

https://twitter.com/0xNezha

来源:bress

Bress

个人专栏

阅读更多

金色早8点

Odaily星球日报

潘达看Web3

DeFi之道

区块律动BlockBeats

比推 Bitpush News

标签:以太坊ODECODCODE以太坊币现在的价格是多少MasternodecoinIncodiumConcretecodes

莱特币最新价格热门资讯
区块链:2022年中国需要怎样的区块链人才?

全球区块链领域核心人才正从金融导向型转向技术导向型。近年来,在地缘、疫情等乌云的笼罩下,一定程度上而言,全球化正在减弱,世界加速割裂,人们都期待下一次技术革命加速到来,以改变现状.

1900/1/1 0:00:00
元宇宙:元宇宙 终归要回归产业

仅仅只是谈元宇宙本身,是无论如何都无法获得长久发展的。只有将元宇宙与产业深度联系在一起,让元宇宙附着在产业身上,从产业当中汲取营养,它的生命才可以长久.

1900/1/1 0:00:00
元宇宙:以太坊将成为元宇宙的货币?

这些天来,元宇宙(metaverse)一直是一个热门话题,在我们最近的播客中,Raoul Pal 将其定义为“数字流动性”.

1900/1/1 0:00:00
NFT:我眼中区块链各个赛道正在演进的技术趋势

说下近期各个板块看到的正在发生的,以及未来6-12个月可能出现的趋势整体会分为公链,Defi(Dex,借贷,稳定币,合成资产等) , NFT , Gamfi.

1900/1/1 0:00:00
加密货币:观点:DeFi和区块链游戏 两者中谁才是杀手级应用?

“杀手级应用程序”可以被认为是一种具有巨大价值的应用程序,它确保了与其相关的技术的成功。简而言之,杀手级应用就是让其底层技术首次被广泛理解,为主流采用打开了闸门.

1900/1/1 0:00:00
API:ERC-20、ERC-721、ERC-1155、ERC-4626 和可组合性

来源:/img/2022103215946/0.jpg" />以太坊是一台世界计算机。它是由匿名和不受信任的节点组成的网络所维护的共享资源;通过共识达成一致,并且在经济上保障网络的安全.

1900/1/1 0:00:00