跳到正文

如何阅读智能合约审计报告

智能合约审计是对指定代码、构建、部署、假设和性质进行的有限审查;其发现与修复必须同线上系统逐项核对。

更新于

仅供教育参考,不构成投资或安全建议。审计报告、工具结果、已解决的发现或匹配的源文件,都不是认证、保险、赔偿承诺,也不能证明线上部署是安全的。

直接答案

智能合约审计是在明确期间内,对指定需求、源代码、构建输入、部署逻辑和安全假设进行的有限审查。审计人员运用相互补充的方法识别缺陷、展示利用路径、评估影响并检查拟议修复。结论只适用于报告所述的审计快照和证据。

快照应锁定代码仓库与提交或目录树哈希、子模块与依赖锁、编译器及设置、生成代码、部署脚本、目标链和地址、代理、实现或信标、构造器或初始化器数据、库、管理员、时间锁,以及某一区块或时间点。明确排除项与纳入项同样重要:前端、keeper、预言机、跨链桥、治理流程或链下签名者即使不在审计范围内,也可能主导风险。

审计需要威胁模型和规范。应识别资产、参与者、特权角色、信任边界、攻击者能力、排序与重组假设、外部依赖、状态转换,以及精确的安全性和活性性质。缺少单位、前置条件、量词和例外的不变量,可能完美地证明或测试了错误行为。

应维护四本账:范围、构建与部署身份账;需求、威胁与不变量账;发现、证据与复测账;残余风险、接受与披露账。报告没有 critical 发现不等于安全认证,标为 resolved 的发现不一定已经部署,而证明也只覆盖其编码的性质、模型和假设。

运作机制

人工审查追踪架构、资金流、跨函数状态和经济意图。静态分析寻找模式与数据流,但可能产生假阳性和假阴性。单元、集成、分叉和差分测试比较具体行为。有状态模糊测试与不变量测试探索生成的调用序列,但结果取决于处理器、选择器、种子、语料库、运行次数、深度和建模环境。

符号执行与形式化验证可在受支持的语义和假设下确立特定断言。求解器返回 unknown、超时或遇到不支持的行为,都不构成证明。即使性质已获证明,也可能遗漏预言机经济机制、治理、部署配置、链上行为,或团队真正意图实现的需求。规范与解释仍由人工审查负责;AI 生成的观察并非独立的保证方法。

每项发现都应指出受影响的制品与部署、前提条件、最小证明、利用路径、可达性、所需权限、攻击者资本、可重复性、经济影响、严重度标准和修复建议。可利用性或发生可能性与影响是两个不同维度。理论最大值、漏洞名称或工具标签不能证明可执行损失。

openacknowledgedrisk acceptedpartially fixedresolvedretested 等状态并非通用标准。可信的结项应把原发现绑定到精确修复提交,记录已测试的变更路径与相邻路径,并说明由谁在何时复测了什么。已接受风险仍然是风险,有限复测不会把原审计范围扩展至所有新增代码。

可升级部署需要专项核对。应解析代理、实现或信标及管理员插槽;验证初始化器与再初始化器行为、实现合约锁定、存储兼容性、升级授权、时间锁或紧急绕过、迁移与回滚。从被审构建中复现创建字节码和运行时字节码,再在每条链上比较链接库、参数、角色和已初始化状态。

最终报告应说明修订版、审计人员和日期、精确范围、方法与配置、限制、发现、证据、修复状态、未解决或已接受风险和披露条款。发布后应监控实现哈希、角色、参数、依赖与事件。任何重大变更都会产生需要复审的新差异;附在旧报告上的徽章不会自动跟随未来代码。

请按以下流程执行:

  1. 冻结审计清单:代码仓库、提交、依赖、编译器与设置、生成和部署代码、链、地址、代理栈、参数、区块、报告修订版、纳入项与排除项。
  2. 定义资产、参与者、特权角色、信任边界、攻击者能力、生命周期、排序与活性假设、外部依赖和可度量不变量。
  3. 复现构建并梳理架构、存储、数据、资金和控制流;核对源码、制品、库、创建与运行时字节码、初始化器、角色和线上部署。
  4. 组合开展人工、静态、单元、集成、分叉、差分、模糊、不变量、符号或形式化方法,并记录工具版本、配置、种子、语料库、覆盖率、超时和未知结果。
  5. 记录每项问题的受影响制品、前提、证明、可利用性、影响、严重度方法、部署暴露、建议及保密证据,不把工具标签当作判断。
  6. 冻结修复提交并复测问题、相邻路径和不变量;验证代理存储、初始化、迁移、回滚、可复现构建和部署收据,再赋予有证据支持的状态。
  7. 发布范围、方法、限制和残余风险;将被审制品同每条线上链核对,并随系统变化持续更新监控、披露、事件响应和漏洞赏金控制。

