EVM的深入研究和分析

article/2025/10/30 23:35:41

最终目标是能够完整地理解已编译的Solidity合同
1、执行
evm-tools 安装
https://github.com/CoinCulture/evm-tools/blob/master/INSTALL.md
/home/xue/go/bin/evm --debug --code 366020036101000a600035045b6001900380600c57 --input 05

不同字节码编译成不同EVM指令
1、基本:disam显示指定地址后面的汇编代码
echo 60056004016000526001601ff3  | disasm
evm --debug --code 60056004016000526001601ff3
2、输入
echo 60003560203501 | disasm
evm --debug --code 60003560203501 --input 00000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000004

2、合约

字节码在evm部署后编译为EVM指令集
$ echo 6005600401 | evm-deploy | disasm 
600580600b6000396000f36005600401
0      PUSH1  => 05
$ evm --debug --code 600580600b6000396000f36005600401

3、安全性

同一个合约每次在evm部署后生成的 合约地址不同
1、生成合约地址
// Contract Address: 1F2A98889594024BFFDA3311CBE69728D392C06D
$ evm --code $(echo "60056004016000526001601ff3" | evm-deploy)  --datadir evm-data
// Contract Address: 14F6D12ECEBB7606C528880AD8B97C25AB7D4AD9
$ evm --code $(echo "60056004016000526001601ff3" | evm-deploy)  --datadir evm-data
2、向合约发送交易
$ evm --to 14F6D12ECEBB7606C528880AD8B97C25AB7D4AD9 --datadir evm-data
Datadir already exists
Loading database
Loading root hash 60209E93FEFD3DD5CF1D6B3FBDC33DA1B020C5B880A51E8306A3F5FDF269122A
Loaded account for receiver 14F6D12ECEBB7606C528880AD8B97C25AB7D4AD9
CODE: 60056004016000526001601FF3
VM STAT 0 OPs
OUT: 0x09

4、异常

//  5f 不是合理操作码
evm --debug --code 5f
// JUMP (0x56)  要求堆栈中至少有一个参数
evm --debug --code 56
// 0x0 不是一个JUMPDEST
evm --debug --code 600056
// gas 超出异常
evm --debug --gas 1 --code 6000

5、内存和存储

EVM的编译器实际上不会为字节码的大小、速度或内存高效性进行优化。相反,它会为gas的使用进行优化,这间接鼓励了计算的排序,让以太坊区块链可以更高效一点
一笔交易的每个零字节的数据或代码费用为 4 gas
一笔交易的每个非零字节的数据或代码的费用为 68 gas

0x200000000000000000000000000000000比exp(0x2, 0x81)更便宜
0x200000000000000000000000000000000字节码包含了很多的0,更加的便宜。
(1 * 68) + (32 * 4) = 196608160020a字节码更短,但是没有0。
5 * 68 = 340

6、合约
一个帐户最多只能有一个与之关联的程序 - 无论何时对合同进行交易,或者它是执行CALL操作码的另一个合同的目标,该合同的代码都将执行。部署后,合同代码可能不会更改。
合约创建时,通过将合同代码作为数据发送到空地址。通过创建新帐户,运行调用数据中指定的程序,以及将EVM返回的任何内容设置为新合同的代码,以太坊状态转换功能将此事件解释为合同创建事件。也就是说,在创建期间发送的代码与将存储在合同中的代码不同 - 它是所谓的“部署代码”,它包含在某些操作中包含的实际合同代码,这些操作将其复制到内存中并返回它。

合约编译的字节码通过evm部署转化为部署代码,再编译执行
$ echo 6005600401 | evm-deploy | disasm 
600580600b6000396000f36005600401
0      PUSH1  => 05

7、solidity
Solidity可编译为EVM。它也符合以太坊ABI,这是一个关于如何在调用数据中编码参数和函数调用的规范。 总之,调用数据的前四个字节是函数标识符,对应于函数签名的规范版本的sha3散列的前四个字节。 其余参数以填充方式传递给32字节。
无返回值:

