Foundry智能合约开发框架Skill foundry-framework

Foundry 是一个用于以太坊智能合约开发的极速、模块化工具包。本技能涵盖其核心组件 Forge(测试与构建)、Cast(链上交互)、Anvil(本地节点)和 Chisel(REPL调试),提供完整的智能合约开发、测试(包括模糊测试和不变性测试)、Gas优化、本地部署和脚本化部署能力。关键词:Foundry,智能合约开发,以太坊,Solidity测试,模糊测试,Gas报告,区块链开发工具,DApp部署。

智能合约 0 次安装 2 次浏览 更新于 2/23/2026

name: foundry-framework description: Foundry(Forge、Cast、Anvil、Chisel)在智能合约开发、测试和部署方面的专家级使用。包括模糊测试、Gas报告、本地开发和部署脚本能力。 allowed-tools: Read, Grep, Write, Bash, Edit, Glob, WebFetch

Foundry 框架技能

Foundry 的专家级使用,这是一个用于以太坊应用开发的极速、可移植和模块化工具包。

能力

  • Forge 测试:使用模糊测试编写和运行 Solidity 测试
  • Gas 优化:生成详细的 Gas 报告和快照
  • 本地开发:使用 Anvil 作为本地区块链
  • 链上交互:执行 Cast 命令进行链上操作
  • 项目配置:为项目设置 foundry.toml
  • 部署脚本:编写和运行 forge 脚本
  • REPL 调试:使用 Chisel 进行 Solidity 探索

安装

# 安装 Foundry
curl -L https://foundry.paradigm.xyz | bash

# 更新到最新版本
foundryup

# 验证安装
forge --version
cast --version
anvil --version
chisel --version

项目设置

初始化项目

# 新项目
forge init my_project
cd my_project

# 添加依赖
forge install OpenZeppelin/openzeppelin-contracts
forge install foundry-rs/forge-std

foundry.toml 配置

[profile.default]
src = "src"
out = "out"
libs = ["lib"]
solc = "0.8.20"
optimizer = true
optimizer_runs = 200
via_ir = false

[profile.default.fuzz]
runs = 256
max_test_rejects = 65536
seed = "0x1234"

[profile.default.invariant]
runs = 256
depth = 15
fail_on_revert = false

[profile.ci]
fuzz = { runs = 10000 }
invariant = { runs = 1000, depth = 50 }

[rpc_endpoints]
mainnet = "${MAINNET_RPC_URL}"
sepolia = "${SEPOLIA_RPC_URL}"
arbitrum = "${ARBITRUM_RPC_URL}"

[etherscan]
mainnet = { key = "${ETHERSCAN_API_KEY}" }
sepolia = { key = "${ETHERSCAN_API_KEY}" }

Forge 测试

基础测试

// test/Counter.t.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "forge-std/Test.sol";
import "../src/Counter.sol";

contract CounterTest is Test {
    Counter public counter;

    function setUp() public {
        counter = new Counter();
        counter.setNumber(0);
    }

    function test_Increment() public {
        counter.increment();
        assertEq(counter.number(), 1);
    }

    function testFail_Underflow() public {
        counter.decrement();
    }
}

模糊测试

contract FuzzTest is Test {
    function testFuzz_SetNumber(uint256 x) public {
        counter.setNumber(x);
        assertEq(counter.number(), x);
    }

    function testFuzz_BoundedInput(uint256 x) public {
        x = bound(x, 1, 100);
        // x 现在在 1 到 100 之间
    }
}

不变性测试

contract InvariantTest is Test {
    Counter public counter;

    function setUp() public {
        counter = new Counter();
        targetContract(address(counter));
    }

    function invariant_NumberNeverNegative() public {
        assertTrue(counter.number() >= 0);
    }

    function invariant_NumberUnderMax() public {
        assertTrue(counter.number() < type(uint256).max);
    }
}

分叉测试

contract ForkTest is Test {
    function setUp() public {
        // 在特定区块分叉主网
        vm.createSelectFork("mainnet", 18000000);
    }

    function test_MainnetState() public {
        // 与主网合约交互
        IERC20 dai = IERC20(0x6B175474E89094C44Da98b954EescdeCB5c811d7);
        uint256 balance = dai.balanceOf(address(this));
    }
}

