Fuzzlib 是一个通用的 Solidity 模糊测试库,兼容 Echidna、Medusa 和 Foundry,提供了 assertions、value clamping、logging 和 math operations 等常用工具,方便进行有状态的和无状态的模糊测试。它通过 fl 命名空间提供常用工具,例如断言、值钳制、日志记录、数学运算等。
Fuzzlib 是一个通用的 Solidity 模糊测试库, 提供了 assertions、value clamping、logging 和 math operations 等常用工具,方便进行有状态的和无状态的模糊测试, 方便我们在测试 Solidity 合约时,发现更多的问题。
详见 Github: https://github.com/perimetersec/fuzzlib
以下介绍翻译自:Fuzzlib Github 的 Readme:
用于有状态和无状态模糊测试的通用、非主观的 Solidity 模糊测试库。兼容 Echidna、Medusa 和 Foundry。
通过简单的 fl
命名空间提供用于模糊测试的常用实用程序:断言、值钳位(value clamping)、日志记录、数学运算等。
errAllow
进行错误处理的实用程序,用于预期的故障forge install perimetersec/fuzzlib
soldeer install perimetersec-fuzzlib~1.0.0
npm install @perimetersec/fuzzlib
添加到你的 remappings.txt
:
fuzzlib/=lib/fuzzlib/src/
通过扩展 FuzzBase
来创建一个简单的模糊测试:
import {FuzzBase} from "fuzzlib/FuzzBase.sol";
contract MyFuzzer is FuzzBase {
function testMath(uint256 a, uint256 b) public {
// 将输入钳位到合理的范围内
uint256 x = fl.clamp(a, 0, 1000);
uint256 y = fl.clamp(b, 0, 1000);
// 记录以进行调试
fl.log("Testing max function. x =", x);
fl.log("Testing max function. y =", y);
// 测试数学性质
fl.gte(fl.max(x, y), x, "Max should be >= x");
fl.gte(fl.max(x, y), y, "Max should be >= y");
}
}
// 基本断言
fl.t(exists, "Property X exists");
fl.eq(result, 100, "Result should equal 100");
fl.neq(userA, userB, "Users should be different");
// 比较断言
fl.gt(balance, 1000, "Balance should be greater than 1000");
fl.gte(amount, 50, "Amount should be greater than or equal to 50");
fl.lt(fee, 100, "Fee should be less than 100");
fl.lte(price, 500, "Price should be less than or equal to 500");
// 允许特定的 require 消息
string[] memory allowedMessages = new string[](1);
allowedMessages[0] = "Insufficient balance";
fl.errAllow(errorData, allowedMessages, "Message X should be allowed");
// 允许特定的自定义错误
bytes4[] memory allowedErrors = new bytes4[](1);
allowedErrors[0] = CustomError.selector;
fl.errAllow(errorSelector, allowedErrors, "Error X should be allowed");
// 组合的错误处理
fl.errAllow(errorData, allowedMessages, allowedErrors, "Either should be allowed");
// 具有均匀分布的值钳位
uint256 clamped = fl.clamp(inputValue, 0, 100);
// 钳位到大于值
uint256 clampedGt = fl.clampGt(inputValue, 50);
// 钳位到大于或等于
uint256 clampedGte = fl.clampGte(inputValue, 50);
// 钳位到小于值
uint256 clampedLt = fl.clampLt(inputValue, 100);
// 钳位到小于或等于
uint256 clampedLte = fl.clampLte(inputValue, 100);
// 简单日志记录
fl.log("Testing scenario");
// 记录值
fl.log("Balance:", balance);
fl.log("User count:", 42);
// 故障日志记录
fl.logFail("This test failed");
fl.logFail("Invalid amount:", amount);
// 最小值/最大值运算
uint256 maximum = fl.max(150, 300);
int256 minimum = fl.min(-50, 25);
// 绝对值和差值
uint256 absolute = fl.abs(-42);
uint256 difference = fl.diff(100, 75);
// 混排数组
uint256[] memory array = new uint256[](10);
fl.shuffleArray(array, entropy);
// 进行函数调用
bytes memory result = fl.doFunctionCall(
address(target),
abi.encodeWithSignature("getValue()"),
msg.sender // 执行者
);
// 使用自动欺骗进行调用
(bool success, bytes memory data) = fl.doFunctionCall(
address(target),
abi.encodeWithSignature("transfer(address,uint256)", recipient, amount),
sender
);
// 静态调用(视图函数)
(bool success, bytes memory data) = fl.doFunctionStaticCall(
address(target),
abi.encodeWithSignature("balanceOf(address)", user)
);
int128
范围,以避免范围计算中的溢出问题Error(string)
冲突,可能会发生意外行为我们欢迎贡献! 有关详细信息,请参阅我们的贡献指南。
本项目采用 GNU General Public License v3.0 协议授权。 有关详细信息,请参见 LICENSE 文件。
此代码的某些部分修改自 Crytic Properties,该代码已获得 GNU Affero General Public License v3.0 (AGPL-3.0) 协议的许可。
此代码的某些部分修改自 OpenZeppelin Contracts,该代码已获得 MIT 许可证的许可。
本软件按原样提供,不提供任何担保。 主分支包含新的和实验性的功能,这些功能可能不稳定。 对于生产用途,我们建议使用经过全面测试的官方标记版本。 虽然我们不对任何 bug 或问题负责,但我们维护一个仅适用于官方版本的 bug 赏金计划。
- 原文链接: github.com/perimetersec/...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!