投资百科/加密货币/EVM以太坊虚拟机是什么?智能合约代码如何被每个节点执行?

EVM以太坊虚拟机是什么?智能合约代码如何被每个节点执行?

EVM是以太坊智能合约的确定性执行环境,负责字节码、Gas、存储和调用。本文通过交易流程、Opcode、回滚与实操核验讲清原理。

2026-06-24

EVM(Ethereum Virtual Machine,以太坊虚拟机)是以太坊执行智能合约的确定性计算环境。用户发送交易后,不是某一台中心服务器决定结果,而是网络节点按照相同EVM规则执行字节码,并对新的账户、余额与合约存储状态达成一致。

EVM也被许多兼容链采用。“EVM兼容”通常表示可以使用相似地址、字节码和开发工具,不表示这些链拥有与以太坊相同的共识、资产安全或去中心化程度。

定义

EVM可以理解为一台由协议定义的虚拟计算机。它读取:

  • 当前世界状态;
  • 发起账户与交易参数;
  • 合约字节码;
  • 调用数据Calldata;
  • 区块环境;
  • 可用Gas。

执行后输出新的状态、日志、返回值或回滚结果。所有验证节点必须得到一致结果,否则无法对区块状态根达成共识。

从交易到执行的完整流程

  1. 钱包构造交易,包括Chain ID、Nonce、目标地址、Value、Calldata、Gas参数。
  2. 用户用私钥签名并广播。
  3. 节点检查签名、Nonce、余额和基础格式。
  4. 交易进入Mempool,等待验证者或构建者选择。
  5. 交易被放入区块后,EVM按顺序执行。
  6. 每个Opcode消耗Gas并改变内存、栈或存储。
  7. 成功时状态提交,失败时状态修改回滚。
  8. 节点计算新的State Root并验证区块。

交易哈希存在只表示交易被创建;Receipt Status与状态变化才能说明执行是否成功。

EVM是栈式机器

EVM主要使用256位字的栈进行计算。Opcode从栈顶取参数,再把结果压回栈。

例如简单加法的概念流程:

  1. PUSH1 0x02
  2. PUSH1 0x03
  3. ADD

执行后栈顶得到5。Solidity等高级语言会被编译成EVM字节码,节点实际执行的不是源代码文本,而是部署后的字节码。

因此,验证合约时要确认源代码与链上字节码匹配。网页展示一份代码不代表它就是当前地址正在执行的实现。

账户与状态

EVM世界状态包含外部账户和合约账户。外部账户由私钥控制;合约账户由代码控制。

每个账户可包含Nonce、余额、代码哈希和存储根。合约状态不是一个普通数据库表,而是通过键值存储映射并纳入状态树。

交易按顺序执行。前一笔交易改变的余额或存储会成为下一笔输入,因此同一区块内排序可能影响结果,并产生MEV。

Storage、Memory与Calldata

Storage

持久保存在链上状态中,交易结束后仍存在。写Storage通常Gas较高,因为会增加或修改全网维护的状态。

Memory

仅在一次外部调用执行期间存在,结束后清除。扩展Memory也消耗Gas,但通常低于持久存储。

Calldata

交易或外部调用附带的只读输入。函数选择器和参数通常编码在Calldata中。它不等于“安全的人类可读消息”,恶意前端可以构造任意字节。

签名前应解码Calldata,确认调用的方法、参数、地址和授权额度。

Gas为什么存在?

EVM支持通用计算,若没有资源计价,攻击者可以提交无限循环或大量存储,让所有节点无法完成执行。

每个Opcode有Gas成本,交易设定Gas Limit。执行每一步扣除Gas;Gas耗尽时交易失败,状态修改回滚,但已经消耗的计算资源仍需付费。

费用粗略关系:

交易费 = Gas Used × 有效Gas价格

转账、代币授权、DEX交换和复杂DeFi操作使用Gas不同。Gas Limit是最多允许消耗量,不是一定支付金额。

Out of Gas与Revert的区别

Out of Gas表示执行资源耗尽。Revert是合约主动终止并返回错误数据,例如滑点超限、权限不足或余额不够。

两者通常都会回滚当前交易状态,但Gas处理和错误信息不同。界面只显示“失败”时,应查看Receipt、Revert Reason、Trace和事件日志。

内部调用失败也可能被外层合约捕获,整个交易Status仍成功。必须检查实际代币余额与事件,不能只看顶部绿色状态。

原子执行

一笔EVM交易中的多个调用通常作为整体执行。若未被捕获的错误发生,之前状态修改回滚,避免只完成交换的一半。

例如闪电贷在同一交易中借款、交易、偿还。交易结束前未归还,整个状态回滚。

原子性不消除价格风险、MEV和合约Bug。攻击者可以在同一交易内组合多个协议,放大重入、预言机和治理漏洞。

合约调用案例

用户在DEX把1 ETH换成USDC。钱包发送给路由合约的Calldata可能包含:

  • 输入代币与输出代币;
  • 输入数量;
  • 最低输出;
  • 路径;
  • 收款地址;
  • 截止时间。

