仅供教育参考,不构成投资或安全建议。EVM 行为取决于具体的链、分叉、状态、字节码、调用上下文、Gas 计费规则、客户端和协议升级。
直接答案
以太坊虚拟机是执行层的状态转换机,按照特定分叉的规则解释字节码。给定相同的有效前状态、顶层交易或消息、区块环境和分叉规范,符合规范的执行客户端必须算出相同的后状态或失败结果。EVM 不决定交易顺序,不提供共识最终性,不认证前端,也不会让每条 EVM 兼容链都具备与以太坊相同的安全性。
由外部签名的交易是顶层协议对象。合约之间的活动由嵌套的消息调用和调用帧组成,并非各自拥有交易 nonce、收据或哈希的独立交易。每个帧都有代码、程序计数器、256 位栈、内存、调用数据、返回数据、Gas 和执行上下文;持久存储属于账户,而瞬态存储在相应分叉规则下只存在于一笔交易期间。
工作原理
- 锁定执行快照:链及
chainId、网络、区块号和区块哈希、规范或最终化状态、分叉、执行客户端及规范修订版、前状态或状态根、交易类型、原始签名字节、交易哈希和收据。确定性以这一准确上下文为条件。 - 解码交易信封,并把执行前有效性与执行分开。验证签名和发送者、nonce、目的地址或合约创建、转账价值、调用数据、Gas 上限、费用字段、访问列表及各交易类型特有的字段。在纳入区块之前被拒绝的交易,并不是已经纳入并执行后发生状态回退的交易。
- 构建顶层消息和完整调用树。记录
CALL、STATICCALL、DELEGATECALL、合约创建及预编译合约帧;调用者、上下文地址、代码地址、msg.sender、msg.value、价值转移、调用数据、返回数据、转发的 Gas 和成功标志。区块浏览器所谓的内部交易是跟踪视图,并非签名交易。 - 跟踪每个帧的程序计数器、栈、内存、调用数据、返回数据、日志、持久存储和瞬态存储日志。
CALL使用被调用方的地址和存储上下文;DELEGATECALL在调用方的地址与存储上下文中执行目标代码,同时保留上游发送者和转账价值;STATICCALL禁止修改状态。 - 应用目标分叉的 Gas 规则:固有 Gas、操作码动态成本、内存扩展、冷访问与热访问、调用转发、津贴、预编译收费、退款及退款上限。然后依据已用 Gas 和有效 Gas 价格,单独计算交易费用,不与转账价值混在一起。Gas 估算有条件限制,不是保证。
- 按作用域处理帧结果。如果祖先帧最终提交,
RETURN会提交当前帧。REVERT会回退当前帧及其后代帧,返回数据,而且不一定耗尽当前帧的剩余 Gas;异常停机的规则不同。父帧可以捕获失败的低级调用并继续执行,因此即使子调用失败,顶层收据状态也可能是1。顶层交易纳入后即使失败,仍会消耗发送者 nonce 和实际支付的 Gas。 - 将收据状态、已用 Gas、日志、创建地址和返回数据,与前后状态中的余额、nonce、代码、持久与瞬态存储、代币账本、执行跟踪和区块状态根进行核对。必要时使用独立客户端重新执行;代理实现、存储布局、预编译合约、编译器 EVM 目标和分叉升级,应与共识最终性分开审计。
算例
- 已纳入区块的顶层回退及费用账本。 一笔类型 2 交易的 Gas 上限为
80,000,已用 Gas 为52,000,基础费用为20 gwei,最高优先费为3 gwei,最高费用为40 gwei。有效 Gas 价格是min(40, 20 + 3) = 23 gwei;实际费用为52,000 * 23 gwei = 0.001196 ETH,其中销毁52,000 * 20 gwei = 0.001040 ETH,优先费为52,000 * 3 gwei = 0.000156 ETH。未用的28,000 gas不收费。如果顶层执行回退,其存储、价值转移和日志影响都会撤销,但发送者 nonce 和实际费用仍会保留。 - 被捕获的子调用失败。 合约 A 初始为
A.x = 5。它调用 B;B 写入B.y = 9,发出日志后执行REVERT。B 的写入和日志均被回退。A 观察到success = false,写入A.x = 7并正常返回。最终收据状态为1,A.x = 7,B 则保持调用前的值。因此,顶层成功不能证明每个子调用都成功。 - DELEGATECALL 的存储上下文。 代理的
slot0 = 5,实现账户的slot0 = 99。实现代码读取槽位 0,加上7后写回。通过DELEGATECALL执行时,代理变为slot0 = 12,实现账户仍为slot0 = 99;所采用的是代理地址和存储上下文,上游发送者和转账价值保持不变。不兼容的存储布局可能损坏代理状态。 - 受分叉约束的 SELFDESTRUCT。 在 EIP-6780 规则下,一个已有合约持有
2 ETH,并向受益人 B 执行SELFDESTRUCT。B 收到2 ETH,合约余额变为零,但这个既有账户、代码和存储不会删除。只有合约在同一笔交易中创建并自毁时,才仍适用删除行为。这是受分叉约束的规则,不能向过去或每条 EVM 链外推。
风险
- 在错误的链、区块、分叉、客户端或前状态上重放。
- 把非规范或已被重组替代的状态当作最终执行上下文。
- 混淆执行前验证拒绝与纳入区块后的执行回退。
- 假设待处理交易的模拟结果会与之后纳入时的状态一致。
- 忽略顶层回退、异常停机或 Gas 耗尽。
- 漏掉被父帧捕获的子调用失败。
- 误读调用上下文、代码地址、调用方、发送者或转账价值。
- 因
DELEGATECALL存储布局不匹配而损坏代理状态。 - 允许重入攻击,或不安全地向外转移价值和控制权。
- 信任未经验证的返回数据、成功标志或自定义错误。
- 把日志或执行跟踪当作权威最终状态。
- 错算冷访问、热访问、内存或调用转发的 Gas。
- 错用退款、退款上限、津贴或
63/64规则。 - 使用错误的预编译地址、输入、Gas 规则或分叉语义。
- 混淆持久存储、内存和瞬态存储的生命周期。
- 预期在
STATICCALL内能成功修改状态。 - 沿用 EIP-6780 之前关于
SELFDESTRUCT删除状态的假设。 - 漏掉代理实现、管理员或编译器目标的漂移。
- 运行规则分歧或未升级的执行客户端。
- 从 EVM 兼容性推断共识、桥、代币、治理或最终性安全。
常见误区
- Solidity 源代码就是链上直接执行的对象。
- 已纳入区块的交易发生状态回退后不花费任何费用,nonce 也不变。
- 收据状态为
1就证明每个内部调用都如预期成功。 - 事件或执行跟踪就是权威的资产与存储状态。
- EVM 兼容性保证操作码、Gas、预编译合约、共识和安全性完全相同。
相关主题
来源
- Ethereum Virtual Machine (EVM) - Ethereum.org(查阅日期:2026-08-12)
- Ethereum Yellow Paper: a formal specification of Ethereum, a programmable blockchain - Ethereum Foundation(查阅日期:2026-08-12)
- Ethereum Execution Layer Specification - Ethereum Execution Specs(查阅日期:2026-08-12)
- Introduction to Smart Contracts - Solidity Documentation(查阅日期:2026-08-12)
- EIP-7: DELEGATECALL - Ethereum Improvement Proposals(查阅日期:2026-08-12)
- EIP-140: REVERT instruction - Ethereum Improvement Proposals(查阅日期:2026-08-12)
- EIP-2929: Gas cost increases for state access opcodes - Ethereum Improvement Proposals(查阅日期:2026-08-12)
- EIP-6780: SELFDESTRUCT only in same transaction - Ethereum Improvement Proposals(查阅日期:2026-08-12)