GLM 5.3 审计借贷协议健康因子与抵押清算:Compound 分叉盘算术下溢漏洞挖掘

发布时间:2026/10/12 12:16:46

GLM 5.3 审计借贷协议健康因子与抵押清算:Compound 分叉盘算术下溢漏洞挖掘 在去中心化借贷协议的历史长河中Compound v2 的源码架构无疑是整个 DeFi 乐高世界被“分叉Fork”最多的代码资产之一。从各种小众公链上的初代借贷产品到各类结合了新兴质押衍生品LST/LRT的结构化杠杆协议其核心结算逻辑几乎都流淌着 Compound 经典双代币模型cToken 与 Comptroller的血脉。然而开源代码的繁荣背后潜藏着极其巨大的安全隐患。很多分叉团队为了支持自身独特的代币经济学往往会在不经意间对底层的核心数学库进行“微调”将老旧的 Solidity 0.5.x / 0.6.x 代码强行升级到 Solidity 0.8.x并在为了节省 Gas 的冲动下大量包裹非安全的unchecked { ... }作用域在支持非标准精度代币如 6 位精度的 USDC/USDT、8 位精度的 WBTC 与 18 位精度的 WETH时粗暴地魔改利息累加因子Borrow Index与抵押物扣押计算公式未能深刻理解抵押品清算过程中极端行情下的算术下溢Arithmetic Underflow与精度截断Precision Truncation导致健康因子计算产生荒谬的数值翻转。这种由于多代币精度不对齐和代数运算顺序错误引发的漏洞通常隐藏在数百行复杂的指数折算库中传统的静态语法扫描工具几乎无法识别。本文将手把手带你使用GLM 5.3智能合约审计模型系统还原一起典型的 Compound 分叉盘精度截断漏洞并拆解工业级的防御审计指南。一、Compound 借贷流动性评估的核心数学骨架在 Compound 的风险控制中用户的借贷安全性由审计核心合约Comptroller中的getAccountLiquidity方法全权裁决$$\text{账户净流动性 (Liquidity)} \sum \left( \text{有效抵押物价值} \times \text{抵押因子} \right) - \sum \left( \text{借出负债总价值} \right)$$有效抵押物价值将用户持有的 cToken 按照底层汇率Exchange Rate折算为原生资产再乘以预言机喂价Oracle Price负债总价值用户未偿还的借款本息总和乘以对应代币价格安全边界若 $\text{Liquidity} 0$账户健康允许继续借款或提现若 $\text{Liquidity} 0$账户发生赤字Shortfall触发抵押品被清算。二、真实致命缺陷多精度换算下的截断与下溢陷阱让我们来看一段在分叉项目中极其常见的魔改版清算抵押物扣押函数liquidateCalculateSeizeTokens// SPDX-License-Identifier: MIT pragma solidity 0.8.26; contract VulnerableCompoundForkMath { // 假设预言机统一返回 18 位精度的 USD 价格 // priceBorrowed: 被偿还负债代币的单价 (18 位精度) // priceCollateral: 被没收抵押物代币的单价 (18 位精度) // actualRepayAmount: 清算者偿还的负债代币真实数量 function calculateSeizeTokens( uint256 priceBorrowed, uint256 priceCollateral, uint256 exchangeRateCollateral, uint256 actualRepayAmount, uint8 collateralDecimals, uint8 borrowedDecimals ) public pure returns (uint256 seizeTokens) { // 开发者试图对不同代币的小数位差进行手动对齐 // 致命错误运算顺序颠倒先进行了小整数除法引发严重的精度截断归零! uint256 decimalAdjustment 10 ** (18 collateralDecimals - borrowedDecimals); // 错误实现的抵押品扣押比率: // 原意为: (repayAmount * priceBorrowed * 1.05) / priceCollateral // 但开发者在中间提前除以了 priceCollateral且未对大数进行前置放大: uint256 priceRatio (priceBorrowed * 1e18) / priceCollateral; // 灾难发生当抵押物单价极高如 WBTC $60,000而借出代币单价极低如 1 枚小币 $0.05时: // priceBorrowed * 1e18 / priceCollateral 在数值上由于向下截断结果直接变成 0! // 导致计算出的 seizeTokens 瞬间被清零! uint256 seizeAmount (actualRepayAmount * priceRatio) / decimalAdjustment; seizeTokens (seizeAmount * 1e18) / exchangeRateCollateral; } }2.1 精度截断引发的协议瘫痪与坏账穿仓在上述有缺陷的代码中当借款人借入低价垃圾代币、抵押高价值资产如 WBTC发生资不抵债时外部清算机器人尝试替其还款清算调用calculateSeizeTokens计算其应当分得的抵押物由于priceRatio计算过程中分子被分母无情碾压截断为0清算者拿到的seizeTokens变成了0清算者付出了还款成本却分不到任何抵押物回报导致全网没有任何理性套利者愿意替该用户执行清算坏账随着市场暴跌无限制失控放大最终彻底击穿借贷池本金导致全体无辜存款人资金遭遇永久挤兑封锁。三、利用 GLM 5.3 执行上下文二阶交叉审计面对此类晦涩的代数公式我们向针对以太坊 DeFi 协议微调过的GLM 5.3模型输入如下审计提示词链你是一名负责以太坊借贷协议数学安全的资深审计专家。 请深度审查以下来自 Compound v2 分叉合约的清算公式 1. 检查是否存在【先除后乘Division Before Multiplication】引发的精度截断到 0 的风险 2. 分析当借入代币价格远低于抵押品价格时如 10^-4 倍中间变量是否存在算术下溢或计算归零 3. 推演清算者在极端行情下无法获得抵押物份额导致协议坏账的攻击路径 4. 给出基于定点数大数优先相乘Multiplication Before Division的工业级加固代码。3.1 GLM 5.3 的核心审计输出GLM 5.3 展现出了极高的代数洞察力精准指出了痛点“漏洞根因在于priceRatio的独立计算违背了 EVM 定点数运算的基本准则——必须严格保持‘先乘后除’以维持最大有效精度。在被清算资产与抵押品价格跨越多个数量级时(priceBorrowed * 1e18) / priceCollateral发生了致命的向下整数截断Integer Truncation to Zero。这使得清算奖励被置零打破了借贷协议依靠清算罚金维系流动性的博弈平衡。该漏洞属于 P0 级坏账死锁风险。”四、工业级防御定点数先乘后除与全量精度对齐在 Solidity 中处理不同精度的代币折算绝对不能把中间比率拆开计算必须将所有的分子在进入除法之前统一乘以大数Scale Factor并将其合并为一个单一的大分数// SPDX-License-Identifier: MIT pragma solidity 0.8.26; contract SecureCompoundForkMath { uint256 private constant EXP_SCALE 1e18; uint256 private constant LIQUIDATION_INCENTIVE 105e16; // 1.05 代表 5% 清算奖励 error TruncationToZeroDetected(); /// notice 安全计算清算应扣押的 cToken 份额 function calculateSeizeTokensSafe( uint256 priceBorrowed, uint256 priceCollateral, uint256 exchangeRateCollateral, uint256 actualRepayAmount, uint8 collateralDecimals, uint8 borrowedDecimals ) public pure returns (uint256 seizeTokens) { // 1. 严格统一分子先乘后除将实际还款额、清算奖励因子、借出代币价格连乘 // 同时乘以前置的小数位补偿因子确保整个乘积在大数域中进行 uint256 numerator actualRepayAmount * LIQUIDATION_INCENTIVE * priceBorrowed; // 2. 统一分母将抵押物价格与基础精度连乘 uint256 denominator priceCollateral * EXP_SCALE; // 3. 补充代币精度差额的幂次补偿 if (collateralDecimals borrowedDecimals) { numerator numerator * (10 ** (collateralDecimals - borrowedDecimals)); } else { denominator denominator * (10 ** (borrowedDecimals - collateralDecimals)); } // 4. 执行单次终极除法将有效精度损失降至极限物理底线 uint256 seizeAmount numerator / denominator; if (seizeAmount 0 actualRepayAmount 0) { revert TruncationToZeroDetected(); } // 5. 按照抵押品汇率折算为最终待扣押的 cToken 数量 seizeTokens (seizeAmount * EXP_SCALE) / exchangeRateCollateral; } }五、安全审计员复核 CheckList在审查任何借贷协议的数学库时审计员必须强制核对以下四条红线先乘后除铁律Multiplication Before Division所有的代数公式中除法指令/必须且只能出现在整个计算表达式的绝对最末端严禁在中间步骤中保存未放大的除法商数多代币精度单元测试必须包含极限边界单元测试用例必须覆盖“18 位抵押品 6 位负债代币”以及“6 位抵押品 18 位负债代币”的双向场景并且输入单价必须包含从 $$0.000001$ 到 $$100,000$ 的极端价格落差非零扣押断言Non-zero Seize Check在清算函数的出口必须对算出的抵押物份额进行显式非零断言require(seizeTokens 0)绝不允许清算者在偿还债务后得到空响应警惕 unchecked 滥用在 Solidity 0.8 中除非有极其完备的形式化验证证明该减法绝对不可发生下溢否则严禁在流动性评估主流程中使用unchecked块强行跳过编译器的默认溢出防护。
延伸阅读

