本文内容
智能合约审计前检查清单:30 个问题
Wavect 不把这份清单称为独立审计。它是面向 EVM 合约的审计前加固审查。清单可以暴露证据缺口和常见风险,但不能证明合约安全、经济机制可靠、集成正确,或在每条链和每次部署中都安全。
审查范围应限定为准确的源代码、编译器、设置、依赖、生成的 bytecode、proxy 模式、链、地址、角色、资产、集成、部署脚本和运营流程。应使用当前 Solidity 文档、已知编译器缺陷、威胁模型和更全面的验证标准。官方的 Solidity 安全注意事项、已知缺陷列表、OWASP 智能合约安全验证标准以及 EEA 当前的 EthTrust Security Levels 规范列表都是实用输入。
即将接受审计?
预约免费咨询应如何使用这份清单?
每个问题都应提供代码引用、测试、工具结果、部署产物、运营控制或明确的风险接受。通过只意味着约定的证据支持已限定的要求,不意味着整个类别安全。重大失败应修复、移出范围,或由获授权负责人接受,并记录后果、补偿控制与后续行动。
静态分析、fuzzing、不变量、形式化方法、fork 测试和人工审查能发现不同问题。不存在适合所有代码库的固定 seed 数量或零告警规则。应定义重要属性与覆盖范围,分类误报,保存工具版本和配置,并向独立审查者说明残余不确定性。
类别 1:规范与工具链(问题 1 至 5)
- 预期行为是否有规范?识别资产、参与者、权限、信任假设、状态转换、不变量、失败模式和禁止结果。
- 构建能否复现?固定已发布编译器、EVM 目标、optimizer 与 IR 设置、依赖、生成器和命令,并比较已部署 bytecode 与元数据。
- 是否检查编译器风险?对照当前机器可读缺陷列表和升级指南检查所选版本。
- 是否处理自动化发现?运行适当的编译器检查、linter 与 analyzer,分类每项重大结果并记录合理的抑制。
- 测试是否针对属性?结合示例、边界、负向用例、fuzzing、不变量、集成,以及在值得投入时采用差分或形式化检查。
类别 2:权限与生命周期(问题 6 至 10)
- 是否映射全部特权操作?记录谁能暂停、升级、铸造、销毁、扣押、配置、提款、救援或更换依赖。
- 控制是否与风险匹配?评估密钥托管、法定人数、签名者独立性、timelock、紧急权限、活性、恢复和运营负担,而不是一概禁止某类账户。
- 授予、转移、撤销与放弃是否安全?测试预期与误操作转换、待处理状态、签名者丢失和最后管理员路径。
- 初始化与部署是否受保护?防止未授权初始化、抢跑、错误参数或地址,以及未经验证的 implementation 或 proxy 状态。
- 紧急控制是否有边界?定义触发条件、权限、影响、沟通、证据、恢复或取消暂停,以及控制本身失效时的行为。
类别 3:资产、算术与经济机制(问题 11 至 15)
- 数值域是否明确?检查单位、精度、舍入方向、边界、类型转换、有符号值和有依据的
unchecked块。 - 是否验证代币假设?按具体集成处理小数位、返回值、callback、转账费用、rebasing、暂停、blocklist 和非标准行为。
- 是否测试价值守恒属性?定义存款、提款、费用、奖励、债务、抵押和尘埃在每次状态转换中如何对账。
- 预言机与市场假设是否有边界?测试新鲜度、操纵成本、小数转换、sequencer 或市场中断、fallback 和清算。
- 是否建模对抗性经济行为?检查排序、MEV、闪电流动性、griefing、治理捕获、激励循环和纯代码检查可能遗漏的盈利状态。
类别 4:外部调用与可组合性(问题 16 至 20)
- 外部交互能否重入?分析同函数、跨函数、跨合约、只读、hook、代币和 callback 路径,而不是机械依赖单个 guard。
- 状态变更与回滚是否正确?使用 checks-effects-interactions 或其他有依据的设计,并测试部分失败和嵌套调用。
- 是否按实际接口解释返回数据?按所需合约处理成功、revert、空数据、畸形数据和非标准代币,而不是通用长度规则。
- 依赖能否阻止进展?测试不可用、revert、耗 gas、恶意、暂停或升级后的外部合约,并定义隔离或恢复。
- 授权与签名是否安全?审查 allowance 竞态、nonce 与 replay 域、期限、链和合约绑定、签名可塑性与智能账户验证。