Forge 命令

# 构建项目
forge build

# 运行测试
forge test

# 详细模式运行测试
forge test -vvvv

# 运行特定测试
forge test --match-test testFuzz_SetNumber

# 运行测试并生成 Gas 报告
forge test --gas-report

# 生成 Gas 快照
forge snapshot

# 比较 Gas 快照
forge snapshot --diff

# 覆盖率
forge coverage

# 格式化代码
forge fmt

Cast 命令

读取链上数据

# 获取 ETH 余额
cast balance 0x... --rpc-url $RPC

# 读取合约存储
cast storage 0x... 0 --rpc-url $RPC

# 调用视图函数
cast call 0x... "balanceOf(address)" 0x... --rpc-url $RPC

# 解码 calldata
cast calldata-decode "transfer(address,uint256)" 0x...

发送交易

# 发送 ETH
cast send 0x... --value 1ether --rpc-url $RPC --private-key $KEY

# 调用合约函数
cast send 0x... "transfer(address,uint256)" 0x... 1000 --rpc-url $RPC --private-key $KEY

实用命令

# 单位转换
cast to-wei 1 ether
cast from-wei 1000000000000000000

# 计算函数选择器
cast sig "transfer(address,uint256)"

# 获取 ABI 编码
cast abi-encode "transfer(address,uint256)" 0x... 100

# 解码 ABI
cast abi-decode "balanceOf(address)(uint256)" 0x...

Anvil 本地节点

# 启动本地节点
anvil

# 使用特定链 ID 启动
anvil --chain-id 31337

# 分叉主网
anvil --fork-url $MAINNET_RPC

# 在特定区块分叉
anvil --fork-url $MAINNET_RPC --fork-block-number 18000000

# 预加载账户
anvil --accounts 20 --balance 10000

Anvil RPC

# 模拟账户
cast rpc anvil_impersonateAccount 0x... --rpc-url http://localhost:8545

# 设置余额
cast rpc anvil_setBalance 0x... 0x1000000000000000000 --rpc-url http://localhost:8545

# 挖矿
cast rpc anvil_mine 10 --rpc-url http://localhost:8545

# 设置区块时间戳
cast rpc evm_setNextBlockTimestamp 1700000000 --rpc-url http://localhost:8545

部署脚本

脚本示例

// script/Deploy.s.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

import "forge-std/Script.sol";
import "../src/Counter.sol";

contract DeployScript is Script {
    function setUp() public {}

    function run() public {
        uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");

        vm.startBroadcast(deployerPrivateKey);

        Counter counter = new Counter();
        counter.setNumber(42);

        vm.stopBroadcast();

        console.log("Counter 部署地址:", address(counter));
    }
}

运行脚本

# 模拟部署
forge script script/Deploy.s.sol --rpc-url $RPC

# 部署到网络
forge script script/Deploy.s.sol --rpc-url $RPC --broadcast

# 在 Etherscan 上验证
forge script script/Deploy.s.sol --rpc-url $RPC --broadcast --verify

Chisel REPL

# 启动 Chisel
chisel

# 在 REPL 中
> uint256 x = 100
> x * 2
200
> address(this)
0x...

流程集成

流程 目的
smart-contract-development-lifecycle.js 完整开发流程
smart-contract-fuzzing.js 模糊测试和不变性测试
invariant-testing.js 基于属性的测试
gas-optimization.js Gas 性能分析
所有 DeFi 流程 测试和部署

最佳实践

  1. 提交前使用 forge fmt
  2. 维护 Gas 快照用于回归测试
  3. 使用分叉测试进行集成测试
  4. 为 CI 设置适当的模糊测试运行次数
  5. 使用基于配置文件的配置
  6. 将 foundry.toml 保存在版本控制中

另请参阅

  • skills/hardhat-framework/SKILL.md - 替代框架
  • skills/echidna-fuzzer/SKILL.md - 高级模糊测试
  • skills/gas-optimization/SKILL.md - Gas 优化
  • Foundry 手册