Foundry[5]中常用命令和作弊码的速查表。
还可以在 gist[6] 中找到此速查表。
初始化
创建新项目
创建新项目:
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>
Cheatcodes 作弊吗码
参考作弊码参考[7]获取所有可用作弊码。
上下文 context
// 设置 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)
调用者 Caller
// 为下一次调用设置 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)
调用 call
// 模拟对 `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
// 期望一下一个调用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`[8] 获取所有功能。
余额
// 为某地址设置余额
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`[9],用于捕获内部 Solidity 错误:
stdError.assertionError - assert失败。
stdError.arithmeticError - 算术运算失败(例如溢出/下溢)。
stdError.divisionError - 除法失败(例如除以零)。
stdError.indexOOBError - 访问超出范围的数组元素。
stdError.popError - 从空数组中弹出。不适用于外部合约中的空数组。
stdError.enumConversionError - 将大于枚举变体数量的数字转换为枚举。
stdError.encodeStorageError - 使用内联汇编访问损坏的存储中的数据。
stdError.memOverflowError - 分配具有超过 2^64-1 个项目的动态内存数组。
stdError.zeroVarError - 通过未初始化的函数指针调用函数。
断言
来自 forge-std/std-assertions[10]。
// 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)
数学
来自 `forge-std/std-math`[11]。
// 返回绝对值
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[12] 协助支持, 在 DeCert 构建可信履历,为自己码一个未来。
参考资料
[1]
登链翻译计划: https://github.com/lbc-team/Pioneer
[2]
翻译小组: https://learnblockchain.cn/people/412
[3]
Tiny 熊: https://learnblockchain.cn/people/15
[4]
learnblockchain.cn/article…: https://learnblockchain.cn/article/7344
[5]
Foundry: https://learnblockchain.cn/docs/foundry/i18n/zh/index.html
[6]
gist: https://gist.github.com/MiloTruck/30cd9b051176da8b76fe7dc81996eaf9
[7]
作弊码参考: https://learnblockchain.cn/docs/foundry/i18n/zh/cheatcodes/index.html
[8]
Forge Std 的Test: https://learnblockchain.cn/docs/foundry/i18n/zh/reference/forge-std/
[9]
forge-std/std-errors: https://learnblockchain.cn/docs/foundry/i18n/zh/reference/forge-std/std-errors.html
[10]
forge-std/std-assertions: https://learnblockchain.cn/docs/foundry/i18n/zh/reference/forge-std/std-assertions.html
[11]
forge-std/std-math: https://learnblockchain.cn/docs/foundry/i18n/zh/reference/forge-std/std-math.html
[12]
DeCert.me: https://decert.me/
声明:本网站所有相关资料如有侵权请联系站长删除,资料仅供用户学习及研究之用,不构成任何投资建议!