"只有当每个回答都指向证据与残余风险时,审计前清单才有价值。一排绿色勾选不是安全证明。"
类别 5:升级与存储(问题 21 至 25)
- 升级模型是否明确?记录 proxy 类型、implementation 发现、升级权限、延迟、回滚假设、初始化和兼容边界。
- 是否验证存储兼容性?使用理解所选模式、继承、packing 和 namespaced storage 的工具比较布局,不要假设固定 gap 大小适合所有合约。
- Implementation 合约是否受保护?对适用的 proxy 模式锁定 implementation 初始化,并验证所有 parent initializer 与 reinitializer。使用该技术栈时遵循当前的 OpenZeppelin 升级指南。
- 授权是否符合模式?测试谁能选择和执行升级、通过哪个 proxy 或治理路径,并包括取消与权限被攻破的场景。
- 是否演练真实迁移?填充代表性状态,通过生产路径升级,验证不变量与集成,测试失败和恢复并保留产物。
类别 6:可用性、部署与运营(问题 26 至 30)
- 用户控制的增长能否超过执行限制?限制循环与批处理或分页,并针对目标链当前规则测试现实最坏情况。
- Gas 或 revert 能否导致拒绝服务?分析 push payment、callback、外部调用、refund、批处理原子性和 griefing,不依赖任意的区块 gas 百分比。
- 部署是否确定且经过验证?检查参数、salt、library、owner、角色、implementation、源码验证、chain ID、资金和交接。
- 监控与响应是否就绪?定义事件、不变量或余额监控、告警、负责人、密钥泄露响应、暂停标准、沟通和证据保留。
- 上线与退出风险是否受控?设置价值与速率限制、分阶段上线、依赖与链应急方案、用户恢复、升级或不可变性影响和退役。
为什么不把未完成代码直接交给审计方?
当需求、构建产物、测试、已知工具发现、权限和部署计划一致时,独立审查时间通常更有价值。这不支持通用日费率、承诺减少多少发现,或保证更便宜、更快上线。审计范围、复杂度、团队、复测、报告政策和排期都会不同。
应询问哪些内容必须冻结、需要哪些产物、如何处理变更与复测、覆盖哪些链与集成,以及如何分类发现。以书面形式比较相同范围。外部审查者必须能自由质疑审计前审查的假设。
由谁负责签字?
为每个问题指定负责的技术 owner,并为每项被接受的重大风险指定获授权的业务或治理 owner。交接中应包含 commit 与 bytecode 引用、测试与工具证据、部署配置、未解决假设和变更日志。独立审查者决定依赖这些材料的程度。
审查后的代码与运营变更可能让证据失效。应定义哪些变更需要重新分析或审计,并让部署依赖当前获批产物,而不是过时清单。
最终思考
这 30 个问题从规范、工具链、权限、经济机制、外部调用、升级、可用性、部署和运营方面组织审计前加固。它们既不穷尽风险,也不是安全证明。应限定到准确系统,并结合当前标准、威胁建模、适当的自动与人工分析以及独立审查。
解决每项重大问题,或记录由获授权人员作出的风险接受、后果和控制。保留可复现的构建与部署证据,演练高风险迁移和失败路径,并定义哪些后续变更会使审查失效。目标是形成更清晰、可测试的审计交接,而不是保证发现数量或上线日期。