Foundry:Solidity 智能合约本地开发、测试与部署指南

前言
最近在使用Foundry开发智能合约,发现它相较于传统的Hardhat或Truffle工具链确实有明显的优势。Foundry是由Paradigm团队开发的Ethereum智能合约开发工具包,基于Rust构建,包括四个核心组件:forge(编译、测试与部署)、cast(链上交互)、anvil(本地节点模拟)和chisel(Solidity REPL)。特别值得一提的是,它支持原生Solidity测试,无需JavaScript,同时还有模糊测试(fuzzing)支持,性能也相当出色。
最近正好在研究Foundry v0.2.0+版本(Rust 1.80+),结合官方文档和社区实践,总结了以下本地开发、测试与部署的完整流程,分享给大家。
1. 安装与项目初始化
1.1 安装 Foundry
安装Foundry非常简单,使用官方的foundryup脚本即可:
1# 安装 foundryup
2curl -L https://github.com/foundry-rs/foundry/releases/latest/download/foundryup-installer.sh | bash
3
4# 安装 Foundry 工具链(forge, cast, anvil, chisel)
5foundryup
6
7# 验证安装
8foundry --version # 输出类似: forge 0.2.0 (abc1234 2025-11-01)
9anvil --version
10cast --version
个人建议:
- 在项目中使用
foundry.toml配置来锁定版本,避免更新带来的兼容性问题。 - CI/CD中可以使用
foundryup -i来确保环境一致性。
1.2 创建新项目
Foundry项目结构非常简洁,主要包含:src/(合约源代码)、test/(测试)、script/(部署脚本)、lib/(依赖):
1# 初始化新项目
2forge init my-project
3cd my-project
4
5# 项目结构
6ls
7# 输出: foundry.toml lib/ script/ src/ test/
src/Counter.sol:默认示例合约(简单计数器)test/Counter.t.sol:默认测试文件(.t.sol后缀表示测试)foundry.toml:配置文件(可自定义 Solidity 版本、优化器等)
示例配置文件(foundry.toml):
1[profile.default]
2src = "src"
3out = "out"
4libs = ["lib"]
5solc_version = "0.8.27"
6optimizer = true
7optimizer_runs = 200
8via_ir = true # 启用 Intermediate Representation 优化(提高 Gas 效率)
1.3 本地开发工作流
编写合约:在
src/下创建Solidity文件。Foundry支持OpenZeppelin等库,通过Git子模块管理依赖(无需npm)。举个例子:扩展
Counter.sol为ERC20代币(src/MyToken.sol):1// SPDX-License-Identifier: MIT 2pragma solidity ^0.8.27; 3 4import "forge-std/console.sol"; // Foundry 内置日志库 5 6contract MyToken { 7 string public name = "MyToken"; 8 mapping(address => uint256) public balanceOf; 9 10 function mint(address to, uint256 amount) external { 11 balanceOf[to] += amount; 12 console.log("Minted %d tokens to %s", amount, to); // 调试日志 13 } 14}安装依赖:
1# 添加 OpenZeppelin(Git 子模块) 2forge install OpenZeppelin/openzeppelin-contracts@v5.0.0 3 4# 更新 remappings(自动生成 .solc-remappings.json) 5forge remappings > remappings.txt编译合约:
1forge build # 编译 src/ 下所有 .sol 文件,输出到 out/ 2# 或指定优化 3forge build --optimize --optimize-runs 1000000
调试小技巧:
- 使用
chisel进行交互式测试:1chisel # 启动 REPL,输入 Solidity 代码实时执行 2> uint256 x = 42; console.log(x); # 输出: 42 - 使用
forge build --gas-report生成Gas使用报告。
2. 测试智能合约
Foundry 的测试框架(Forge)允许用 Solidity 编写测试,支持模糊测试(fuzzing)、作弊码(cheatcodes,如 vm.prank 模拟调用者)和断言(assertEq)。测试文件置于 test/,继承 Test.sol。
2.1 编写测试
示例:为 MyToken 编写全面测试(test/MyToken.t.sol):
1// SPDX-License-Identifier: UNLICENSED
2pragma solidity ^0.8.27;
3
4import "forge-std/Test.sol";
5import "../src/MyToken.sol";
6
7contract MyTokenTest is Test {
8 MyToken token;
9 address user = makeAddr("user"); // 生成测试地址
10
11 function setUp() public {
12 token = new MyToken();
13 deal(address(token), 1000 ether); // 作弊码:注入 ETH(模拟余额)
14 }
15
16 // 基本断言测试
17 function testName() public {
18 assertEq(token.name(), "MyToken");
19 }
20
21 // 集成测试:铸币与余额检查
22 function testMint() public {
23 vm.prank(user); // 作弊码:模拟 user 调用
24 token.mint(user, 100);
25
26 assertEq(token.balanceOf(user), 100);
27 }
28
29 // 模糊测试:随机输入验证(fuzzing,覆盖边缘案例)
30 function testMintFuzz(uint256 amount) public {
31 vm.assume(amount > 0 && amount < type(uint256).max / 2); // 假设边界
32 vm.prank(user);
33 token.mint(user, amount);
34 assertEq(token.balanceOf(user), amount);
35 }
36
37 // 失败案例测试(expectRevert)
38 function testMintFail() public {
39 vm.expectRevert(); // 预期回滚
40 vm.prank(address(0)); // 零地址调用(假设无权限)
41 token.mint(user, 100);
42 }
43}
关键概念:
- setUp():每个测试前执行(类似于Mocha的beforeEach)
- 作弊码(Cheatcodes):
vm实例提供EVM操纵,如vm.prank(伪造msg.sender)、vm.deal(注入余额)、vm.warp(时间戳跳跃) - 模糊测试:
testMintFuzz(uint256 amount)自动生成数千随机输入,检测溢出/边界问题
2.2 运行测试
1# 运行所有测试
2forge test
3
4# 详细输出 + Gas 报告
5forge test -vvv --gas-report
6
7# 运行特定测试
8forge test --match-test testMint
9
10# 模糊测试(增加迭代次数)
11forge test --fuzz-runs 10000
12
13# 覆盖率报告
14forge coverage --report lcov # 生成 LCOV 报告,可集成 SonarQube
输出示例(成功测试):
[PASS] testMint() (gas: 25000)
[FAIL] testMintFail() (gas: 15000) # 预期失败
Coverage: 95.2% lines, 88.5% branches
个人经验:
- 测试覆盖率尽量保持在90%以上(使用
forge coverage) - 每个
test*函数保持独立,互不影响 - 重点关注边界情况:零值、最大值、重入(reentrancy)
3. 部署智能合约
部署主要通过Forge的脚本系统(script/下的Solidity脚本)来完成,也支持CLI方式。支持本地(Anvil)、测试网(Sepolia)和主网部署。
3.1 启动本地节点(Anvil)
Anvil是Foundry的本地EVM模拟器,提供10个预资助账户(每个10000 ETH):
1# 启动 Anvil(默认 RPC: http://127.0.0.1:8545)
2anvil
3
4# 输出: Accounts (10): 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 (10000 ETH)
5# Listener: http://127.0.0.1:8545
- Fork 模式:可以模拟真实网络(如Sepolia fork):
1anvil --fork-url https://rpc.sepolia.org --fork-block-number 5000000
3.2 编写部署脚本
在script/Deploy.s.sol中:
1// SPDX-License-Identifier: MIT
2pragma solidity ^0.8.27;
3
4import "forge-std/Script.sol";
5import "../src/MyToken.sol";
6
7contract DeployToken is Script {
8 function run() external {
9 uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY"); // 从环境变量加载
10 vm.startBroadcast(deployerPrivateKey);
11
12 MyToken token = new MyToken();
13 console.log("Deployed at: %s", address(token));
14
15 vm.stopBroadcast();
16 }
17}
3.3 执行部署
1# 设置环境变量
2export PRIVATE_KEY=your_private_key_here # 测试网私钥(勿用主网)
3
4# 本地部署(Anvil)
5forge script script/Deploy.s.sol --rpc-url http://127.0.0.1:8545 --broadcast
6
7# 测试网部署(Sepolia)
8forge script script/Deploy.s.sol --rpc-url https://rpc.sepolia.org --broadcast --verify # --verify 自动验证 Etherscan
9
10# 输出示例
11[⠒] Compiling...
12[⠔] Broadcasting...
13Transaction successful: 0xabc123... (Block Confirmation: 1)
14Deployed at: 0x1234567890abcdef...
链上交互(Cast): 部署后,使用 Cast 调用合约:
1# 调用 mint 函数
2cast send 0x1234567890abcdef "mint(address,uint256)" 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 "100" --private-key $PRIVATE_KEY --rpc-url http://127.0.0.1:8545
3
4# 查询余额
5cast call 0x1234567890abcdef "balanceOf(address)(uint256)" 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 --rpc-url http://127.0.0.1:8545
6# 输出: 100
3.4 多链与升级部署
- 配置多链:在
foundry.toml添加[etherscan]部分,支持自动验证 - 代理升级:集成OpenZeppelin Upgrades插件(
forge install OpenZeppelin/openzeppelin-upgrades-flattener)
个人经验:
- 使用
--slow标志运行完整测试套件(包括Gas基准测试) - CI/CD中使用GitHub Actions(测试+部署到测试网)
- 安全方面:私钥通过环境变量或
DOTENV加载;生产前运行slither .静态分析
最后
最近使用Foundry开发了一些项目,确实感觉比传统的Hardhat工具链效率更高。特别是原生Solidity测试和作弊码功能很大程度上简化了开发流程,模糊测试也提供了更全面的测试覆盖。
进一步阅读:
- 官方手册:https://book.getfoundry.sh/
- 示例项目:ethereum-blockchain-developer.com 的 ERC721 教程
- 高级测试:Metana 的 Foundry 测试指南
- 社区:Foundry Discord / GitHub (foundry-rs/foundry)