contract Addition{int x;function add(int a, int b){x = a + b;}
}
(1)编译合约
solc --bin-runtime --optimize -o . add.sol
(2)反汇编:将内存中的机器码程序以指令助记符的形式显示出来
$ echo $(cat MyContract.bin-runtime)  | disasm 
606060405260e060020a6000350463a5f3c23b8114601a575b005b60243560043501600055601856
(3)验证函数标识符:通过运行solc --hashes add.sol,或通过散列规范签名
>>> import sha3
>>> sha3.sha3_256("add(int256,int256)").hexdigest()[:8]
'a5f3c23b`
(4)正确调用函数evm --debug --code $(cat Addition.bin-runtime) --input **a5f3c23b**00000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000004

带返回值:

contract Addition{int x;function add(int a, int b){x = a + b;}function get() returns (int){return x;}}
(1)编译:solc --bin --optimize -o . add.sol
(2)部署:
$ evm --code $(cat Addition.bin) --datadir evm-data
Loading database
Loading root hash 0000000000000000000000000000000000000000000000000000000000000000
Contract Address: 1F2A98889594024BFFDA3311CBE69728D392C06D
VM STAT 0 OPs
OUT: 0x606060405260e060020a60003504636d4ce63c81146024578063a5f3c23b146031575b005b600054606090815260
(3)调用 add方法 :
evm --datadir evm-data --to 0x1F2A98889594024BFFDA3311CBE69728D392C06D --input a5f3c23b00000000000000000000000000000000000000000000000000000000000000050000000000000000000000000000000000000000000000000000000000000004
(4)调用get方法
$ solc --hashes add.sol
======= Addition =======
Function signatures: 
6d4ce63c: get()
a5f3c23b: add(int256,int256)
(5)调用合约
Now we can call the contract:$ evm --datadir evm-data --to 0x1F2A98889594024BFFDA3311CBE69728D392C06D --input 6d4ce63c
Datadir already exists
Loading database
Loading root hash F3C30A7CD9769C45590C236816F2714E96198DBD7FEC33AE892E861816F548B2
Loaded account for receiver 1F2A98889594024BFFDA3311CBE69728D392C06D
CODE: 606060405260E060020A60003504636D4CE63C81146024578063A5F3C23B146031575B005B6000546060908152602090F35B60243560043501600055602256
VM STAT 0 OPs
OUT: 0x0000000000000000000000000000000000000000000000000000000000000009


1、EVM架构
EVM是一种简单的基于堆栈的架构
2、EVM的机器空间
EVM存储
2.1 堆栈
所有操作都在堆栈上执行。如PUSH / POP / COPY / SWAP,…
在这里插入图片描述
2.2 内存
内存是线性的,可以在字节级别进行寻址。使用MSTORE / MSTORE8 / MLOAD指令访问。内存中的所有位置最初定义为零。
内存
2.3 账户存储
存储是一个键值存储,可将256位字映射到256位字。使用SSTORE / SLOAD指令访问。存储中的所有位置最初都定义为零。
账户存储
2.4 EVM代码
EVM代码是EVM可以本机执行的字节代码。
2.5 执行模型
执行模型
3、信息调用
EVM可以向其他帐户发送消息。消息调用的深度限制为小于1024。
在这里插入图片描述
3.2 消息调用说明
消息调用由CALL指令触发。使用内存传递参数和返回值。
在这里插入图片描述
4、异常
在这里插入图片描述
5、Gas 和 fee
外部账户:Externally owned account (EOA)
RLP(递归长度前缀)的目的是编码任意嵌套的二进制数据数组,RLP是用于序列化以太坊中对象的主要编码方法。
以太坊中的所有可编程计算都需要收取费用(以gas计价)