更多相关文章

2026/10/12 12:16:46

VSCode+Mermaid classDef:让技术文档图表样式可维护

做技术文档这件事,我这些年最大的感受就是:图的维护成本往往比文字高得多。以前画架构图,用一个独立的绘图文件,负责人一离职,图就没人会改了;后来用独立工具画完截图贴进Markdown,文字改了图对…

2026/10/12 12:11:45

FPGA设计中锁存器与触发器的区别:从Verilog推断到时序分析实战

第一次在综合报告里看到“Latch Inferred”这个警告时,我根本没放在心上。直到有一块板子在接口抓数时出现偶发读取错误,查了整整一天才定位到一个小模块——代码里某个电平使能的赋值漏写了 else,综合工具默默补了一个锁存器,把整…

2026/10/12 13:11:55

GPT-6模型家族选型与降本增效:工程化实践指南

1. 项目概述 1.1 核心需求解析 GPT-6 模型家族选型这件事,最近几乎成了每个做 AI 应用的团队绕不开的坎。我们团队从 GPT-6 系列开放首批接口就开始跟进,经历了从“无脑选最大”到“按场景精细匹配”的完整过程,踩过的坑、沉淀下来的方法&am…

2026/10/12 13:11:55

Java数组双循环与去重逻辑:从原理到方法封装实战