示例

  • 金库通胀路径需要完整账本。 攻击者通过首存分支存入 1 asset 并获得 1 share,随后捐赠 1,000,000 assets;总量变为 1,000,001 assets1 share。受害者存入 500,000 assets,不安全的向下取整计算得到 floor(500,000 * 1 / 1,000,001) = 0 shares。若系统接受零份额存款,金库将持有 1,500,001 assets;攻击者赎回全部资产并获利 500,000 assets,其投入为 1,000,001-asset。若实现会在零份额时回退交易,则这条具体损失路径不会执行。
  • 文件覆盖率不等于部署覆盖率。 清单包含 24 source units4 deployment scripts3 keeper services,合计 31 items。审计纳入 20 source units2 scripts,所以按数量计算的覆盖率为 22 / 31 = 70.96774194%;其余 9 items 被排除。如果线上代理指向由排除单元构建的实现,则该线上实现的覆盖率是 0%,即使标题数字是 70.96774194%
  • 模糊测试观察不构成不存在性证明。 一次有状态测试执行 2,000 sequences * 64 calls = 128,000 calls;不变量在 3 sequences 中失败,占生成序列的观察比例 3 / 2,000 = 0.15%。修复后,10,000 sequences * 64 calls = 640,000 calls 未出现失败。这表示该语料库中为零,而非证明;在独立且生成器稳定的教学假设下,三倍法则给出的近似 95% 上限是每个生成序列 3 / 10,000 = 0.03%
  • 发现结项与部署身份彼此独立。 报告有 12 findings2 critical3 high4 medium3 low。复测关闭 2 + 2 + 3 + 2 = 9 项,按数量计算的结项率为 9 / 12 = 75%;仍有一项高、一项中和一项低未关闭。被审运行时哈希为 H1,但线上实现是 H2,因此无论结项率如何,部署验证都失败。换成精确的 H1 并匹配代理插槽、初始化器和角色,只能证明所检查区块时点的身份一致。

风险

  • 代码仓库、提交、子模块或生成源码陈旧或含糊。
  • 编译器版本、优化器设置、库或依赖没有锁定。
  • 部署脚本、构造器数据、初始化器或 CREATE2 salt 被排除。
  • 审查了错误的链、地址、代理、信标或实现。
  • 源码、制品、创建字节码和运行时字节码无法相互核对。
  • 威胁模型遗漏参与者、权限、资产或信任边界。
  • 规范或不变量使用错误的单位、前置条件或例外。
  • 管理员、守护者、时间锁、暂停、升级或迁移路径被遗漏。
  • 预言机、代币、跨链桥、keeper、治理或链上假设失效。
  • 静态分析产生未经分流核验的假阳性。
  • 人工审查、测试或模糊测试遗漏未生成的路径。
  • 模糊测试工具、选择器、种子、语料库、深度或状态模型有偏。
  • 求解器超时、不支持的语义或 unknown 被误认为证明。
  • 正确的证明形式化了错误需求或不完整系统。
  • 严重度依据漏洞名称,而非可利用性和影响。
  • 理论风险价值被误认为可达损失或攻击者利润。
  • 修复引入相邻回归或破坏经济不变量。
  • 代理存储、初始化器、升级或迁移破坏线上状态。
  • 已接受、未关闭或仅部分修复的问题被“通过审计”徽章掩盖。
  • 报告被视为保险、认证、赔偿承诺或永久覆盖。

常见误区

  • “没有严重发现就说明合约安全。” 这只描述有限范围、时间与方法下报告的发现,并非所有可能缺陷。
  • “测试覆盖率高或模糊测试零失败,就证明没有漏洞。” 这些只是对选定代码和生成路径的度量,不是不存在性证明。
  • “形式化验证证明整个协议安全。” 它只证明模型在假设下编码的性质;规范和周边系统仍可能有误。
  • “已解决意味着所有线上部署都已修复。” 结项需要独立复测,并逐一核对每个部署的构建、字节码、代理、参数与角色。
  • “知名审计机构会保证赔偿或未来升级。” 责任取决于审计合同,用户未必是受益人,后续代码或配置不在旧快照范围内。

相关主题

来源

导航

搜索知识库...