news 2026/9/16 12:49:25

Foundry Cast Safe CLI 的确定性测试基座:解析 Safe v1.4.1 运行时字节码 fixtures

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Foundry Cast Safe CLI 的确定性测试基座:解析 Safe v1.4.1 运行时字节码 fixtures

Foundry Cast Safe CLI 的确定性测试基座:解析 Safe v1.4.1 运行时字节码 fixtures

【免费下载链接】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 safe命令端到端测试所准备的 Safe v1.4.1 运行时字节码 fixtures:这三个以“官方已部署代码”为蓝本 vendored 的二进制文件如何保证测试无需公网 RPC 或真实 Safe Transaction Service 即可确定性运行,其来源(provenance)、格式约定与双重校验机制(字节长度 + Keccak-256 哈希)在源码中的落点,以及cast safe create等命令是如何基于这套 fixtures 完成全生命周期验证的。

一、这批 fixtures 解决什么问题

Safe(原 Gnosis Safe)是多签智能账户,cast safe子命令负责在本地/远端链上创建并管理 Safe 实例。要对该命令做端到端(end-to-end)测试,测试环境必须满足一个苛刻条件:链上某组地址必须恰好部署着“官方 Safe v1.4.1 运行时字节码”,否则cast safe create之后对 Safe 实例的getOwners()getThreshold()nonce()等调用都无法真实执行。

正常情况下这依赖 fork 一条主网或接入公开的 Safe 服务,但这会让测试变得不稳定且不可离线复现。仓库给出的解法是:把官方部署的运行时字节码原样 vendor 进仓库,在本地 anvil 节点启动后用anvil_setCode把代码安装到其规范部署地址(canonical address)上。fixtures 目录说明 明确指出这样做使“测试保持确定性,不依赖公共 RPC 端点或在线的 Safe Transaction Service”。

当前 fixtures 目录共 3 个二进制文件与 1 个说明文档:

  • SafeL2.runtime.bin
  • SafeProxyFactory.runtime.bin
  • SimulateTxAccessor.runtime.bin
  • README.md

二、来源与授权:与官方部署逐字节对齐

这批 fixtures 对应 Safe Contracts v1.4.1 官方发布版本,取自 safe-smart-account 仓库 commitbf943f80fec5ac647159d26161446ac5d716a294;其规范部署地址与代码哈希则以 safe-deployments 仓库 v1.4.1 assets(commita1e93fb)为对照基准。上游 Safe 合约采用 GNU LGPL v3.0 许可证,这也解释了为什么 fixtures 目录保留了一份专门的 Provenance and license 说明。

README 中的来源对照表是理解这套基座的核心,完整保留如下:

FixtureDeployment asset规范部署地址运行时字节数Keccak-256 代码哈希
SafeL2.runtime.binsafe_l2.json0x29fcB43b46531BcA003ddC8FCB67FFE91900C76224,4210xb1f926978a0f44a2c0ec8fe822418ae969bd8c3f18d61e5103100339894f81ff
SafeProxyFactory.runtime.binsafe_proxy_factory.json0x4e1DCf7AD4e460CfD30791CCC4F9c8a4f820ec673,0540x50c3cdc4074750a7a974204a716c999edd37482f907608d960b2b025ee0b3317
SimulateTxAccessor.runtime.binsimulate_tx_accessor.json0x3d4BA2E0884aa488718476ca2FB8Efc291A461998500x91f82615581fc73b190b83d72e883608b25e392f72322035df1b13d51766cf8d

三个地址/长度/哈希在测试源码中被原样声明为常量,见 safe.rs#L35-L46:

const SAFE_L2_V1_4_1: Address = address!("29fcB43b46531BcA003ddC8FCB67FFE91900C762"); const SAFE_PROXY_FACTORY_V1_4_1: Address = address!("4e1DCf7AD4e460CfD30791CCC4F9c8a4f820ec67"); const SIMULATE_TX_ACCESSOR_V1_4_1: Address = address!("3d4BA2E0884aa488718476ca2FB8Efc291A46199"); const SAFE_L2_V1_4_1_RUNTIME_LEN: usize = 24_421; const SAFE_PROXY_FACTORY_V1_4_1_RUNTIME_LEN: usize = 3_054; const SIMULATE_TX_ACCESSOR_V1_4_1_RUNTIME_LEN: usize = 850; const SAFE_L2_V1_4_1_RUNTIME_HASH: B256 = b256!("b1f926978a0f44a2c0ec8fe822418ae969bd8c3f18d61e5103100339894f81ff");