不用急着去背“双循环”“去重”“多分支”“方法”这些孤立的知识点。很多Java基础明明都见过,一写代码就乱,说到底是因为没有把“循环怎么控制”“逻辑怎么分支”“代码怎么封装”这三件事串成一条线。这篇文章就从数组的双循环开始,把去重…

2026/10/12 13:11:55

大项目手足无措?用责任域切片、价值里程碑与最小契约破局

1. 大项目恐惧不是能力问题,而是系统性认知错位“手足无措”这四个字,我第一次在某跨平台系统重构项目启动会上听到时,坐在会议室第三排的A同学突然把笔捏断了。他不是不会写代码,也不是没做过模块——他刚独立交付过一个用户量20…

2026/10/12 13:11:55

产品交付控制程序编写指南:从流程梳理到落地避坑

简介:面向核电产品交付管理场景的质量体系规范文档,核心价值在于明确从完工到客户接收全过程的控制要求,适用于直发件、见证件、档案材料、备品备件、专用工具及完工文件等各类核电产品。文档按目的、范围、编制依据、职责、程序说明、形成文…

2026/10/12 13:06:54

ARM64离线部署Harbor 2.13.1:避坑指南与实战

简介:这是一份面向ARM架构服务器环境的Harbor容器镜像仓库离线部署包,对应Harbor 2.13.1版本,适合在无法访问外网或网络受限的国产化、信创及ARM服务器场景中搭建私有镜像仓库的运维与开发人员使用。压缩包共包含6个文件,以sh安装…

2026/10/11 0:02:13

Python调用Gemini Structured Outputs实现工单路由门禁

客服工单最怕的不是模型“答错一句话”,而是它给出一段看起来合理的说明,程序却从中猜错优先级。通俗做法是:要求模型只交 JSON(JavaScript Object Notation,轻量数据格式),再让代码验证它。Gem…

2026/10/12 12:01:26

Spring Boot超市进销存系统毕设实战:从需求拆解到答辩通关

最近带的一个学生项目组里,有A同学跑来问我:选什么毕设题目最稳妥,既能让评审老师觉得工作量够,又不会在答辩时被问到语无伦次。我第一反应就是推荐基于Spring Boot的超市仓库管理系统——也就是超市进销存系统。这个题目乍一看平…

2026/10/12 12:54:07

Flutter StatefulWidget 生命周期核心解析

很多刚开始接触 Flutter 的朋友,在看完一堆“Hello World”和基础组件之后,大概率都会撞上同一堵墙:StatefulWidget 里那堆 initState、build、dispose 方法,到底什么时候被调用?为什么顺序是那样?在里面到…

2026/10/12 0:04:22

绝缘子缺陷检测数据集清洗与工业级训练实战指南

简介:本资源是面向电力AI研发人员、工业视觉工程师及智能巡检系统开发者的绝缘子缺陷检测专用YOLO格式数据集,解决无人机航拍场景下绝缘子破损、污闪、积雪等9类典型缺陷的精准识别与定位难题。数据集共2139张真实巡检图像(含训练/验证/测试集…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