Foundry 项目结构
本章介绍一个新的 Foundry
项目的基本结构。
我们使用 forge init 命令构建的项目,在默认情况下,项目中包含 4 个目录 lib
、script
、src
、test
,以及 foundry.toml
文件。
项目的结构如下所示:
. ├── foundry.toml ├── lib │ └── forge-std │ ├── LICENSE-APACHE │ ├── LICENSE-MIT │ ├── README.md │ ├── foundry.toml │ ├── lib │ └── src ├── script │ └── Counter.s.sol ├── src │ └── Counter.sol └── test └── Counter.t.sol 7 directories, 8 files
各目录的用途说明:
- 文件
foundry.toml
:项目配置文件,用于配置forge
命令的行为。 - 目录
src
:用于存放待发布的智能合约文件。我们最终要发布的智能合约都要放到这个目录下。 - 目录
test
:用于存放测试使用的智能合约文件。我们使用这些合约执行测试,以验证src
目录下合约功能的正确性。 - 目录
lib
:用于存放项目依赖的库。如果项目需要依赖于外部智能合约或库(比如 OpenZeppelin 的合约),它们将会被安装在这个目录下。 - 目录
script
:包含用于与智能合约交互的脚本。这些脚本可以用来部署合约、执行交易或者调用合约的函数。
这个结构旨在帮助开发者组织和管理智能合约项目,使得代码更加模块化,便于管理和协作。
这些目录都是按照默认配置生成的,但是我们可以通过 forge
命令参数改变这些目录。
比如:使用 --lib-paths 可以指定依赖库所在的目录;使用 --contracts 可以指定合约存放的目录。
另外,我们还可以在 foundry.toml
中自行配置这些目录。
lib 目录
在 lib
目录中,默认安装了 forge-std
依赖库,这也是 Foundry
项目必不可少的一个基础依赖库。
forge-std
是 Foundry
框架中的一个标准库,旨在为智能合约开发者提供一系列的实用功能和工具,以便更高效地编写、测试和部署智能合约。
forge-std
包含了许多预定义的合约和库函数,这些功能涵盖了合约测试、模拟交易、状态修改等多个方面,极大地简化了合约开发过程中的常见任务。
src 目录
待发布合约的默认目录是 src
。这个目录中可以放置任意多个合约,它们最终都要部署到主网。我们的测试工作也都是针对这些合约进行的。
在一个新创建的项目中,默认包含了一个样例合约 Counter.sol,用于初学者学习使用。在实际项目中,我们可以直接删除。
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.13; contract Counter { uint256 public number; function setNumber(uint256 newNumber) public { number = newNumber; } function increment() public { number++; } }
这个合约实现了一个简单的计数器功能。其中函数 setNumber 用于设置计数器的初值。函数 increment 用于将计数器加 1 。
test 目录
用于存放测试使用的智能合约文件。我们使用这些合约执行测试,以验证 src
目录下合约功能的正确性。
在一个新创建的项目中,默认包含了一个样例合约 Counter.t.sol,用于测试 src
目录中 Counter.sol 合约。
它的代码如下:
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.13; import {Test, console} from "forge-std/Test.sol"; import {Counter} from "../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 test_SetNumber(uint256 x) public { counter.setNumber(x); assertEq(counter.number(), x); } }
合约中任何具有以 test 开头的函数的合约都被视为测试用例,比如: 函数 test_Increment 和 test_SetNumber,它们都是测试用例。
我们在执行 forge test 命令时,就会自动执行 test_Increment 和 test_SetNumber 这两个函数。