EVM执行路由合约,再调用池合约转移资产、更新储备并发出事件。若最终输出低于最低值,合约Revert,资产状态回滚,但Gas仍消耗。

实操中要检查最低输出与截止时间。签名页面只写“与合约交互”远远不够。

Delegatecall与代理合约

CALL在被调用合约自己的Storage上下文执行;DELEGATECALL执行另一地址代码,却使用调用者Storage与身份上下文。

代理合约利用Delegatecall实现升级:代理保存状态,实现合约提供逻辑。管理员改变实现地址后,同一代理地址会执行新代码。

这也是风险来源。查看合约安全时要找到Implementation、Admin、Timelock和升级历史,不能只审计代理壳。

Reentrancy为什么发生?

合约向外部地址调用时,控制权暂时交给对方。若自身状态尚未更新,恶意合约可在第一次调用结束前重新进入原函数,重复提款。

常见防御包括Checks-Effects-Interactions、Reentrancy Guard和Pull Payment。EVM按调用栈执行,理解外部调用顺序比只看函数名称重要。

审计“使用最新版编译器”不能自动消除业务逻辑重入。

Event Logs是什么?

合约可通过LOG Opcode产生事件。日志便于钱包、浏览器和索引器检索,但不会被其他合约像Storage一样直接读取。

事件不是状态本身。恶意或有Bug合约可以发出看似成功的Transfer事件,却不按预期改变余额;也可能改变状态但漏发事件。

验证结果应读取合约状态与余额,日志用于辅助索引。跨链桥若只依赖事件,还要证明事件来自最终且正确执行的链。

EVM确定性

所有节点必须对相同输入得到相同结果,因此合约不能直接读取随机网页、当前股票价格或本地文件。

外部数据需要Oracle以链上交易形式输入。所谓随机数也需使用可验证随机、提交揭示或协议随机源;直接使用区块时间和哈希可能被出块者有限操纵。

确定性保证节点一致,不保证输入真实。Oracle错误会被EVM确定地执行成错误结果。

怎样实际检查一笔EVM交易?

  1. 核对Chain ID与目标地址。
  2. 确认目标是否代理合约及当前实现。
  3. 解码函数选择器与参数。
  4. 检查Value和代币数量小数位。
  5. 查看Approval是否无限。
  6. 用交易模拟查看余额和权限变化。
  7. 设置合理滑点、截止时间与Gas参数。
  8. 广播后查看Receipt Status。
  9. 检查内部调用、日志和最终余额。
  10. 失败时读取Revert Reason,不盲目提高Gas重试。

大额或陌生合约先用隔离钱包和小额测试,不要让长期资产钱包拥有无限授权。

EVM兼容不等于同样安全

两条EVM链可运行相同Solidity合约,却使用不同验证者、桥、排序器、最终性和Gas代币。

同一地址格式也会增加误转风险。链A上的USDC合约地址与链B可能不同;钱包切换网络后,要重新核对资产合约。

EVM兼容降低开发迁移成本,不会继承以太坊全部经济安全。

客户端与硬分叉

EVM Opcode和Gas规则会通过协议升级改变。不同客户端必须实现相同规则,否则可能在同一交易上计算不同状态并分叉。

节点运营者需要及时升级并核对目标分叉版本。合约开发者也要关注新Opcode、弃用行为和Gas变化。

“合约不可变”不代表执行环境永远完全不变,底层协议仍会升级。

常见误区

误区 1:Solidity源码就是链上执行内容

链上执行字节码,必须验证源码编译结果与地址匹配。

误区 2:交易失败就不会花钱

失败执行仍消耗节点资源,通常会支付Gas。

误区 3:Status成功表示所有内部动作符合预期

外层合约可能捕获内部失败,应检查最终状态。

误区 4:Event就是资产状态

日志是索引信息,余额与Storage才是状态。

误区 5:提高Gas Price能修复Revert

Gas Price影响优先级;业务条件错误需要修正参数,盲目加价无效。

误区 6:所有EVM链共享相同安全性

执行兼容与共识、桥和治理安全是不同层。

常见问题 FAQ

EVM能运行任何程序吗?

理论上具备通用计算能力,但受Gas、区块限制和确定性要求约束。

合约地址有私钥吗?

普通合约账户由代码控制,没有像外部账户一样的私钥,但管理员可能拥有升级或权限密钥。

为什么读取合约有时不花Gas?

本地只读调用由RPC节点模拟,不写入共识状态;链上交易中的读取仍属于执行成本。

Nonce有什么作用?

外部账户Nonce确定交易顺序并防止同一签名交易被重复执行。

怎样判断Approval是否危险?

检查Spender、额度和可调用代币;不用的无限授权应撤销,并核对目标合约权限。

一句话总结

KEY TAKEAWAY

EVM是所有节点按相同规则执行字节码并更新状态的确定性环境;安全使用不只要看合约源码,还要核对链、代理实现、Calldata、Gas、内部调用、最终状态和底层网络,因为执行一致不等于输入与业务逻辑正确。