对当前仓库文件的实测大小(24421 / 3054 / 850 字节)与 README 表格、源码常量三者完全一致,说明 fixtures 与其文档承诺逐字节吻合。

一个值得注意的细节是SimulateTxAccessor:它含有一个immutable self-address(编译期内嵌自身的部署地址)。fixtures 中该 immutable 字使用的是规范地址0x3d4BA2E0...而非本地占位地址,这正是其 Keccak-256 哈希能与已部署代码对齐的原因——如果直接拿编译产物替换地址,哈希校验必然失败。这提示任何想复用/替换 fixtures 的团队:immutable 自地址代码必须与目标部署地址绑定。

三、文件格式约定:是“运行时字节码”而非“创建字节码”

README 的 Format and verification 一节明确了格式边界:

  1. 文件为已部署的运行时字节(deployed runtime bytes),不含0x前缀、无换行,且不是合约创建字节码(creation bytecode)
  2. 测试通过include_bytes!在编译期把它们嵌入二进制;
  3. 安装前先校验字节长度Keccak-256 哈希双重指纹;
  4. 校验通过后用 anvil 的anvil_setCode方法把代码写入规范地址。

这里的“运行时字节码 vs 创建字节码”区分对 EVM 测试很关键:anvil_setCode写入的是运行时码,直接对应链上eth_getCode的返回值;若误用创建字节码(含构造器逻辑),部署后的代码哈希与主网部署就不一致,所有依赖“与官方部署相同代码”的断言都会失效。

四、源码级实现:从校验到注入的完整链路

fixtures 的消费方是 crates/cast/tests/cli/safe.rs(约 1880 行的集成测试文件),其核心流程可概括为三步:

1. 编译期嵌入 + 运行期双重校验

