Foundry是一个用Rust语言编写的以太坊部署环境,能够帮助开发者管理依赖项、编译项目、运行测试、部署合约以及从命令行与区块链交互。由于最近开发公链使用了和foundry一样的evm crate,就安装了一下看看,后边可能需要对foundry进行二次开发;这次就简单的测试一下;
Foundry由四个工具组成:
这里我只写一下,我实践过方法;
如果您使用 Linux 或 macOS,使用 foundryup 安装最新版本,对于 Linux 和 macOS 用户来说,这是最简单的选择。打开您的终端并输入以下命令:
-
- curl -L https://foundry.paradigm.xyz | bash
这将下载foundryup。 然后通过运行安装 Foundry:
foundryup
如果一切顺利,您现在可以使用三个二进制文件:forge、cast 、anvil和chisel。
如果您使用 macOS 并显示以下错误,您需要键入 brew install libusb 来安装库
dyld[32719]:Library not loaded:/usr/local/opt/libusb/lib/libusb-1.0.0.dylib
要从源代码构建,您需要获取 Rust和 Cargo。所以需要先按照rust的开发环境;读者自行安装。
安装好环境执行,就比较简单了,方法1或者2,任选一种;
方法1:
cargo install --git https://github.com/foundry-rs/foundry --profile local forge cast chisel anvil
方法2:
- # clone the repository
- git clone https://github.com/foundry-rs/foundry.git
- cd foundry
- # install Forge
- cargo install --path ./crates/forge --profile local --force
- # install Cast
- cargo install --path ./crates/cast --profile local --force
- # install Anvil
- cargo install --path ./crates/anvil --profile local --force
- # install Chisel
- cargo install --path ./crates/chisel --profile local --force
Linux/macOS使用foundryup,很方便;如果你是在windows,只能从源码构建了;
使用如下命令,创建一个默认的项目
forge init foundry
创建默认项目后,您将看到以下文件:
- .
- ├── 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 配置 Foundry 的行为。remappings.txt 中指定。src/。test/,其中任何具有以test开头的函数的合约都被视为测试。lib/ 中。src文件夹可能已经包含Counter.sol(一个最小的Solidity合约),我可以自行删除此合约。然后添加,一个ERC-20合约。在合约目录中,可以创建一个Token.sol文件,打开文件并添加以下合约:
- // SPDX-License-Identifier: UNLICENSED
- pragma solidity ^0.8.13;
-
- import "openzeppelin-contracts/contracts/token/ERC20/ERC20.sol";
-
- contract Token is ERC20{
- constructor(
- string memory name,
- string memory symbol,
- uint256 initialSupply) ERC20(name, symbol){
- _mint(msg.sender, initialSupply);
- }
- }
由于我们使用了OpenZeppelin合约,需要在编译合约之前,安装OpenZeppelin合约作为依赖项。我们使用forge install xxx安装依赖项;(默认情况下,Forge 使用 git submodules管理依赖项,这意味着它可以与任何包含智能合约的 GitHub 代码库一起使用。)所以xxx可以是一个 GitHub 仓库的路径(owner/repo),详细可以参考forge install
forge install OpenZeppelin/openzeppelin-contracts
安装完所有的依赖项后,您可以开始编译合约:
forge build
编译完成后,将创建两个文件夹:out和cache。您合约的ABI和字节码将包含在out文件夹中。这两个文件夹已被默认Foundry项目初始化中包含的.gitignore忽略。
让我们回顾一下最常见的编写测试的方式,使用 Forge 标准库(forge-std) 的 Test 合约,这是使用 Forge 编写测试的首选方式。它提供基本的日志记录和断言功能。 要访问这些函数,请导入 forge-std/Test.sol 并继承自测试合约 Test :
import "forge-std/Test.sol";
测试之前,我们先看下一test文件夹底下的Counter.t.sol;注意名字中的.t。
- import {Test, console2} from "forge-std/Test.sol";
- import {Counter} from "../src/Counter.sol";
-
- contract CounterTest is Test {
- Counter public counter;
- //setUp:在每个测试用例运行之前调用的可选函数,用于部署环境
- function setUp() public {
- counter = new Counter();
- counter.setNumber(0);
- }
- //test:以 test 为前缀的函数作为测试用例运行
- function test_Increment() public {
- counter.increment();
- assertEq(counter.number(), 1);
- }
- //testFail: test 前缀的测试的反面 - 如果函数没有 revert,则测试失败
- function testFail_Increment() public {
- counter.increment();
- assertEq(counter.number(), 99);
- }
-
- function testFuzz_SetNumber(uint256 x) public {
- counter.setNumber(x);
- assertEq(counter.number(), x);
- }
- }
我们修改创建一个Token.t.sol,用来测试我们的Token.sol;
- // SPDX-License-Identifier: UNLICENSED
- pragma solidity ^0.8.13;
-
- import {Test, console2} from "forge-std/Test.sol";
- import {Token} from "../src/Token.sol";
-
- contract TokenTest is Test {
- Token public token;
- //使用0x9创建一个新的erc20合约
- function setUp() public {
- vm.prank(address(9));
- token = new Token("XQToken","XQ", 10000);
- }
- //测试0x9的地址上,token数量是不是等于总量
- function test_BalanceOf() public {
- uint256 bo = token.balanceOf(address(9));
- assertEq(bo, 10000);
- }
- }
然后就可以使用,forge test进行测试啦;
更多细节可以查看Foundry