
Foundry 运行时硬分叉覆盖Forge 与 Chisel 共享的--hardforkCLI 参数解析【免费下载链接】foundryFoundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.项目地址: https://gitcode.com/GitHub_Trending/fo/foundry本文基于 Foundry 仓库变更记录 runtime-hardfork-cli-override.md 展开。该变更引入了一个Forge 与 Chisel 命令共享的--hardfork覆盖参数用于直接指定 EVM 运行时的硬分叉runtime EVM hardfork并分别以chisel: minor、forge: minor、foundry-cli: minor三个版本级别发布。读完本文你将掌握该参数的语法、命名空间规则、与foundry.toml配置及evm_version的优先级关系以及它在源码中的解析与校验链路。一、为什么需要运行时硬分叉覆盖在 Foundry 中EVM 版本存在两个容易混淆的维度编译期 EVM 版本evm_version决定 Solidity 编译器solc以哪个版本语义生成字节码配置项位于 config/src/lib.rs 中的evm_version: EvmVersion。运行时 EVM 硬分叉hardfork决定 revm 执行字节码时采用哪套 opcode 语义、gas 规则与预编译合约由Config中的hardfork: OptionFoundryHardfork字段承载。在引入本次变更之前Forge 与 Chisel 对运行时硬分叉的指定方式并不一致Forge 主要依赖foundry.toml中的配置以及部分命令各自携带的参数而 Chisel 需要自行处理硬分叉解析。本次变更的核心动作是在共享的 CLI 参数层foundry-cli新增统一的--hardfork参数让 Forge 与 Chisel 都通过同一套机制覆盖运行时 EVM 硬分叉从而消除两条命令之间行为不一致的问题。从变更记录的 frontmatter 可以看到它同时触及三个 crate说明这是一次跨命令的共享能力收拢而非某个命令的独有特性。二、参数定义EvmArgs中的--hardfork--hardfork参数定义在共享的 EVM 参数结构体EvmArgs中位于 crates/cli/src/opts/evm.rs/// The runtime EVM hardfork to use. /// /// Network-specific hardforks must be namespaced, for example tempo:T5. #[arg(long, value_name HARDFORK)] #[serde(skip_serializing_if Option::is_none)] pub hardfork: OptionFoundryHardfork,关键信息参数名为--hardfork取值类型是OptionFoundryHardfork即未指定时为空由配置层兜底文档注释明确提示网络专属硬分叉必须带命名空间前缀例如tempo:T5value_name HARDFORK说明该参数接受一个字符串值该字段通过 serde 序列化进 figment 配置提供器EvmArgs实现了Provider从而可以无缝合并进Config的解析流程见 evm.rs 的data()实现。EvmArgs在注释中明确说明了自己在配置层级中的位置EvmArgsandEnvArgstake the highest precedence in the Config/Figment hierarchy.也就是说通过--hardfork传入的值在配置合并时拥有最高优先级能够覆盖foundry.toml中的同名配置。三、FoundryHardfork统一的硬分叉枚举--hardfork的值类型FoundryHardfork定义于 crates/evm/hardforks/src/lib.rs是一个覆盖多网络的统一枚举pub enum FoundryHardfork { Ethereum(EthereumHardfork), #[cfg(feature optimism)] Optimism(OpHardfork), Tempo(TempoHardfork), #[cfg(feature monad)] Monad(MonadHardfork), }它把四类网络的硬分叉收拢为一个类型网络枚举变体说明EthereumEthereum(EthereumHardfork)即 alloy 的EthereumHardfork如Shanghai、Cancun、Prague等OptimismOptimism(OpHardfork)需要启用optimismfeature如op:...TempoTempo(TempoHardfork)Tempo 网络专属硬分叉如tempo:T5MonadMonad(MonadHardfork)需要启用monadfeature如monad:MonadNine命名空间解析规则FromStr实现lib.rs定义了 CLI 字符串到枚举的映射规则不带冒号的裸字符串如--hardfork shanghai按 Ethereum 硬分叉解析带命名空间的字符串ns:fork按前缀匹配网络且前缀大小写不敏感to_ascii_lowercase硬分叉名中的-与空格会被规范化为下划线支持的命名空间别名eth/ethereum→ Ethereumop/optimism→ Optimism需optimismfeaturet/tempo→ Tempom/monad→ Monad需monadfeature未知命名空间时回退尝试 Ethereum 解析仍失败则报错unknown hardfork {raw}序列化与反序列化序列化时lib.rsEthereum 硬分叉直接输出裸名称如prague其余网络输出network:hardfork格式如optimism:...、tempo:T5、monad:MonadNineDeserialize同样走FromStr因此foundry.toml中的hardfork tempo:T3与 CLI 上的--hardfork tempo:T3使用完全一致的解析语义。四、实战用法Forge指定测试运行时的硬分叉Forge 的命令如forge test通过共享EvmArgs获得该参数例如# 用 Ethereum Prague 硬分叉运行测试 forge test --hardfork prague # 指定 Tempo 网络硬分叉注意命名空间 forge test --hardfork tempo:T5 # 指定 Monad 硬分叉 forge test --hardfork monad:MonadNine在 Forge 执行链路上--hardfork的值最终会进入执行配置TestConfig中的hardfork: OptionFoundryHardfork字段见 multi_runner.rs并在构建执行器时通过resolve_execution_spec解析为具体的spec_id同时传递给调用跟踪解码器with_hardfork保证执行语义与 trace 解码使用同一个硬分叉见 forge/src/cmd/test/mod.rs。ChiselREPL 会话的硬分叉Chisel 同样继承了该参数例如# 以 Cancun 硬分叉启动交互式会话 chisel --hardfork cancun # 切换到 Tempo 网络硬分叉 chisel --hardfork tempo:T3Chisel 的会话配置结构体ChiselSessionConfig中新增了resolved_hardfork: OptionFoundryHardfork字段标注#[serde(skip)]不持久化在执行前通过resolve_execution_spec解析并写入 EVM 环境见 chisel/src/executor.rs同时用于 trace 解码器的硬分叉上下文见 chisel/src/dispatcher.rs。与--chain/--evm-version的关系--evm-versionevm_version仍只影响编译--hardfork直接覆盖运行时语义配置层提供了优先级兜底Config::evm_spec_id()的实现config/src/lib.rs为pub fn evm_spec_idSPEC: FromEvmVersion(self) - SPEC { self.hardfork.map(Into::into).unwrap_or_else(|| evm_spec_id(self.evm_version)) }即只要配置了hardfork运行时 spec 就以它为准否则回退到evm_version推导。这解释了为什么--hardfork被称为覆盖override。五、foundry.toml中的对应配置--hardfork与配置文件字段一一对应。在foundry.toml中可以这样写[profile.default] # 与 --hardfork prague 等价 hardfork prague # 网络专属硬分叉必须命名空间化 # hardfork tempo:T3仓库测试 config/src/lib.rs 验证了该行为#[test] fn tempo_hardfork_infers_tempo_network() { figment::Jail::expect_with(|jail| { jail.create_file( foundry.toml, r# [profile.default] hardfork tempo:T3 #, )?; let config Config::load().unwrap(); assert_eq!(config.hardfork, Some(FoundryHardfork::Tempo(TempoHardfork::T3))); assert!(config.networks.is_tempo()); Ok(()) }); }注意一个附带效果指定命名空间的硬分叉会自动推断并激活对应网络。例如hardfork tempo:T3会让config.networks.is_tempo()变为truemonad:MonadNine会推断 Monad 网络见 config/src/lib.rs 的namespaced_hardfork_infers_monad_network测试。六、冲突校验与安全边界Config在加载后会调用normalize_hardfork_settings()config/src/lib.rs对硬分叉与网络配置做一致性校验fn normalize_hardfork_settings(mut self) - Result(), Error { self.networks.validate().map_err(Error::from)?; let Some(hardfork) self.hardfork else { return Ok(()) }; self.networks self.networks.normalize_for_hardfork(hardfork).map_err(Error::from)?; Ok(()) }仓库测试hardfork_rejects_conflicting_networkconfig/src/lib.rs验证了冲突检测逻辑#[test] fn hardfork_rejects_conflicting_network() { figment::Jail::expect_with(|jail| { jail.create_file( foundry.toml, r# [profile.default] tempo true hardfork shanghai #, )?; let err Config::load().unwrap_err(); assert!( err.to_string().to_lowercase().contains( hardfork shanghai conflicts with network config tempo ) ); Ok(()) }); }结论当--hardfork指定的硬分叉与已激活的网络如tempo true冲突时配置加载会直接报错错误信息形如hardforkshanghaiconflicts with network configtempo避免在错误的语义下静默执行。反之celo_network_accepts_ethereum_hardfork测试config/src/lib.rs表明Celo 网络可以合法地接受 Ethereum 硬分叉如hardfork prague说明冲突校验是网络感知的而非一刀切。七、CLI 层的解析测试EvmArgs自身的单元测试hardfork_arg_selects_networkevm.rs完整演示了从 CLI 字符串到Config的整条链路#[test] fn hardfork_arg_selects_network() { let args EvmArgs::parse_from([foundry-cli, --hardfork, tempo:T5]); let hardfork tempo:T5.parse::FoundryHardfork().unwrap(); assert_eq!(args.hardfork, Some(hardfork)); let config Config::from_provider(Config::figment().merge(args)).unwrap(); assert_eq!(config.hardfork, Some(hardfork)); assert!(config.networks.is_tempo()); }该测试同时验证了三件事clap 能正确解析--hardfork tempo:T5tempo:T5能通过FromStr解析为FoundryHardfork::Tempo(T5)EvmArgs作为 figmentProvider合并进Config后config.hardfork被正确设置且Tempo 网络被自动激活。八、解析链路小结从 CLI 输入到 EVM 执行--hardfork的完整数据流为参数解析clap 将--hardfork HARDFORK解析为EvmArgs.hardfork: OptionFoundryHardfork字符串按FromStr规则转枚举crates/cli/src/opts/evm.rs配置合并EvmArgs作为Provider与Config含foundry.toml合并CLI 值优先级最高evm.rs一致性校验normalize_hardfork_settings()校验与网络配置的冲突并自动激活对应命名空间网络crates/config/src/lib.rsSpec 解析Forge / Chisel 在构建执行环境时调用resolve_execution_spec(evm_version, hardfork, evm_env, context, ...)把FoundryHardfork转换为 revm 的SpecId并写入cfg_env.speccrates/evm/core/src/opts.rs执行与解码一致解析出的resolved_hardfork同时传给 trace 解码器.with_hardfork(...)保证执行语义与解码语义对齐。九、适用前提与限制网络硬分叉可用性取决于编译特性Optimism变体需要optimismfeatureMonad变体需要monadfeature见 crates/evm/hardforks/src/lib.rs未启用对应 feature 时相关命名空间无法解析历史 fork 场景以源链为准resolve_execution_spec的注释指出ExecutionSpecContext::fork场景下若 fork 端点上报了精确硬分叉fork_hardfork会优先采用端点硬分叉见 crates/evm/core/src/opts.rs 及resolve_execution_spec_prefers_exact_endpoint_hardfork测试此时本地--hardfork的覆盖能力受上下文约束命名空间格式必须规范网络专属硬分叉若遗漏前缀如直接写--hardfork T5将按 Ethereum 解析并报unknown ethereum hardfork T5。结语--hardfork共享参数的引入把 Forge 与 Chisel 的运行时硬分叉选择统一到了foundry-cli的EvmArgs层一套参数、一套解析语义、一套校验规则覆盖 Ethereum / Optimism / Tempo / Monad 四类网络。对开发者而言它提供了比evm_version更精确、比改foundry.toml更轻量的运行时语义控制手段对项目而言它消除了两条命令在硬分叉处理上的行为分叉为后续 trace 解码、fork 场景与多网络执行奠定了统一的硬分叉上下文基础。延伸阅读本文关联的变更记录见 .changelog/runtime-hardfork-cli-override.md共享 EVM 参数定义见 crates/cli/src/opts/evm.rs硬分叉枚举与解析见 crates/evm/hardforks/src/lib.rs配置字段与校验见 crates/config/src/lib.rs执行 spec 解析见 crates/evm/core/src/opts.rs。【免费下载链接】foundryFoundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.项目地址: https://gitcode.com/GitHub_Trending/fo/foundry创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考