第1章:安全审计与合约——如何看懂审计报告
说实话,我见过太多人拿到审计报告后直接翻到最后一页看结论。
「通过审计」四个字就让他们放心了。
嗯,这其实挺危险的。审计报告不是一张「安全通行证」,它更像是一份体检报告。你得看懂每个指标,才知道自己到底有没有病。
1.1 审计报告的结构
一份标准的审计报告,通常包含这几块内容:
- 项目概览:审计了哪些合约、什么版本、用什么工具
- 风险分级:Critical(致命)、Major(严重)、Medium(中等)、Minor(轻微)
- 发现详情:每个漏洞的描述、影响、修复建议
- 审计结论:最终评级和备注
我个人习惯,先看风险分级那一页。如果出现 Critical 级别的漏洞,哪怕只有一个,这个项目我基本就不碰了。为什么?因为致命漏洞往往意味着资金可以直接被盗。
重点提醒:审计报告里的「通过」不代表「没问题」。它只代表「在审计时,没发现已知漏洞」。新漏洞每天都在被发现。
1.2 常见合约漏洞——重入攻击
重入攻击,DeFi 世界里最经典的漏洞之一。2016 年的 The DAO 事件,就是被这个漏洞搞垮的。
它的原理其实很简单:
合约 A 调用合约 B 转账,合约 B 在收到钱后,又回调合约 A 的函数。如果合约 A 在转账后没有更新状态,那合约 B 就可以反复「提款」。
看个简化版的例子:
// 有漏洞的合约
function withdraw(uint amount) public {
require(balances[msg.sender] >= amount);
(bool success, ) = msg.sender.call{value: amount}("");
require(success);
balances[msg.sender] -= amount; // 状态更新在转账之后
}
发现问题了吗?转账在前,余额更新在后。攻击者可以在 receive 函数里再次调用 withdraw,此时余额还没扣,就能反复提走所有钱。
避坑指南:我曾经审计过一个机枪池合约,团队把「先转账后更新」写成了「先更新后转账」的反面——嗯,就是上面那个漏洞。幸好发现得早,不然上线第一天就得被薅秃。
修复方法也很简单:先更新状态,再转账。或者用 OpenZeppelin 的 ReentrancyGuard 加个锁。
1.3 闪电贷攻击
闪电贷,DeFi 里最「神奇」的发明。你可以在一个交易里借出几千万美元,只要在同一个区块内还回去就行。
听起来很酷对吧?但攻击者也觉得它很酷。
闪电贷攻击的核心逻辑:
- 借一大笔钱,用来操纵某个池子的价格
- 利用价格偏差,在另一个协议里套利或清算
- 还掉闪电贷,利润落袋
我见过最典型的案例是:攻击者用闪电贷借出大量 ETH,在 Uniswap V2 里把某个代币的价格砸到极低,然后去另一个借贷协议里用低价抵押品借出所有资产。整个过程就一个交易,几秒钟完成。
我的经验:检查一个协议是否容易受到闪电贷攻击,核心看两点——
- 价格预言机是否使用 TWAP(时间加权平均价格)?
- 关键计算是否依赖链上瞬时价格?
如果答案是「瞬时价格 + 无 TWAP」,那基本就是靶子。
1.4 开源代码的检查要点
很多人觉得「开源 = 安全」,其实不一定。代码开源了,但没人看,或者看不懂,那跟没开源一样。
我个人检查一个开源项目时,会重点关注这几个地方:
| 检查项 | 具体内容 | 为什么重要 |
|---|---|---|
| 权限控制 | owner 能不能随意 mint?有没有 timelock? | 防止「rug pull」 |
| 价格计算 | 用的是 Chainlink 还是池子瞬时价格? | 防止闪电贷操纵 |
| 数学运算 | 有没有用 SafeMath 或 Solidity 0.8+ 的溢出检查? | 防止整数溢出 |
| 外部调用 | call/delegatecall 有没有限制目标地址? | 防止恶意合约 |
你想想看,如果一个项目的 owner 地址可以随时 mint 无限量的代币,那审计报告写得再漂亮也没用。这就是所谓的「中心化风险」。
一句话总结:审计报告是工具,不是信仰。看懂它,你才能判断一个项目值不值得投入。
知识体系图
下面这张图,帮你理清本章的核心逻辑:
嗯,这一章的内容就到这里。记住我说的:别只看结论,要看细节。下一章我们会聊「如何识别蜜罐合约和貔貅盘」,那才是真正考验眼力的地方。