打破我‘完美’合约的测试
Source: Dev.to
为什么开发工具比以往更重要
第一次有测试毁掉我的“完美”智能合约时,攻击者并不是黑客,而是我自己的开发环境。我刚完成一个 AI 辅助的 Solidity 合约——代码整洁,没有编译器警告,几个正常路径的测试都通过了。
然后我切换了框架,执行了一条命令,看到模糊测试把它撕得粉碎。相同的合约、相同的逻辑,却用了不同的工具。
那时我恍然大悟:
你如何开发和测试合约(Hardhat、Foundry、静态分析器)几乎和你写的代码本身一样重要。
为什么开发工具现在如此重要
到目前为止,在本系列中,你已经:
- 编写并部署了简单的合约。
- 看到像重入攻击这样的漏洞如何抽走真实的资金。
- 目睹 AI 生成的“可运行”Solidity 代码仍然隐藏安全陷阱。
当前的现实:
- 智能合约漏洞每年仍然让用户损失数亿美元。
- 安全标准(例如 OWASP 智能合约 Top 10、审计公司指南)强调测试、模糊测试和静态分析,而不仅仅是“能编译”。
大多数严肃的团队使用以下组合:
- 开发框架 – Hardhat / Foundry
- 自动化测试 – 单元测试、集成测试、模糊测试
- 静态分析工具 – Slither、Aderyn
因此,如果你今天在学习 Web3,你学习的已经不只是 Solidity 语法,而是一种工作流。
Hardhat – JavaScript 助手
Hardhat 多年来一直是默认的以太坊开发工具,仍然被广泛使用。把它当作你的 全栈开发伴侣:
- 用 JavaScript 或 TypeScript 编写测试和脚本。
- 部署合约、分叉主网、运行任务,并与前端工具链对接。
- 丰富的插件生态(Ethers.js、OpenZeppelin、gas 报告、覆盖率等)。
为什么初学者和产品团队喜欢 Hardhat
- 如果你来自 Web2 或 React,JS/TS 测试使用起来很自然。
- 与 MetaMask、Alchemy、Infura 等基础设施配合良好。
- 可以在本地测试中使用主网分叉,模拟真实用户流程。
缺点
- 测试使用 JS/TS 编写,而合约使用 Solidity → 上下文切换可能会让部分人感到慢。
- 模糊测试和高级测试通常是基于插件,而非内置功能。
Hardhat 的优势体现于
- 你正在构建带前端的 dApp。
- 你需要丰富的工具链和集成。
- 你既考虑 “产品流程” 又考虑 “原始 Solidity”。
Foundry – Solidity 原生强力工具
Foundry 已迅速成为 Solidity 密集型和安全导向工作的首选。把它想象成你的 高性能测试与安全平台:
- 直接用 Solidity 编写测试。
- 使用
forge test运行它们。 - 内置模糊测试、Invariant 测试、作弊码,以及极快的编译速度。
关键优势
| 功能 | 好处 |
|---|---|
| 速度 | 基准显示 Foundry 编译和运行测试的速度是传统基于 JS 的方案的数倍。 |
| Solidity‑优先 | 没有 JS/TS 层;你的测试就是合约。只用一种语言,思考方式与 EVM 同步。 |
| 安全友好 | 模糊测试和 Invariant 是一等公民,正是现代安全指南所推荐的。 |
为什么在前面的文章之后仍然重要
- 在审查 AI 生成的合约时,模糊测试可以触及你从未想到的奇怪输入。
- 当担心重入或逻辑错误时,Invariant 让你能够断言诸如 “无论输入如何,总余额永不为负” 之类的属性。
Foundry 的最佳适用场景
- 你非常关注 Solidity 的正确性和安全性。
- 你习惯主要在 Solidity 中工作。
- 你希望 快速 迭代测试和合约。
Source: …
那么… Hardhat 还是 Foundry?
对于大多数构建者来说,诚实的答案往往是:两者都用,取决于具体任务。
思维模型
| 工具 | 侧重点 |
|---|---|
| Hardhat | 产品与集成 – JS/TS 测试、主网分叉、插件生态、前端/DevOps 集成。 |
| Foundry | Solidity 与安全 – 快速编译/测试循环、仅 Solidity 测试、内置模糊测试与不变性检查。 |
你不必永远只用一种工具。常见的工作流:
- 使用 Foundry 进行原型开发与核心逻辑测试。
- 使用 Hardhat 编写部署脚本、主网分叉以及前端集成。
对于这 60 天的旅程
- 如果你刚开始熟悉 Solidity,先用 Foundry 编写测试实际上可以更快地学习 Solidity。
- 如果你更熟悉 JS/TS,Hardhat 则是进入智能合约世界的平缓坡道。
真正的错误不是选择了“错误”的框架。
而是没有认真使用任何框架,只依赖 Remix + 运气。
Slither 与 Aderyn 的适用场景
在上一篇文章中,一位 Medium 关注者 MihaiHng 评论道:
“除了手动审查以确保遵守 CEI 模式之外,还有一些非常有用的静态分析工具,例如 Slither、Aderyn。”
他完全正确。手动审查 + CEI 很重要,但现代安全文化默认 你会遗漏一些东西。这正是静态分析器发挥作用的地方。
Slither (Trail of Bits)
- 最广泛使用的 Solidity 静态分析工具之一。
- 快速检测常见漏洞(重入、访问控制问题、危险模式)。
- 能够很好地集成到 CI 中,并兼容 Hardhat 与 Foundry 项目。
Aderyn (Cyfrin)
- 专注于 Solidity 项目的现代静态分析器。
- 对 Foundry 与 Hardhat 项目提供一流支持。
- 生成 JSON、Markdown、SARIF 格式的报告,并可在 VS Code 中提供编辑器内反馈。
实际工作流
- 在 Hardhat 或 Foundry 中编写测试。
- 运行模糊测试/不变量检查以获得更深的覆盖率。
- 同时运行 Slither/Aderyn,以捕获人类和测试可能遗漏的模式。
一个可复制的开发工作流
下面是一个轻量级流程,你可以在下一个合约项目中实际使用:
1. 原型
- 使用 AI(谨慎)加上你自己的编辑来起草 Solidity 合约。
- 保持合约 小而专注。
2. 选择框架
-
如果你使用 JavaScript 环境:
npx hardhat init # write JS/TS tests -
如果你以 Solidity 为主:
forge init # write Solidity tests
3. 编写测试
- 针对正常路径行为的单元测试。
- 针对边缘情况的模糊测试 / 不变量测试。
4. 运行静态分析
# Hardhat example
npx hardhat run scripts/deploy.ts
slither .
# Foundry example
forge test
aderyn .
5. CI 集成
- 添加一个 GitHub Actions 工作流,运行
forge test && slither .或hardhat test && slither .。 - 只要有任何发现就使构建失败。
6. 部署
- 使用 Hardhat 脚本进行前端就绪的部署,或使用 Foundry 的
forge create快速在主网分叉上部署。
Solidity land: Foundry 项目,Solidity 测试
编写基础测试
- Happy‑path 单元测试 – 存款、取款、状态变更。
- 一些 “恼人用户” 场景(零值、超大值、重复调用)。
添加模糊测试 / 不变量
- Foundry – 使用内置的模糊测试和不变量。
- Hardhat – 如有需要,可通过插件或外部工具添加模糊测试。
运行静态分析
- Slither – 快速扫描已知的 bug 模式。
- Aderyn – 额外的检测器以及更好地与现代技术栈集成。
只有在此之后才考虑 testnet / mainnet
在测试 + 模糊测试 + 静态分析全部通过后,部署到测试网(例如 Sepolia)。
- 将合约地址分享给社区,以获得更多审视。
TL;DR
- Hardhat = 以产品为中心,友好的 JS/TS,插件生态丰富。
- Foundry = 以 Solidity 为中心,超高速,安全优先。
- Slither & Aderyn = 静态分析安全网。
根据任务需求灵活组合使用,切勿只依赖单一工具。祝开发愉快!
接下来会有什么
今天的文章放大视角并提出:
“现实中的团队到底是如何开发和测试智能合约的?”
明天我们将把视角拉回,在真实合约上进行端到端操作:
- 选取一个小型的 AI 生成的 Solidity 合约。
- 将其包装进一个 Foundry 项目。
- 添加少量测试,然后进行模糊测试和不变量检查。
- 运行一次 Slither 或 Aderyn,看看它们在任何测试网部署之前捕获了哪些问题。
把今天当作领土的地图。
明天,我们将一起一步步走完整条路径。
深入资源
- Solidity 文档 — 安全注意事项 – 官方语言文档,解释外部调用为何危险以及如何安全地组织状态更改。
- ConsenSys Diligence — 智能合约最佳实践 – 关于攻击模式、checks‑effects‑interactions(检查‑效果‑交互)以及常见陷阱的经典参考。
- OpenZeppelin 合约 — ReentrancyGuard – 实际使用该模式的事实标准实现,帮助你了解如何正确使用重入锁。
- Foundry 文档 – 完整的安装指南、模糊测试、invariants(不变量)以及 cheatcodes(作弊码)使用说明。
关注系列内容
- Medium: Ribhav Modi
- Twitter: @RibsModi
- Future: Ribhav Modi
加入 Telegram 讨论群:Web3ForHumans,一起构建未来。