如何让Foundry脚本与已部署合约交互?foundry-devops部署-交互全流程完整演示
【免费下载链接】foundry-devops 项目地址: https://gitcode.com/gh_mirrors/fo/foundry-devops
foundry-devops 是一个面向 Foundry 开发者的高效 DevOps 工具库,专门解决「合约部署后地址难追踪」的痛点:它能自动解析 broadcast 文件夹中的部署记录,一键拿到任意合约在指定链上的最新部署地址,让 Foundry 脚本轻松与已部署合约交互。本文用本地链完整演示「部署 → 查询 → 交互」全流程,新手 5 步即可跑通。
为什么Foundry新手总是卡在「找不到已部署合约地址」
写 Foundry 脚本时,最常见的卡点之一是:
- 合约 A 已经用
forge script --broadcast部署上链; - 现在要写第二个脚本调用合约 A,却不知道它的地址;
- 手动从终端输出里复制地址?容易复制错、版本混乱,多环境(测试网/主网)时更是灾难。
foundry-devops 的思路非常巧妙:Foundry 每次广播部署都会把完整记录写入 broadcast 目录。既然地址就躺在这些 JSON 文件里,那直接在 Solidity 脚本里读取它们就行了——无需硬编码地址,天然支持多链、多次部署,永远取最新一次。
它还提供附带能力:判断当前是否在 zkSync 系链上运行(src/ZkSyncChainChecker.sol、src/FoundryZkSyncChecker.sol),方便脚本做链环境适配。
一键安装 foundry-devops:快速准备环境
前置依赖:git、Foundry(forge --version 可正常输出)、jq。
克隆仓库:
git clone https://gitcode.com/gh_mirrors/fo/foundry-devops
cd foundry-devops
make
💡 项目的 makefile 已封装好
install、build、deploy、interact、test等命令,本文演示全程只需敲 make 命令,零记忆成本。
全流程演示:部署→查询→交互,本地链5步跑通
第一步:启动本地 Anvil 测试链
make anvil
对应命令为 anvil -m 'test test ... junk' --steps-tracing --block-time 1,一个确定性助记词 + 1 秒出块,非常适合调试部署流程。
第二步:用 forge script 广播部署合约
script/DeployStuff.s.sol 定义了一个极简合约 Stuff(返回 7),以及部署脚本 DeployStuff,核心就三行:vm.startBroadcast(); new Stuff(); vm.stopBroadcast();
执行广播:
make deploy
实际展开为:
forge script script/DeployStuff.s.sol:DeployStuff --broadcast --rpc-url http://localhost:8545 --private-key <ANVIL_KEY> -vvvv
执行成功后,Foundry 会自动把本次部署记录写入 broadcast 目录。
第三步:认识 broadcast 部署记录文件
部署后目录结构如下(链 ID 即子目录名,本地 Anvil 为 31337):
broadcast/
└── DeployStuff.s.sol/
└── 31337/
├── run-1700448371.json # 每次广播一个 run 文件
└── run-latest.json # 指向最新一次部署
以 broadcast/DeployStuff.s.sol/31337/run-latest.json 为例,关键字段:
{
"transactions": [
{
"contractName": "Stuff",
"contractAddress": "0x5FbDB2315678afecb367f032d93F642f64180aa3"
}
],
"timestamp": 1700448371,
"chain": 31337
}
foundry-devops 要做的,就是遍历这些文件,按 timestamp 比较后返回最新一次该合约名的 contractAddress。
第四步:让脚本与已部署合约交互
script/InteractWithStuff.s.sol 就是「交互脚本」的标准写法:
function run() external view {
address mostRecent = DevOpsTools.get_most_recent_deployment("DeployStuff", block.chainid);
uint256 value = Stuff(mostRecent).getSeven();
assert(value == 7);
}
它先通过 src/DevOpsTools.sol 查出最新部署地址,再把地址转成 Stuff 类型调用 getSeven() 并断言结果为 7——脚本间协作,全程无需人工复制地址。
运行:
make interact
第五步:运行测试验证全流程
test/DevOpsToolsTest.t.sol 覆盖了多种真实场景:
- 只部署一次,正确取回地址;
- 同一合约部署多次,正确取最新地址;
- 该链从未有过部署记录 → 回滚
No deployment artifacts were found for specified chain; - 合约名不存在 → 回滚
No contract named 'xxx' has been deployed on chain xxx; - 兼容新版(无
rpc字段)广播文件格式。
make test
进阶:一行代码查询任意链上的最新部署地址
在自己的项目中使用 foundry-devops,只需两步:
- 在
foundry.toml中授予脚本读取broadcast目录的权限(本项目配置见 foundry.toml):
fs_permissions = [
{ access = "read", path = "./broadcast" },
{ access = "read", path = "./reports" },
]
- 调用核心 API,第二个参数传链 ID 即可切换环境:
import {DevOpsTools} from "lib/foundry-devops/src/DevOpsTools.sol";
address addr = DevOpsTools.get_most_recent_deployment("MyContract", block.chainid);
⚠️ 细节提示:该库会自动跳过
dry-run文件,且同时兼容旧版与新版 broadcast JSON 格式(见 src/DevOpsTools.sol 中的两次目录遍历逻辑),升级 Foundry 版本后依然可用。
常见问题快速排查(FAQ)
| 现象 | 原因 | 解决办法 |
|---|---|---|
报 No deployment artifacts were found for specified chain | 指定链 ID 下没有广播记录 | 先执行部署脚本,或检查 block.chainid 是否传错 |
报 No contract named 'xxx' | 合约名与 contractName 不匹配 | 名称要填合约名(如 Stuff),不是脚本合约名 |
| 读文件被拒绝 | 未配置文件系统权限 | 按上文添加 fs_permissions |
| 多链部署后地址拿错 | 传了错误的 chainId | broadcast 按链 ID 分目录,确认目标链 |
项目目录结构速览
- src/DevOpsTools.sol —— 核心:解析 broadcast 取最新部署地址
- src/StringUtils.sol —— 字符串工具(路径归一化等)
- src/ZkSyncChainChecker.sol —— 基于预编译/chainid 判断 zkSync 链
- src/FoundryZkSyncChecker.sol —— 判断是否运行在 foundry-zksync
- script/ —— 部署与交互示例脚本
- broadcast/ —— 部署记录产物
- test/ —— 单元测试,覆盖多种部署场景
一句话总结:把部署地址管理交给 broadcast 文件夹,把查询工作交给 foundry-devops,你的 Foundry 部署-交互脚本从此告别硬编码地址 🚀
【免费下载链接】foundry-devops 项目地址: https://gitcode.com/gh_mirrors/fo/foundry-devops
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



