尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

智能合约 AI 审计实战复盘:一个 DeFi 项目的完整安全扫描流程与发现

智能合约 AI 审计实战复盘:一个 DeFi 项目的完整安全扫描流程与发现
📅 发布时间:2026/7/11 20:03:14

智能合约 AI 审计实战复盘:一个 DeFi 项目的完整安全扫描流程与发现

一、从人工审计到 AI 辅助:为何需要重构安全扫描流程

传统智能合约审计依赖人工逐行审查,配合 Slither、Mythril 等静态分析工具。在一个涉及借贷池、质押奖励和治理代币的 DeFi 项目中,代码量超过 8000 行 Solidity,跨 12 个合约文件。人工审计周期通常是 2-3 周,而项目方的上线窗口只有 5 个工作日。

引入 AI 辅助审计不是为了替代人工,而是重构工作流的优先级。核心思路是让大语言模型完成第一轮"粗筛"——识别常见漏洞模式、检查业务逻辑一致性、标记潜在的访问控制缺失——再由审计工程师聚焦在高风险点和业务逻辑深度验证上。

实际落地中,选择了 GPT-4-turbo 结合定制化的 system prompt,配合 Foundry 测试框架做自动化验证闭环。整套流程跑下来,首轮即发现了 3 个中危漏洞和 7 个低危问题,其中 2 个中危漏洞在人工初审阶段被遗漏了。

二、AI 审计流水线架构与核心原理

审计流水线分为四个阶段:代码预处理、分片语义分析、漏洞模式匹配、验证回环。

代码预处理阶段负责展平合约依赖、移除注释干扰、提取函数签名与状态变量。分片阶段将合约按功能模块切割——借贷逻辑、质押逻辑、治理逻辑——分别送入 LLM 的独立上下文窗口。每个分片附带一份"关注清单",列出该模块常见的漏洞类型。

漏洞模式匹配不是简单的正则,而是利用 LLM 的语义理解能力判断代码意图与实际行为的偏离。例如识别"先转账后更新状态"模式的时机,不需要硬编码规则,LLM 可以通过上下文自行判断。

flowchart TD A[Solidity 源码] --> B[代码预处理: 展平+签名提取] B --> C{按模块分片} C --> D1[借贷模块] C --> D2[质押模块] C --> D3[治理模块] D1 --> E1[LLM 语义分析] D2 --> E2[LLM 语义分析] D3 --> E3[LLM 语义分析] E1 --> F[漏洞报告聚合] E2 --> F E3 --> F F --> G{置信度过滤} G -->|高/中置信| H[Foundry 验证脚本] G -->|低置信| I[人工复核队列] H --> J{复现成功?} J -->|是| K[确认漏洞] J -->|否| L[误报过滤] K --> M[生成修复建议] L --> I M --> N[审计报告输出]

系统 prompt 的设计是决定输出质量的关键。不能直接问"这个合约有什么漏洞",而是要明确指令:逐函数分析状态变更顺序、检查外部调用后的状态一致性、标记所有未使用 SafeERC20 的转账操作。提示词中还嵌入了 Foundry 测试模板,要求 LLM 输出可执行的 PoC 代码。

三、核心实现:审计引擎的代码骨架

审计引擎使用 TypeScript 编写,核心逻辑集中在AuditPipeline类中。以下摘取分片策略和 LLM 调用部分。