在这里插入图片描述
6、输入和输出
EVM可以从消息调用中输入外部数据。EVM可以输出日志。 EVM还可以将值返回给Caller EVM。
输入数据说明图
7、字节顺序
内存为字节图(网络字节顺序)
MSB代表最高有效位,而LSB代表最低有效位。
字节指令和签名扩展指令的字节顺序图。
8、指令集
MUL:乘法 DIV:无符号整除运算 SDIV:有符号整除运算
合约账户CA
EVM code在EVM上运行,在创建期间代码evm code与存储在合约中的代码storage code不同 ,storage code作为“部署代码”,它包含嵌套在某些操作中的实际合约代码,这些操作将其复制到内存中并返回它。


http://chatgpt.dhexx.cn/article/8gbVleU2.shtml

相关文章

Ethereum EVM简介

1. 引言 首先需了解以下基本概念: 1)区块链2)世界状态3)账号4)交易5)消息6)去中心化账本7)原子性和顺序性 1.1 何为以太坊区块链? 以太坊可看成是基于交易的状态机&a…

误差向量幅度(EVM)

转自:http://blog.sina.com.cn/s/blog_6c46cb860100otm3.html 误差向量幅度(EVM):误差向量(包括幅度和相位的矢量)是在一个给定时刻理想无误差基准信号与实际发射信号的向量差。Error Vector Magnitude E…

WiFi基础知识

