Foundry 常用命令和作弊码速查表
- 原文链接:https://milotruck.github.io/blog/Foundry-Cheatsheet/
- 译文出自:登链翻译计划
- 译者:翻译小组 ,校对:Tiny 熊
- 本文永久链接:learnblockchain.cn/article…
Foundry中常用命令和作弊码的速查表。
还可以在 gist 中找到此速查表。
创建新项目:
forge init <project_name>
使用模板创建新项目:
forge init --template <template> <project_name>
# 例如
forge init --template https://github.com/zobront/paradigm-ctf paradigm_ctf
初始化 Foundry:
# Create required directories
mkdir out lib
# 添加 `forge-std` 模块到 `lib`
git submodule add https://github.com/foundry-rs/forge-std lib/forge-std
# Create foundry.toml
touch foundry.toml
在foundry.toml
中指定目录:
[profile.default]
src = "contracts"
out = "out"
lib = "lib"
在现有项目中安装依赖项:
forge install
添加新依赖项:
forge install <dependency>
# 例如
forge install openzeppelin/openzeppelin-contracts
将依赖项添加到现有 git 存储库:
# 不生成 git commit
forge install --no-commit <dependency>
# 不生成 git 库
forge install --no-git <dependency>
Forge 可以自动推断重映射:
forge remappings > remappings.txt
要自定义重映射,只需将其添加到remappings.txt
中:
echo "@openzeppelin/=lib/openzeppelin-contracts/" > remappings.txt
运行测试:
forge test
日志详细程度
-vv
显示console.log
输出。-vvv
显示失败测试的执行跟踪。-vvvv
显示所有测试的执行跟踪,并显示失败测试的设置跟踪。-vvvvv
显示所有测试的执行和设置跟踪。运行特定测试:
--match-test
运行与指定正则表达式匹配的测试。--match-contract
运行与指定正则表达式匹配的合约中的测试。--match-path
运行与指定路径匹配的源文件中的测试。分叉网络:
forge test --fork-url <rpc_url>
要在分叉环境中识别合约,请使用--etherscan-api-key
传递你的 Etherscan API 密钥:
forge test --fork-url <rpc_url> --etherscan-api-key <etherscan_api_key>
参考作弊码参考获取所有可用作弊码。
// 设置 block.timestamp
vm.warp(uint256 timestamp)
// 增加指定秒数到 block.timestamp
skip(uint256 time)
// 减少指定秒数到 block.timestamp
rewind(uint256 time)
// 设置 block.number
vm.roll(uint256 blockNumber)
// 从地址上加载槽位
vm.load(address account, bytes32 slot)
// 写入数据到槽位
vm.store(address account, bytes32 slot, bytes32 value)
// 设置地址上的代码
vm.etch(address addr, bytes calldata code)
// 为下一次调用设置 msg.sender
vm.prank(address msgSender)
// 为之后的一系列调用设置 msg.sender
vm.startPrank(address msgSender)
// 停止上次的设置
vm.stopPrank()
// 改变之后的一系列调用的 msg.sender
changePrank(address msgSender)
// 设置 msg.sender 以及为下一次调用充 ether
hoax(address who)
hoax(address who, uint256 give)
hoax(address who, address origin)
hoax(address who, address origin, uint256 give)
// 为之后的一系列调用设置msg.sender 以及充 ether
startHoax(address who)
startHoax(address who, uint256 give)
startHoax(address who, address origin)
startHoax(address who, address origin, uint256 give)
// 模拟对 `where` 的调用, 如果 `data` 匹配返回 `retdata`
vm.mockCall(address where, bytes calldata data, bytes calldata retdata);
// 和上一条类似,但有 msg.value 需要匹配 `value`
vm.mockCall(address where, uint256 value, bytes calldata data, bytes calldata retdata);
示例用法:
function testMockCall() public {
// Without value
vm.mockCall(
address(token),
abi.encodeWithSelector(token.balanceOf.selector, ALICE),
abi.encode(10)
);
assertEq(token.balanceOf(ALICE), 10);
// With value
vm.mockCall(
address(market),
10 ether,
abi.encodeWithSignature("pay(address,uint256)", ALICE, 10 ether),
abi.encode(true)
);
assertTrue(market.pay{value: 10 ether}(ALICE, 10 ether));
}
// 期望一下一个调用revert
vm.expectRevert()
// 期望下一个调用 revert 并抛出 `message`
vm.expectRevert(bytes calldata message)
// 期望下一个调用 revert 并抛出 `bytes4 data` 错误(用于自定义的 error selectors)
vm.expectRevert(bytes4 data)
// 给当前状态快照
uint256 snapshot = vm.snapshot();
// 还原到快照
vm.revertTo(uint256 snapshot);
参考 Forge Std 的Test
获取所有功能。
// 为某地址设置余额
deal(address to, uint256 balance)
// 为某地址设置 ERC20 余额
deal(address token, address to, uint256 balance)
//为某地址设置 ERC20 余额 ,如果 adjust 为 true,增加 totalSupply
deal(address token, address to, uint256 balance, bool adjust)
// 为某地址加指定 `id` 的 ERC721 token
dealERC721(address token, address to, uint256 id)
// 为某地址加指定 `id` 指定数量的 ERC1155 token
dealERC1155(address token, address to, uint256 id, uint256 balance)
// 为某地址加指定 `id` 指定数量的 ERC1155 token , 如果 adjust 为 true,增加发行量
dealERC1155(address token, address to, uint256 id, uint256 balance, bool adjust)
来自 forge-std/std-errors
,用于捕获内部 Solidity 错误:
stdError.assertionError
- assert
失败。stdError.arithmeticError
- 算术运算失败(例如溢出/下溢)。stdError.divisionError
- 除法失败(例如除以零)。stdError.indexOOBError
- 访问超出范围的数组元素。stdError.popError
- 从空数组中弹出。不适用于外部合约中的空数组。stdError.enumConversionError
- 将大于枚举变体数量的数字转换为枚举。stdError.encodeStorageError
- 使用内联汇编访问损坏的存储中的数据。stdError.memOverflowError
- 分配具有超过 2^64-1 个项目的动态内存数组。stdError.zeroVarError
- 通过未初始化的函数指针调用函数。// Fail a test with a message
fail(string memory err)
// Assert true/false
assertTrue(bool data)
assertTrue(bool data, string memory error)
assertFalse(bool data)
assertFalse(bool data, string memory err)
// 断言相等
assertEq(<type> a, <type> b)
assertEq(<type> a, <type> b, string memory err)
// Asserts `a` is approximately equal to `b` with delta in absolute value.
assertApproxEqAbs(uint256 a, uint256 b, uint256 maxDelta)
assertApproxEqAbs(uint256 a, uint256 b, uint256 maxDelta, string memory err)
// Asserts `a` is approximately equal to `b` with delta in percentage, where `1e18` is 100%.
assertApproxEqRel(uint256 a, uint256 b, uint256 maxPercentDelta)
assertApproxEqRel(uint256 a, uint256 b, uint256 maxPercentDelta, string memory err)
// 创建一个标签地址
address addr = makeAddr(string memory name)
// 创建一个标签地址 和私钥
(address addr, uint256 privateKey) = makeAddrAndKey(string memory name)
// 签名数据
(uint8 v, bytes32 r, bytes32 s) = vm.sign(uint256 privateKey, bytes32 digest)
// 返回绝对值
uint256 v = abs(int256 a)
// 返回绝对差值
uint256 v = delta(uint256 a, uint256 b)
uint256 v = delta(int256 a, int256 b)
// 返回百分比差值, `1e18` 是 100%.
uint256 v = percentDelta(uint256 a, uint256 b)
uint256 v = percentDelta(int256 a, int256 b)
使用vm.assume()
指定输入条件。应仅用于狭窄检查:
function testSomething(uint256 v) public {
vm.assume(v != 0);
require(v != 0);
...
}
使用bound()
限制输入到特定范围:
function testSomething(uint256 v) public {
v = bound(v, 100, 500);
require(v >= 100 && v <= 500);
...
}
本翻译由 DeCert.me 协助支持, 在 DeCert 构建可信履历,为自己码一个未来。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!