如何在Foundry Fork环境中检测与测试zkSync链?foundry-devops的vm.createSelectFork完整测试实践
2026/9/24 4:57:15 网站建设 项目流程

如何在Foundry Fork环境中检测与测试zkSync链?foundry-devops的vm.createSelectFork完整测试实践

【免费下载链接】foundry-devops项目地址: https://gitcode.com/gh_mirrors/fo/foundry-devops

想在 Foundry Fork 环境中同时测试以太坊主网和 zkSync 链?foundry-devops是一个面向 Foundry 开发者的运维工具库,核心能力有两个:自动读取broadcast目录获取合约最近一次部署地址,以及在 Fork 测试中智能检测"当前是否运行在 zkSync 链上"。本文将用一套完整实践,带你看懂vm.createSelectFork双 Fork 测试、ZkSyncChainChecker检测原理,以及foundry-zksync的特殊处理技巧。

🚀 快速上手:安装 foundry-devops

环境要求清单

工具验证命令预期输出示例
gitgit --versiongit version 2.x.x
foundryforge --versionforge 0.2.0 (…)
foundry-zksyncfoundryup-zksync --help显示安装器帮助信息
jqjq --versionjq-1.6

克隆仓库并安装依赖

git clone https://gitcode.com/gh_mirrors/fo/foundry-devops cd foundry-devops make

make会依次执行清理、安装依赖、更新和构建,对应命令都定义在 makefile 中。

🔍 核心机制:ZkSyncChainChecker 如何识别 zkSync 链

项目的核心检测逻辑在src/ZkSyncChainChecker.sol中,它提供了两条互补的判断路径

  • 路径一:chainId 判断——isOnZkSyncChainId()检查block.chainid是否为 324(主网)、300(Sepolia 测试网)或 260(In-Memory 节点)。在 Fork 环境中这是最快的方式。
  • 路径二:预编译合约探测——isOnZkSyncPrecompiles()通过调用 zkSync 不支持的预编译合约(0x030x040x050x08)来反推:如果调用失败,说明当前就运行在 zkSync 上。

两个判断被isZkSyncChain()串联,并暴露了两个非常好用的修饰器:

  • skipZkSync:在 zkSync 链上自动跳过该测试函数
  • onlyZkSync:只允许在 zkSync 链上执行

🧪 完整实践:用 vm.createSelectFork 构建双 Fork 测试

第一步:配置 RPC 端点

Fork 测试需要本地配置文件foundry.toml中声明两条链的 RPC,本项目已配置好(见 foundry.toml):

[rpc_endpoints] mainnet = "${MAINNET_RPC_URL}" zksync = "${ZKSYNC_RPC_URL}"

只需在环境变量中设置MAINNET_RPC_URLZKSYNC_RPC_URL即可。

第二步:在 setUp 中创建并切换 Fork

参考test/ZkSyncChainCheckerTest.t.sol的写法,测试骨架长这样:

function setUp() public { vm.createSelectFork("mainnet"); // 创建以太坊主网 Fork mainnetForkId = vm.activeFork(); vm.createSelectFork("zksync"); // 创建 zkSync Fork zkSyncForkId = vm.activeFork(); }

关键技巧:vm.createSelectFork返回后,必须立刻用vm.activeFork()记录 Fork ID,之后再用vm.selectFork(id)在任意测试函数中随时切换上下文。例如:

function testIsOnZkSyncChainByChainId_zksync() public { vm.selectFork(zkSyncForkId); assertEq(checker.isOnZkSyncChainId(), true); // zkSync Fork 上为 true }

配合ZkSyncChainCheckerskipZkSync/onlyZkSync修饰器,同一份测试代码就能在两条链上跑出不同的预期结果,真正做到"一次编写、双链验证"。

第三步:区分 foundry 与 foundry-zksync 运行器

这里有一个新手最容易踩的坑:foundry-zksync编译为 EraVM 后无法识别部分 cheatcodes,不支持vm.selectFork。因此项目采用了分离策略(见test/ZkSyncChainCheckerLocalTest.t.sol):

  • ZkSyncChainCheckerTest.t.sol:仅在原版 foundry 下运行,负责vm.createSelectFork双 Fork 切换测试
  • ZkSyncChainCheckerLocalTest.t.sol:在foundry-zksync下直接跑本地节点,验证预编译合约探测

为了自动识别"当前是哪种 Foundry",src/FoundryZkSyncChecker.sol通过vm.ffi执行forge --version命令并比对版本前缀:原版 foundry 报0.2.x/0.3.x,而foundry-zksync0.0.2。由此提供onlyFoundryZkSynconlyVanillaFoundry两个修饰器,让不同运行器只执行各自的测试。注意使用 FFI 需要在foundry.toml中开启ffi = true(本项目已开启)。

⚡ 运行测试:两条命令搞定

项目通过 makefile 提供了开箱即用的入口:

make test # 原版 foundry 下运行全部测试 make test-zksync # 切换到 foundry-zksync 运行 --zksync 模式测试

其中 zkSync 模式的实现是foundryup-zksync && forge test --zksync && foundryup(见 makefile),执行完会自动切回原版 foundry,无需手动操作。

📌 注意事项与已知限制

  • 不能部署带检查器的合约foundry-zksync对 cheatcodes 兼容性有限,编译到 EraVM 后无法识别,因此含ZkSyncChainChecker的合约不适合在 zkSync 模式下部署(详见 README.md 的 Limitations 部分)。
  • 预编译探测是"临时方案":如果未来 zkSync 支持了相关预编译合约,该检测路径可能失效,代码注释中已明确提醒。
  • RPC 必须可达vm.createSelectFork需要真实 RPC,建议在测试前先用cast chain-id --rpc-url $ZKSYNC_RPC_URL验证连通性。
  • 广播权限foundry.toml中已为./broadcast目录配置了fs_permissions读取权限,用于最近部署地址查询功能,Fork 测试中若需读取本地文件同样受益于此配置。

小结

foundry-devops用三个抽象合约+一套 make 命令,把"多链 Fork 测试"这件繁琐的事变得简单:ZkSyncChainChecker负责链上环境识别,FoundryZkSyncChecker负责运行器识别,vm.createSelectFork+vm.selectFork组合则实现了测试中自由穿梭主网与 zkSync 的上下文切换。掌握这套模式后,你也可以将它迁移到自己的多链项目中,快速搭建跨链兼容性测试体系。

【免费下载链接】foundry-devops项目地址: https://gitcode.com/gh_mirrors/fo/foundry-devops

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询