fixture_runtime(safe.rs#L126)接收include_bytes!得到的静态字节切片及“期望长度 + 期望哈希”两个常量,在测试运行时验证两者均匹配后才返回可用于anvil_setCodeBytes。这是典型的“fail fast”设计:一旦 fixtures 被误改(哪怕一个字节),测试会在校验阶段而非断言阶段暴露问题。

2. anvil 启动后立即安装三份代码

safe_v1_4_1_lifecycle_uses_stateful_service测试(safe.rs#L966-L999)为例:

let (api, handle) = anvil::spawn(NodeConfig::test()).await; let provider = handle.http_provider(); api.anvil_set_code( SAFE_L2_V1_4_1, fixture_runtime( include_bytes!("../fixtures/safe/v1.4.1/SafeL2.runtime.bin"), SAFE_L2_V1_4_1_RUNTIME_LEN, SAFE_L2_V1_4_1_RUNTIME_HASH, ), ) .await .unwrap(); // 同样方式安装 SafeProxyFactory 与 SimulateTxAccessor …

同一段测试还额外在目标地址写入一段最小 EVM 字节码(0x6000546001016000553360005260206000f3,即“对槽 0 加一并返回msg.sender”),用于区分模拟调用的一次执行与重复调用——这体现了 fixtures 不仅用于部署,还服务于对cast safe simulate一类行为的可观测断言。

3. 基于已安装代码执行cast safe create全生命周期

安装代码后,测试驱动真实的cast safe create命令行(safe.rs#L1012-L1044):

cast safe create <owner1> <owner2> --threshold 2 \ --singleton 0x29fcB43b46531BcA003ddC8FCB67FFE91900C762 \ --factory 0x4e1DCf7AD4e460CfD30791CCC4F9c8a4f820ec67 \ --fallback-handler 0x0000000000000000000000000000000000000000 \ --private-key 0x... --rpc-url <anvil endpoint>

测试随后解析 stdout 中打印的 Safe 地址,用alloy_sol_types::sol!声明的TestSafe接口(safe.rs#L51-L90,含nonce()getOwners()getThreshold()getTransactionHash(...)execTransaction(...)ExecutionSuccess事件)直接对链上 Safe 发起真实调用,断言getOwners()返回两个 owner、getThreshold()为 2、nonce()为 0,并调用getTransactionHash验证 Safe 交易哈希计算。此外,同一文件还覆盖--legacy(Type-0 交易)与显式--access-list参数对交易字段的实际影响(safe.rs#L925-L964)。

同一组 fixtures 在文件后段被第二个生命周期测试(约 L1761 起)复用,说明该基座被设计为多个独立测试用例共享的“一次性基础设施”,进一步印证了 vendored 方案相对 fork 方案的复用价值。

五、实践要点小结

  • 适用前提:这套 fixtures 绑定 Safe v1.4.1 这一具体版本;若测试目标换成 v1.3.x 或其他版本,地址、字节数与哈希需整体替换,不能混用。
  • 校验不可省略:长度校验能抓住截断,Keccak-256 校验能抓住任意位翻转;二者同时声明于 safe.rs#L38-L46,替换 fixtures 时必须同步更新这三组常量。
  • 不可用创建字节码顶替anvil_setCode语义要求运行时码;从源码结构看,整条断言链(getOwners/getThreshold/getTransactionHash均返回真实值)的前提就是链上代码与官方部署逐字节一致。
  • immutable 地址的陷阱SimulateTxAccessor类含自地址的合约,fixtures 必须采用规范地址编入 immutable,否则哈希与部署事实脱节。
  • 离线可复现:整套方案不依赖公共 RPC 与在线 Safe Transaction Service;服务侧交互由测试内基于 axum 的本地 mock HTTP 服务(spawn_safe_service,safe.rs#L109)承担,与 fixtures 共同构成cast safe命令的确定性测试闭环。

对维护者而言,这份文档与其三个.bin文件、crates/cast/tests/cli/safe.rs 构成一个自洽单元:文档负责声明“这些字节是谁、从哪来、怎么验”,源码负责执行“验过了才允许装进节点”,二者配合使 Safe 相关 CLI 行为测试在 CI 中无需任何外部依赖即可稳定运行。

【免费下载链接】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),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/16 12:47:34

AI与污点分析结合的自动化漏洞挖掘技术

1. 项目背景与核心思路去年在参与某大型金融系统安全审计时&#xff0c;我注意到一个现象&#xff1a;超过60%的中高危漏洞都源于未正确处理用户输入数据。传统人工审计需要逐个跟踪数据流&#xff0c;效率低下且容易遗漏。这促使我开始探索如何将污点分析技术与AI结合&#xf…

作者头像 李华
网站建设 2026/9/16 12:47:30

51单片机Proteus仿真霍尔无刷电机六步换相全解析

简介&#xff1a;面向51单片机学习者和无刷电机控制开发者&#xff0c;这套仿真资源演示了带霍尔传感器的三相无刷直流电机&#xff08;BLDC&#xff09;在Proteus中的完整驱动过程。资源围绕51单片机控制核心&#xff0c;涉及霍尔传感器位置检测、六步换相、PWM调速等关键知识…

作者头像 李华
网站建设 2026/9/16 12:44:15

Django学生成绩管理系统:ORM聚合与ECharts数据可视化实战

简介&#xff1a;一套基于Python与Django实现的学生成绩管理系统&#xff0c;涵盖首页、个人中心、教师管理、学生管理、公告信息、课程类型、课程信息、选课信息与成绩信息等核心模块&#xff0c;并融合数据可视化展示&#xff0c;适合课程设计、毕业设计或Django初学者参考学…

作者头像 李华
网站建设 2026/9/16 12:43:17

低温环境下微电网储能电池优化调度与Matlab实现

1. 项目背景与核心挑战在极寒地区或冬季低温环境下&#xff0c;微电网系统的储能电池性能会显著下降。这不仅仅是容量衰减的问题&#xff0c;更关键的是低温会导致电池内阻急剧增加、充放电效率降低&#xff0c;甚至引发不可逆的晶体结构损坏。我们团队在内蒙古-25℃的实地测试…

作者头像 李华