// audit/pipeline.ts import { OpenAI } from 'openai'; import { flattenSolidity } from './flattener'; import { VulnerabilityReport, AuditShard, ShardConfig } from './types'; /** * 审计流水线:负责代码预处理、模块分片、LLM调用与结果聚合 * 设计决策:采用分片策略而非全量送入,避免上下文窗口溢出, * 同时让每个分片获得独立的分析焦点 */ export class AuditPipeline { private client: OpenAI; private maxShardSize = 6000; // 每个分片最大字符数,预留 prompt 空间 constructor(apiKey: string) { this.client = new OpenAI({ apiKey }); } async audit(contractPaths: string[]): Promise<VulnerabilityReport[]> { const allReports: VulnerabilityReport[] = []; for (const path of contractPaths) { // Step 1: 展平合约,处理 import 和继承 const flattened = await flattenSolidity(path); // Step 2: 按函数粒度分片,确保每个分片不超限 const shards = this.splitIntoShards(flattened, path); // Step 3: 逐分片送入 LLM 分析 for (const shard of shards) { const shardReports = await this.analyzeShard(shard); allReports.push(...shardReports); } } // Step 4: 去重与聚合 return this.deduplicateReports(allReports); } /** * 分片策略:以函数为单位切分,保证语义完整性 * 如果单个函数过大(> maxShardSize),按行继续拆分 */ private splitIntoShards(source: string, filePath: string): AuditShard[] { const shards: AuditShard[] = []; // 使用正则匹配 Solidity 函数定义 const funcRegex = /function\s+\w+\s*\([^)]*\)[\s\S]*?\{/g; const matches = [...source.matchAll(funcRegex)]; if (matches.length === 0) { // 无函数体(如接口文件),整文件作为一个分片 shards.push({ source, filePath, module: 'interface' }); return shards; } let currentShard = ''; let moduleName = this.inferModule(filePath); for (let i = 0; i < matches.length; i++) { const funcStart = matches[i].index!; const funcEnd = i + 1 < matches.length ? matches[i + 1].index! : source.length; const funcCode = source.slice(funcStart, funcEnd); if ((currentShard + funcCode).length > this.maxShardSize && currentShard) { shards.push({ source: currentShard, filePath, module: moduleName }); currentShard = funcCode; } else { currentShard += funcCode; } } if (currentShard) { shards.push({ source: currentShard, filePath, module: moduleName }); } return shards; } /** * LLM 分析单个分片 * 设计决策:system prompt 中明确要求输出结构化 JSON, * 降低后续解析的失败率 */ private async analyzeShard(shard: AuditShard): Promise<VulnerabilityReport[]> { const systemPrompt = this.buildSystemPrompt(shard.module); const response = await this.client.chat.completions.create({ model: 'gpt-4-turbo', temperature: 0.1, // 低温度保证输出一致性 messages: [ { role: 'system', content: systemPrompt }, { role: 'user', content: `分析以下 Solidity 代码片段,按 JSON 格式输出发现的安全问题:\n\n${shard.source}` } ], response_format: { type: 'json_object' } }); return this.parseReports(response.choices[0].message.content, shard); } /** * 构建模块感知的 system prompt * 不同模块的漏洞关注点不同:借贷关注重入和价格操纵, * 质押关注奖励计算精度,治理关注提案时间锁 */ private buildSystemPrompt(module: string): string { const basePrompt = `你是一名智能合约安全审计专家。分析代码时,请严格按以下维度输出: 1. 重入攻击风险 2. 访问控制缺失 3. 整数溢出/下溢 4. 未检查的外部调用返回值 5. 状态变量更新顺序问题 6. 闪电贷攻击向量 7. 预言机操纵风险 输出格式:JSON 数组,每个元素包含 severity(high/medium/low)、title、description、codeSnippet、suggestedFix。`; const modulePrompts: Record<string, string> = { 'lending': basePrompt + '\n特别关注:借贷利率计算精度、清算机制完备性、抵押品价值计算中的价格操纵。', 'staking': basePrompt + '\n特别关注:奖励计算的累计精度损失、unstaking 时间锁、复利计算是否正确。', 'governance': basePrompt + '\n特别关注:提案执行延迟、投票权委托、时间锁机制是否生效。' }; return modulePrompts[module] || basePrompt; } private parseReports(raw: string | null, shard: AuditShard): VulnerabilityReport[] { if (!raw) return []; try { const parsed = JSON.parse(raw); return Array.isArray(parsed) ? parsed.map((r: any) => ({ ...r, filePath: shard.filePath, module: shard.module })) : []; } catch { console.warn(`[AuditPipeline] JSON 解析失败,已跳过分片: ${shard.filePath}`); return []; } } private deduplicateReports(reports: VulnerabilityReport[]): VulnerabilityReport[] { const seen = new Set<string>(); return reports.filter(r => { const key = `${r.filePath}:${r.title}`; if (seen.has(key)) return false; seen.add(key); return true; }); } private inferModule(filePath: string): string { if (filePath.includes('lend') || filePath.includes('borrow')) return 'lending'; if (filePath.includes('stak') || filePath.includes('reward')) return 'staking'; if (filePath.includes('govern') || filePath.includes('proposal')) return 'governance'; return 'general'; } }

