ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Foundry `cast run` 任意网络交易回放:基于 AnyNetwork 解码 Arbitrum、Celo 与 OP-stack 分叉区块

2026/9/15 23:35:15 拓冰建站 浏览量
Foundry `cast run` 任意网络交易回放:基于 AnyNetwork 解码 Arbitrum、Celo 与 OP-stack 分叉区块 Foundrycast run任意网络交易回放基于 AnyNetwork 解码 Arbitrum、Celo 与 OP-stack 分叉区块【免费下载链接】foundryFoundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.项目地址: https://gitcode.com/GitHub_Trending/fo/foundry本篇技术指南聚焦 Foundry 对cast run的一次关键能力增强使用AnyNetwork解码区块使承载非标准交易类型的链如 Arbitrum、Celo 以及未被路由到专门网络的 OP-stack 分叉上的历史交易可以被完整回放。读完本文你将理解cast run的整条回放流水线目标交易获取 → 区块准备 → 前缀交易重放 → 目标执行 → 跟踪输出、AnyNetwork在其中扮演的角色、Celo CIP-64 与 OP 存款交易等非标准信封的转换机制以及配套的 CLI 参数与测试保障可直接用于对任意 EVM 兼容链上的交易进行本地重放与调试。变更背景为什么任意网络回放是一道坎cast run是 Foundry 中用于在本地重新执行链上某笔历史交易的命令它从 RPC 拉取目标交易及其所在区块fork 出父区块状态逐笔重放该区块中目标交易之前的所有交易最后用目标交易自身驱动 EVM 并输出调用树或操作码级跟踪。cast run的存在使开发者不必依赖节点调试命名空间就能复现一笔交易的确切执行路径、Gas 消耗与状态变更。然而在本次变更之前cast run对区块的拉取与解码使用严格的以太坊交易信封envelope类型。以太坊主网的标准信封只覆盖 legacy、EIP-2930、EIP-1559、EIP-4844blob等类型而 Arbitrum 区块中包含 Arbitrum 特定的AnyTx信封、Celo 使用 CIP-64 动态费用交易、部分 OP-stack 分叉Foundry 未内置专门路由的网络同样携带自定义交易类型。一旦区块里混入这类信封整个区块的拉取与解码就会失败导致这些链上的交易完全无法用cast run回放。本仓库 crates/cast/src/cmd/run.rs 中对fetch_target的源码注释精确描述了这一点AnyNetworkrather thanFEN::Network: chains such as Arbitrum, Celo and the OP-stack forks Foundry does not route to a dedicated network put transaction types the strict Ethereum envelope cannot decode into every block, which would fail the full block fetch inpreparefor the whole chain.即任何一条链只要有一个区块含有严格以太坊信封无法解码的交易类型整链的区块拉取就会失败。本次变更见 .changelog/cast-run-any-network.md正是让cast run改用AnyNetwork解码区块从根上解除这一限制同时保留执行阶段对具体 EVM 网络的区分详见下文执行仍走专用 EVM。核心机制fetch_target 与 ProviderBuilder::cast run的第一步是解析目标交易对应源码中的RunArgs::fetch_targetlet provider ProviderBuilder::AnyNetwork::from_config(config)? .compute_units_per_second_opt(compute_units_per_second) .build()?; let tx provider .get_transaction_by_hash(tx_hash) .await .wrap_err_with(|| format!(tx not found: {tx_hash:?}))? .ok_or_else(|| eyre::eyre!(tx not found: {tx_hash:?}))?;关键点有三Provider 以AnyNetwork为类型参数构建。AnyNetwork是 Alloy 提供的任意网络抽象它可以承载任何AnyRpcTransaction/AnyTxEnvelope无论该信封是标准的还是自定义的。因此get_transaction_by_hash返回的是AnyRpcTransaction交易类型本身不再成为解码瓶颈。RPC 地址来自配置解析。ProviderBuilder::from_config依据 Foundry 配置foundry.toml中的eth_rpc_url、rpc_endpoints或命令行--rpc-url构建 providercompute_units_per_second用于 RPC 速率控制若传入--no-rpc-rate-limit则设为u64::MAX关闭限流。目标交易先于区块拉取被解析。fetch_target在prepare之前完成一旦信封无法解码会快速失败fail fast而不是等到拉完整个区块的前缀交易后才报错——这一点在 Monad 与普通路径的实现注释中都有明确说明。值得注意fetch_target返回的TargetFetch结构中除了交易与 provider还携带compute_units_per_second供 Monad 专用路径复用同一个 provider 构造逻辑。完整回放流水线从 fetch 到 tracecast run的执行入口是RunArgs::run其整体流程如下解析 CLI 参数与 figment 配置 → 合并 RpcOpts / RunArgs 到 Config → 若 --chain 指定了别名且 foundry.toml 中存在对应 rpc_endpoints则回退使用该端点 → evm_opts.fork_url config.get_rpc_url_or_localhost_http() → evm_opts.infer_network_from_fork() // 未显式配置网络时从 fork chain ID 自动推断 → 根据网络分派到 TempoEvmNetwork / MonadEvmNetwork / OpEvmNetwork / EthEvmNetwork → run_with_evm fetch_target (AnyNetwork 拉取目标交易) → 系统交易检查 → preparefork 父区块、配置 EVM 环境 → execute_ordinary重放前缀交易 执行目标交易 → finish输出/渲染 trace其中最关键的两步RunArgs::prepare设置config.fork_block_number Some(tx_block_number - 1)即从目标交易的父区块 fork并行拉取目标区块provider.get_block(tx_block_number).full()与构建 fork 状态TracingExecutor::FEN::get_fork随后用block_env_from_header将区块头字段number、timestamp、basefee、prevrandao、blob 字段等灌入 EVM 的BlockEnv。PreparedRun::execute_ordinary调用TxEnvFor::FEN::from_any_rpc_transaction(self.tx)将AnyRpcTransaction转换为目标 EVM 网络的TxEnv再通过for_each_prefix_transaction逐笔重放目标交易之前的交易最终以executor.transact_with_ordinary_block_replay一次性执行。执行仍走专用 EVMAnyNetwork只负责看得懂任何信封真正执行时的网络类型由FEN: FoundryEvmNetwork决定——run入口按evm_opts.networks分派到TempoEvmNetwork、MonadEvmNetworkfeaturemonad、OpEvmNetworkfeatureoptimism或默认的EthEvmNetwork。这样既解除了区块解码的硬限制又不牺牲各网络特有的执行语义。非标准交易类型的转换FromAnyRpcTransaction交易信封从 RPC 对象转换为 EVM 可执行TxEnv的桥梁是FromAnyRpcTransactiontrait位于 crates/evm/core/src/env.rs。该文件同时引用use foundry_evm_networks::celo::CELO_DYNAMIC_FEE_TX_TYPE; // ... #[cfg(feature optimism)] use op_revm::transaction::deposit::DEPOSIT_TRANSACTION_TYPE;这印证了非标准交易类型支持的两个具体方向Celo CIP-64 动态费用交易Celo 采用 CIP-64 定义自己的动态费用交易类型。关联变更 .changelog/celo-dynamic-fee-replay.md 明确记录Allowed Celo CIP-64 transactions to be converted for local EVM replay——from_any_rpc_transaction能识别CELO_DYNAMIC_FEE_TX_TYPE并将其转换为本地回放可用的交易环境包括链特定的费用参数处理见apply_chain_specific_tx_replay_env_changes_for_chain。OP-stack 存款交易deposit在optimismfeature 下DEPOSIT_TRANSACTION_TYPE被引入供 OP 系网络处理存款交易信封对于 Foundry 未内置专门网络的 OP-stack 分叉AnyNetwork保证其自定义信封能被拉取与解码不阻塞整区块获取。此外RunArgs::prepare_target中还有一个针对伪造签名者的细节当交易信封无法恢复出与tx.from()一致的签名者AnyTxEnvelope::Unknown(_)一律视为伪造时会设置disable_balance_check true避免因本地无法验证签名而拒绝执行保证未知信封交易也能完成回放。链特定环境修正让回放结果贴近链上事实回放不仅仅是能跑还要尽量还原链上真实执行环境。cast run在prepare阶段做了一系列链特定修正自动禁用区块 Gas 上限检查fork.evm_env.cfg_env.disable_block_gas_limit true。注释给出的理由是——已上链的交易必然通过了其所属链自己的检查而部分链如 BSC 的验证者交易Gas 上限可达i64::MAX本地重施加检查只会误杀链上已接受的交易。OsakaEIP-7825交易 Gas 上限默认关闭tx_gas_limit_cap默认设为u64::MAX用户可通过--enable-tx-gas-limit显式开启。不限制合约代码大小limit_contract_code_size None。beacon block root 的按网处理parent_beacon_block_root_for_network对 Monad、CANCUN 之前的 spec 一律不施加 beacon root特别地Polygon、Scroll 等运行 Cancun 及以上 EVM 但没有以太坊 beacon 链的网络从不填充该头字段、也不部署 EIP-4788 合约若强行要求 root 会让这些链的区块变得不可回放对应测试用例见 crates/cast/src/cmd/run.rs。网络环境修正注入apply_chain_and_block_specific_env_changes_for_chain::AnyNetwork, _, _与apply_chain_specific_tx_replay_env_changes_for_chain按 chain id 修正区块与交易环境如 Celo 动态费用、各链 blob 参数等。hardfork 推断未显式指定--evm-version且配置未锁 hardfork 时按 reth 的方式沿链激活条件推断 spec对未知链则回退到 blob-gas 启发式excess_blob_gas存在则按 Cancun 处理。这些细节解释了为什么cast run在 Arbitrum、Celo、BSC、Polygon、Scroll 等非标准链上也能得到与链上事实一致的本地回放结果。CLI 参数全览与实战用法cast run的参数定义在RunArgs完整清单如下参数说明TX_HASH目标交易哈希位置参数--debug/-d在调试器中打开该交易--trace-printer/-t打印操作码级 trace--quick/-q仅使用上一区块状态执行跳过前缀交易重放结果可能与链上实际不同--replay-system-txes/--sys是否重放系统交易默认跳过--prestate-tracer用debug_traceTransaction拉取 prestate 代替整区块重放更快但要求节点暴露debug_命名空间失败时静默回退到区块重放--debug-trace-transaction直接从节点取 callTracer 调用树渲染跳过本地重放与--debug、--decode-internal、--trace-printer、--quick、--prestate-tracer、--evm-version互斥--evm-version覆盖配置中的 EVM 版本--with-local-artifacts/--la使用当前项目 artifacts 辅助 trace 解码--disable-block-gas-limit禁用区块 Gas 上限检查对已上链交易始终隐含--enable-tx-gas-limit开启 EIP-7825 交易 Gas 上限检查--label/-l地址标签ADDRESS:LABEL--rpc-url指定 RPC 端点未指定时由--chain在foundry.toml的rpc_endpoints中解析见 .changelog/cast-run-chain-rpc-endpoint.md基础用法cast run的帮助文案见 crates/cast/src/opts.rs# 常规回放一笔交易重放其所在区块中该交易之前的所有交易 cast run 0xtx_hash --rpc-url https://rpc.arbitrum.io # 只使用上一区块状态快速执行不做前缀重放 cast run 0xtx_hash --quick # 在调试器中打开交易 cast run 0xtx_hash --debug # 使用 foundry.toml 中为 arbitrum 配置的 RPC 端点 cast run 0xtx_hash --chain arbitrum对 Arbitrum、Celo 等链--chain与--rpc-url二选一即可未显式给 RPC URL 时--chain会查找foundry.toml中[rpc_endpoints]对应别名cast run的run入口中即存在config.rpc_endpoints.contains_key(alias)的逻辑。系统交易与端点一致性保障回放路径对系统交易有专门防护is_system_transactioncrates/cast/src/cmd/run.rs依据is_known_system_sender(tx.from())或交易类型等于SYSTEM_TRANSACTION_TYPE判定若目标是系统交易且未加--replay-system-txes命令直接报错退出避免给出误导性的回放结果。前缀交易中的系统交易默认也被跳过。--debug-trace-transaction远程路径remote_trace还实现了交易包含性一致性校验交易哈希、receipt、按哈希取区块、按编号取规范区块四处比对BlockNumHash一旦节点在收集 trace 期间发生了重组织inclusion 变化立即报错提示重试防止把不完整/不一致的远程 trace 当作事实输出。配套工程化改进与测试保障本次AnyNetwork改造并非孤立变更仓库中有一组配套变更共同支撑任意网络可回放这一目标.changelog/cast-run-network-e2e-tests.md新增跨公共网络的cast run端到端回放覆盖归入 nightly flaky 测试 profile对 Arbitrum、Celo 等公共链上的真实交易做持续验证。.changelog/cast-run-single-evm-replay.md回放区块时复用同一个 EVM 实例避免为每笔前缀交易重建执行器带来的性能与状态一致性问题。.changelog/cast-run-chain-rpc-endpoint.md--chain在未显式给 RPC URL 时使用foundry.toml中匹配的端点让多链回放更顺手。.changelog/celo-dynamic-fee-replay.mdCelo CIP-64 交易可转换为本地回放格式同时覆盖cast与forge。结合 crates/cast/src/cmd/run.rs 内置的单测legacy-l别名解析、--debug-trace-transaction与渲染参数的兼容性、beacon root 按网判定、远程路径忽略内部解码配置cast run的任意网络回放能力在单元与端到端两个层面都有验证支撑。小结本次变更让cast run完成了从以太坊专用回放器到任意网络回放器的跨越用AnyNetwork负责区块与交易信封的宽容解码用FoundryEvmNetwork分派具体执行语义辅以链特定环境修正beacon root、Gas 上限、Celo 动态费用、OP 存款交易与系统交易防护最终使 Arbitrum、Celo 及未内置路由的 OP-stack 分叉链上的历史交易都可以在本地被忠实地重新执行与调试。对于需要在非主流链上复现链上行为的开发者cast run如今是一条开箱即用的路径。【免费下载链接】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),仅供参考