跳到主要内容

EVM 兼容性

OXN 在 enclave 内运行一个完全兼容的 EVM。实际上,几乎所有能在以太坊上跑的合约都能在 OXN 上无修改运行。本页记录那少数行为有差异的地方,让你在踩坑前先看到它们。

必须调的编译器设置

evmVersion 锁定为 "paris" 这是 OXN 上最重要的一个设置,也是 "invalid code" 错误最常见的来源。

Solidity 0.8.20 及以后默认 evmVersion: "shanghai",会生成 PUSH0 opcode (0x5F)。OXN 运行时尚未实现 PUSH0。用 Shanghai 默认编译的合约能成功部署,但运行到 PUSH0 的路径会 revert 报 invalid code——典型 Solidity 产物里这样的路径会有很多个。

工具链设置
Hardhathardhat.config.jssolidity.settings.evmVersion: "paris"
Foundryfoundry.tomlevm_version = "paris"
solc-jssettings.evmVersion: "paris"

诊断技巧:如果你升级 solc 之后 bytecode.length 显著增大、又开始出 invalid code,很可能就是 PUSH0。paris 编译的 ERC-20 通常约 5.8 KB;shanghai 编译的约 6.2 KB,含约 180 条 PUSH0 指令。

Opcode 支持矩阵

EVM 版本引入的 opcodeOXN 支持
Frontier基础指令集完全
HomesteadDELEGATECALL完全
ByzantiumRETURNDATASIZERETURNDATACOPYREVERTSTATICCALL完全
ConstantinopleSHLSHRSARCREATE2EXTCODEHASH完全
IstanbulCHAINIDSELFBALANCE、gas 调整完全
BerlinEIP-2929 gas 重定价完全
LondonEIP-1559(base fee)、BASEFEE opcode部分(BASEFEE 返回 0 或固定值;无 EIP-1559 费用拍卖)
ParisThe Merge(DIFFICULTYPREVRANDAO完全
ShanghaiPUSH0、warm COINBASE、EIP-3651不支持
Cancun瞬态存储(TLOADTSTORE)、MCOPYBLOBHASH不支持

evmVersion: "paris" 就在支持范围内。

标准 EVM 预编译合约

以太坊标准预编译(0x010x0a)支持情况:

地址功能OXN 支持
0x01ecrecover完全
0x02sha256完全
0x03ripemd160完全
0x04identity完全
0x05modexp完全
0x06ecAdd(bn128)完全
0x07ecMul(bn128)完全
0x08ecPairing(bn128)完全
0x09blake2f完全
0x0apointEvaluation(KZG)不支持

OpenZeppelin、Solmate 以及大多数标准库只用 0x010x09,这些全部在场。pointEvaluation(用于 EIP-4844 blob 验证)在 OXN 上不需要,因为 OXN 没有 blob 交易。

与以太坊的行为差异

区块环境。

Opcode / 全局变量以太坊OXN
block.number以太坊区块高度OXN 区块高度
block.timestamp区块的 Unix 时间戳一致
blockhash(n)区块 n 的哈希(最近 256)一致
block.chainid1(主网)186(OXN 测试网)
block.coinbase矿工 / 提议人地址零地址或固定哨兵值
block.difficulty / PREVRANDAO随机数信标固定哨兵值——不要用作随机源
block.basefeeEIP-1559 base fee0 或固定值——当前用 legacy 费用模型

随机数。 block.difficulty / PREVRANDAOblock.timestampblock.hash 都是公开可预测的。在机密合约里不要用它们做随机数。Sapphire.randomBytes 预编译——见预编译:随机数

Gas 估算。 显式设置 gasLimit,不要依赖 eth_estimateGas。见 Gas 与手续费

事件日志可见性。 以太坊上:任何观察者都能解码所有事件。OXN 上:加密,只有 emit 它们的调用者能解码。见机密性模型

Revert reason 可见性。 以太坊上:任何观察者都能读到 revert 原因。OXN 上:加密,只有调用者能解码。没有调用者的会话密钥,从外部调试不可能。

测试合约的 OXN 兼容性

发布前的快速清单:

  • 编译器配置里 evmVersion: "paris"
  • 没有使用 PUSH0(隐式满足——来自 evmVersion)
  • 不依赖 block.difficulty / PREVRANDAO 做随机
  • 不依赖 EIP-1559 费用参数(maxFeePerGasmaxPriorityFeePerGas
  • 不使用瞬态存储(TLOADTSTORE
  • 每笔交易显式 gasLimit
  • 事件设计考虑了 OXN 加密模型(如需全局索引,加一份公开事件或用中继)

集成测试跑在 OXN 测试网上,而不是只跑本地 Hardhat network。本地模拟器不建模机密性、不建模 OXN 特有的 opcode 支持。

从以太坊迁移的成本

大多数合约的迁移是两行改动:编译器配置里的 evmVersion: "paris",加上部署脚本里的显式 gasLimit

用到加密特性(Sapphire.encrypt、签名查询等)的合约是 OXN 原生的,在公开 EVM 链上编译不过——这是预期。如果迁移目标是让一份合约在以太坊和 OXN 上都能跑,把 OXN 特有代码路径放在开关后或独立合约里。

分步指南见将以太坊 dApp 迁移到 OXN

下一步