验证环使用 Foundry 编写 PoC 测试。LLM 输出的漏洞报告中包含suggestedFix,但更重要的是它输出了触发漏洞的条件描述。审计工程师根据描述编写 Foundry 测试,在本地分叉主网验证。这个环节是人工审计与 AI 输出的交叉点——AI 负责发现,人负责确认。

四、边界与局限性:AI 审计不能替代什么

第一个边界是复杂多合约交互。当漏洞涉及 3 个以上合约的交叉调用时,分片策略天然割裂了调用上下文,LLM 只能看到局部状态。在实际项目中,一个涉及闪电贷攻击的漏洞跨越了借贷合约、预言机合约和路由合约,AI 没有识别出来,最终由人工发现。

第二个边界是业务逻辑深度。AI 可以判断transfer后balance是否更新,但无法判断抵押率 80% 是否合理,因为这个数值需要结合市场波动率、清算滑点和协议风控策略综合决策。业务逻辑的正确性验证,仍然是审计中最依赖经验的部分。

第三个边界是数学证明类漏洞。涉及形式化验证的漏洞(如某 AMM 池的不变量是否在所有状态下成立),当前的 LLM 不具备严格的数学推理能力,误报率和漏报率都很高。

一个值得注意的发现:对同一个分片重复调用 3 次取交集,可以将误报率从约 35% 降低到约 12%,但漏报率会轻微上升。工程上需要在覆盖率与精确度之间做 trade-off,建议用高温度参数做多次采样后再取交集,作为提高准确率的手段。

五、总结

这次实战复盘验证了一个核心观点:AI 在智能合约审计中最适合的定位是"增强器"而非"替代者"。它能显著加速初筛阶段,将人工审计的精力集中到高风险、高复杂度的漏洞上。

从效率数据看,AI 辅助流程将首轮审计时间从预计的 14 天压缩到 5 天,发现了人工遗漏的 2 个中危漏洞。但同时,跨合约复杂交互漏洞和业务逻辑合理性判断,仍然是 AI 的明确短板。

工程化落地的关键点有三:一是分片策略要与合约模块边界对齐,避免割裂调用关系;二是 system prompt 的领域特化程度直接决定输出质量;三是必须建立验证闭环,LLM 输出不做人工确认绝对不能直接作为结论。下一阶段计划引入 RAG 检索已有漏洞库,让 LLM 在分析时能参考历史相似案例。

相关新闻

  • VSCode TypeScript 调试配置:5步实现源码映射与断点调试
  • 终极指南:如何用一键重置工具快速修复Windows更新问题
  • 数据库注入攻击的AI防御:用深度学习检测SQL注入的变种与绕过

最新新闻

  • 国内环境下的AI图像生成技术实现与合规应用指南
  • HarmonyOS NavPathStack 实战:中式美食详情页怎么记住用户从搜索、收藏还是推荐进来
  • openeuler/ccb本地构建教程:local-build与local-rebuild命令实战
  • 咸安南部宴席测评|升学生日宴高性价比门店推荐 - 资讯快报
  • Armbian上部署Pi Agent:ARM小板AI代理实战指南
  • CHTML 1.2.0 变量命名工具:4种集成方式与96种命名规则实战解析

日新闻

  • OpenClaw本地部署:一键直连微信的私有化AI Agent实战指南
  • Kubernetes 系列【10】控制器:ReplicaSet(副本集)
  • 怎么寄快递才能便宜呢?2026年7月寄快递省钱攻略 - 生活情报姬

周新闻

  • 基于YOLOv12的番茄成熟度智能检测系统开发
  • 终极RimWorld模组管理指南:用RimSort告别模组冲突烦恼
  • AI Agent框架开发:从理论到实践的完整指南

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号