术语和定义 1. 发射功率RF Power 在给定频段范围内发射机通过天线对空间辐射的能量。 2. 矢量误差(EVM) EVM是发射信号理想状态下的IQ分量与实际发送信号的IQ分量之间的矢量差,如图1 所示,其数值等于误差矢量幅度与最大符号幅度之比(取百…

三分钟读懂什么是EVM

虚拟机指的是,通过软件模拟的、具备完整硬件系统功能并运行在隔离环境下的完整计算机系统,比如虚拟化物理机VMware、Java虚拟机等。实际上在PC上常见的各种手机模拟器、主机模拟器,也都是一种虚拟机。这样的虚拟机往往需要固件运行&#xff0…

射频指标之EVM

说到EVM首先先介绍下EVM是什么,其是指目标功率与实际功率的一个矢量差,用下图可以比较详细的表示: 下面就以几个问题来讨论EVM的问题: 1.问题背景: TC芯片输出的EVM正常,单独测试PA输出的EVM也正常&#…

.lib 静态链接库 的破解方法(局限)(1)

因为之前程序调用了一个试用版的.lib库 , 而这个库有时间限制 , 导致程序在试用期过后不能使用 . 然后编译之后要破解一下编译出来的程序 , 很难受 闲来无事,突然想破解一下.lib , 毕竟是个代码库 , 看看是不是破解完了在编译 , 能正常使用 结果当然是能正常用了 不然就没这…

InfluxDB源码编译、安装、配置及主从同步实现

先扯点蛋 公司有个项目要求使用InfluxDB时序数据库储存点东西。第一次听说还有这种数据库,哈哈哈,孤陋寡闻了,先从各位大佬的博客看起,慢慢学习,逐渐了解了之后在服务器上进行安装。直接使用官方包进行安装很简单&…

一种破解静态链接库(.lib)的简单方法

一种破解静态链接库(.lib)的简单方法 作者:游蓝海 博客:http://blog.csdn.net/you_lan_hai 最近,在研究某代码时,遇到这样一个问题:整个解决方案中,有一个工程没有cpp源码,只有头文件跟一个静…

Linux下静态库生成和使用

一.静态库概念 1.库是预编译的目标文件(object files)的集合,它们可以被链接进程序。静态库以后缀为”.a”的特殊的存档(archive file)存储。 2.标准系统库可在目录/usr/lib与/lib中找到。比如,在类Unix系统中C语言的数序库一般…

libuvc介绍及简单使用

libuvc是一个用于USB视频设备的跨平台库,构建在libusb之上,编译libuvc时需要依赖libusb。libuvc的License为BSD,最新发布版本为0.0.6,源码地址: https://github.com/libuvc/libuvc libuvc支持在非windows系统上直接编译&#xff0…

linux下封装函数库——动态库.so和静态库.a(代码实现及链接方式)

在linux环境下的链接库分为静态链接库(.a库)和动态链接库(.so库),其作用是把C程序编译好做成一种可执行链接文件,主程序文件调用这些程序的函数接口是可以使用a库或so库,在主程序中只需要includ…

Hyperledger fabric应用的多机部署(自动化一键部署)

前面关于fabric部署的介绍都是基于单机环境下的,实际生产环境中一般会根据应用场景将节点分开部署在多台物理机上,面临的难题主要是不同主机间的节点如何通过网络进行通信。文章最后会分享一键完成多机增加组织的自动化部署脚本。 前言 这里仍然以balan…

Linux系统编程makefile制作动态库和静态库

目录 制作动态库 制作静态库 首先准备简单的add.c&#xff0c;sub.c,main.c,head.h.具体代码如下 #head.h文件 int Add(int a, int b); int Sub(int a, int b);#add.c文件 #include <stdio.h> int Add(int a, int b) {return a b; }#sub.c文件 #include <stdio.h&…

Linux动态库的下载与配置(以libevent库为例)

** Linux动态库的下载与配置 ** 本章以下载、安装、配置libevent库为例(安装libevent的前提是已经成功安装openssl库) 一、libevent的下载 https://libevent.org/ //官网下载源码包如果学习下载1.0版本为好&#xff0c;使用可以下载2.0版本 1.如果Linux已经进行桥接联网&am…

Linux下编译安装libusb动态库(.so) - libus1-0 vs libusb-0.1

最近在调试代码的过程中&#xff0c;发现libusb库中的一些方法没办法debug到&#xff0c;所以试着下载了一版源码&#xff0c;编译安装到指定的目录。这样&#xff0c;在工程的pro文件中&#xff0c;直接指定库和头文件的目录就可以引用自己编译的libusb库了。 在网上查了相关的…

linux编译生成动态库、静态库,以及使用

一、介绍 在实际开发过程中&#xff0c;当代码的文件较多&#xff0c;可以将一部分代码编译成动态库或者静态库然后再加载到程序中使用 编译过程 1、预编译 2、编译 3、汇编 4、链接 静态库和动态库的差异 1、链接静态库简单理解就是复制目标代码嵌入可执行文件中 2、动态库是…

Linux·libusb源码编译

libusb系列--Linux下libusb源码编译​​ ​ ​源码下载及解压​​ ​​下载源码​​ ​​解压下载的源码压缩包​​ ​​打开终端​​ ​​准备编译环境​​ ​​安装make dh-autoreconf​​ ​​安装 libudev-dev​​ sudo ​./autogen.sh​ ​​​​sudo ./configure --prefi…

ESP32如何用makefile直接编译生成.a静态库

目录 编译痛点前提环境编译准备makefile代码编译痛点 开发过esp系列的攻城狮们都知道,esp32的sdk包含了编译器、组件代码和例程代码,编译都是基于cmake的,都是整体一起编译,CMakeList.txt,component.mk,project.mk等等一系列和编译相关的文件,如果你想要自己编译一个自…

Linux 环境下的静态库生成与使用

目录 一&#xff0c;简介 二&#xff0c;如何生成静态链接库 1.准备测试程序 三&#xff0c;如何使用静态链接库 1.生成静态链接库 2.使用静态链接库 一&#xff0c;简介 这里我们只讲 Linux 环境下的静态库与动态库的生成与使用&#xff0c; Windows直接用VS直接就能生成…

Linux 下libusb编译与生成动态链接库

一、前言 上一篇文章提到了怎样使用Ubuntu 安装libusb&#xff0c;忘了如何将如何编译。 二、libusb使用GCC 编译 正常来讲&#xff0c;使用 gccc xxx.c -o xxx -I/usr/include -lusb-1.0 就可以了&#xff0c;如下图&#xff1a; 但是&#xff0c;当使用Ubuntu 12.04 使用…