跳到主要内容

编译合约

OXN 跑的是标准 EVM。大多数编译器配置无需修改就能用。但有两个设置是不可妥协的,本页覆盖这两个以及常见坑。

必调的两个设置

1. evmVersion: "paris"——必需。

更晚的 EVM 版本(shanghaicancun)引入了 OXN 未实现的 opcode(PUSH0TLOADTSTOREMCOPYBLOBHASH)。用更晚目标编译的合约能成功部署,但运行时会 revert 报 invalid code

2. Solidity ^0.8.20 或更新,加上 paris 目标。 evmVersion 编译器 flag 早在 0.8.20 前就有了;0.8.20 只是默认值切到 shanghai 的版本。

工具链配置行
Hardhathardhat.config.jssolidity.settings.evmVersion: "paris"
Foundryfoundry.tomlevm_version = "paris"
solc-js标准 JSON 输入里 settings.evmVersion: "paris"

优化器

Solidity 优化器在 OXN 上正常工作。推荐设置:

optimizer: { enabled: true, runs: 200 }

runs 是"预期每部署的交易数"——数值越大优化运行时成本、越小优化部署成本。200 是平衡默认值。

对加密状态上有大量计算的合约,可以考虑提到 1000——加密开销基本恒定,每调用的优化会有回报。

Solidity 版本兼容矩阵

Solidity 范围推荐 evmVersion备注
0.8.19 及更早paris(默认)无需显式覆盖即可用。
0.8.200.8.24paris(显式)默认是 shanghai必须显式覆盖
0.8.250.8.27paris(显式)默认是 cancun必须显式覆盖

更早的 Solidity 版本(0.7.x、0.6.x)能跑老代码,但缺少现代语言特性。推荐 0.8.24 作为稳定当前默认。

推荐的 hardhat.config.js 片段

module.exports = {
solidity: {
version: "0.8.24",
settings: {
evmVersion: "paris",
optimizer: { enabled: true, runs: 200 },
},
},
};

推荐的 foundry.toml 片段

[profile.default]
solc = "0.8.24"
evm_version = "paris"
optimizer = true
optimizer_runs = 200

编译错误与修法

"Compiler error: Source file requires different compiler version"——pragma solidity 与配置的编译器不匹配。改 pragma 或改配置。

"Warning: This contract has a payable fallback function"——与 OXN 无关。与以太坊行为一致。

"Error: PUSH0 was introduced in Shanghai but the current EVM version is Paris"——反过来。这个错误意味着编译器以 paris 触发,但源码(或导入的库)需要 Shanghai 特性。检查内联汇编里是否有显式 PUSH0

字节码大小诊断

如果不确定是不是意外用 shanghai 编译了,检查字节码大小:

const artifact = require("./artifacts/contracts/MyToken.sol/MyToken.json");
const bytecodeLength = artifact.bytecode.length / 2 - 1; // hex 长度 -> 字节长度
console.log(`bytecode size: ${bytecodeLength} bytes`);

const push0Count = (artifact.bytecode.match(/5f/g) || []).length;
console.log(`potential PUSH0 count: ${push0Count}`);

paris 编译的 ERC-20 大约 5,800 字节,基本没有 5f 字节。shanghai 编译的约 6,200 字节,含约 180 个 5f 字节——那些就是 PUSH0 指令。

push0Count 高说明你用错了目标。

下一步