这是我的 AI + Web3 实战营 的第六篇研发日志,前五篇如下:
AI+Web3实战营日志 #4 | Rebalancer合约
另外,关于 AI + Web3 实战营的相关介绍则有如下几篇文章:
前天完成了 BlockETF 的第一个里程碑目标——合约开发。之后,昨晚我们就开始进入 测试阶段。
一开始,我就直接对 Claude Code 说:
“现在我们已经完成了 MVP 版本的合约开发,4 个合约都已经完成,下一步我们需要对这些合约进行充分测试。请你先帮我设计出所有测试用例,要尽可能覆盖所有场景。”
Claude Code 立刻开始干活。不过它一开始把整个 测试用例方案 直接打印在聊天窗里,这其实不太方便回看。于是我让它生成文档保存,结果它也很听话,立刻输出了一份 测试计划文档。
第一版测试计划
第一版的测试计划文档已经相当完整,包括:
- 200+ 个测试用例,覆盖所有 4 个合约
- 12 个测试类别:功能、集成、安全、性能等
- 优先级标记:P0 / P1 / P2
- 测试执行计划与时间表
- 环境配置与工具清单
- 验收标准与风险评估
文档大纲长这样👇
要是交给传统测试人员来写,这样一份文档至少要一周时间。Claude Code 却只用了几分钟就完成了。
不足与改进
当然,第一版并不完美。当我开始 review 第一个合约的第一个模块时,就发现用例设计不够完整。我反馈给 Claude Code:
“BlockETFCore 的初始化测试有很多异常情况没覆盖,比如 oracle 没有初始化、价格为 0、数组长度不一致等等。你需要把这些场景都补上。”
在第一版中,初始化模块只有 6 个用例。经过补充,现在扩展到 51 个完整用例,涵盖了:
- 基础验证:正常流程和重复初始化
- Oracle相关:未设置、零价格、异常、过期数据
- 数组验证:空数组、长度不匹配、边界测试
- 资产验证:零地址、重复、非ERC20、恶意代币、不同精度
- 权重验证:总合验证、零权重、溢出测试
- 目标价值验证:过小、零值、极大值
- 转账和余额:余额不足、授权、钩子攻击
- 计算验证:精度损失、舍入误差
- 份额铸造:分配验证、比例验证
- 状态更新:所有状态变量的正确性
- 权限验证:owner权限检查
- 边界和极端情况:价格差异、gas限制、并发
- 集成场景:真实代币、特殊代币
- 事件验证:事件参数正确性
说实话,这么全面的用例设计,连我自己都感到惊喜。单靠人工,很难一次性想到这么多角度。
之后,我又让 Claude Code 把其他功能模块的用例也全部补齐,最终整个测试计划扩展到了 500+ 用例,覆盖了所有公开函数、边界条件和异常场景。
但在继续 review 的过程中,我发现 调整权重 模块依然缺失,便再次要求补充。
推动合约细节优化
这一次的测试设计,不仅让我们收获了一份更完整的测试计划,也顺带推动了合约的细节优化。很多时候,测试用例本身就是发现潜在问题的最好手段。
在 review BlockETFCore 的初始化用例时,我们就注意到几个可以改进的地方:
- Oracle 初始化流程:原本需要先部署合约,再单独调用
setPriceOracle,过程有点繁琐,也存在中间步骤失败的风险。于是我们把 Oracle 地址直接放进构造函数里,部署时一步完成,既减少操作步骤,也更直观。 - 防止重入攻击:初始化函数涉及到多次外部调用。为避免潜在的重入风险,我们给
initialize函数加上了nonReentrant修饰符,让逻辑执行更安全。 - 代币转账的安全性:原本用的是直接
transferFrom,这种方式在失败时可能静默不报错。现在统一改为SafeERC20,确保转账失败会直接revert,避免出现账面和实际不一致的问题。
这些调整看似只是小细节,但它们能大幅提升合约的健壮性。也可以说,正是测试驱动,让我们在实现阶段就提前发现了潜在风险点,并及时修正。
下一步
目前,我们只完成了 BlockETFCore 合约的第一个测试模块——初始化测试。接下来还有大量的测试用例需要逐个走通。
在推进节奏上,我们不会等到所有用例都 review 完才开始写测试脚本,而是采用 迭代式方式:
- 先快速过一遍整体大纲,确保没有明显缺漏;
- 再从高优先级的模块开始,逐个模块 review → 写 Foundry 脚本 → 跑通 → 修正;
- 最后再回头补充边角用例。
这样一来,每完成一个模块,就能立刻验证其稳定性,同时让测试代码与用例设计互相推动,不断完善。