仅19.4%被判定安全:Uniswap v4 Hook恶意攻击向量与检测方法解析
导语:近期,Robinhood Chain 热潮吸引大量用户在其链上使用 Uniswap 交易。有用户发现,某个 Uniswap v4 池子显示 0% 手续费,报价甚至低于市场最优价几个基点,遂将其选为最佳路由。但交易完成后,实际收到代币比报价少近 1%。链上数据显示,损失并非正常滑点,而是隐藏在 Hook 合约中的“暗税”——Hook 通过 afterSwapReturnsDelta 权限在交易结算前截留部分代币。
0x Protocol 对 6 条链上的 84,163 个 Uniswap v4 Hook 进行静态分析、动态分析和实际成交观察后发现,仅 19.4% 的 Hook 被判定为安全,54.2% 被归类为恶意,另有 26.4% 存在疑似恶意行为。Beosin 安全团队对 Uniswap v4 Hook 的攻击向量进行解析,帮助用户和开发者理解其中可能存在的恶意行为。
一、Uniswap v4 Hook 机制与风险位置
在 Uniswap v4 中,流动性池由 PoolManager 统一管理。Hook 合约可在池子初始化、添加流动性、移除流动性、Swap 和 Donate 等关键节点插入自定义逻辑,例如修改交易费、交易前后余额和结算逻辑。其安全风险主要集中在以下位置:Hook 返回异常余额变化;Hook 在回调中调用外部合约;Hook 读取瞬时价格并据此决定费率;Hook 保存跨池、跨用户状态;Hook 利用回调顺序和交易回滚机制制造拒绝服务。
攻击者可能先建立看似正常的流动性池,在 Hook 中加入隐藏收费、黑名单逻辑,再通过前端、空投、聚合器或社交媒体吸引用户。用户进行交易或提供流动性后,攻击者即可通过自定义逻辑、外部调用恶意获取其他用户资产。
二、常见恶意 Hook 形式
- 每次交易抽取少量额外费用;
- 对特定地址收取不同费率;
- 在价格接近某阈值时突然改变行为;
- 让流动性提供者无法移除流动性;
- 通过回调消耗大量 Gas,使兑币交易失败;
- 诱导用户调用假冒的 unlock、settle 或 token 转账函数。
三、恶意 Hook 示例解析
1. 隐性交易费
示例 SuspiciousFeeHook 展示了对指定地址收取额外费用的逻辑:开发者通过 privilegedUsers 给自己、做市商或指定机器人免除费用,而其他用户需承担额外交易费用。在真实 v4 架构中,Hook 通常不能任意绕过 PoolManager 的结算规则,但可通过自定义 delta、外部代币调用或池配置影响最终结算。因此,审计重点是检查 Hook 的所有余额变化路径。
2. 动态价格或费率
AddressBasedHook 示例包含黑名单机制,并根据用户地址设置不同费率。如果费率没有被前端完整展示,用户看到的池子可能与实际交易条件不一致。审计或开发时必须确认所有费率返回值均满足协议允许范围,而不是只检查常规路径。
3. 重入和外部回调
ReentrantHook 示例中的外部调用可能触发 ERC-777 或自定义 ERC-20 回调、ERC-721/ERC-1155 接收回调、借贷协议回调、聚合器回调、当前 Hook 再次调用或其他池子 Swap。如果状态更新和外部调用顺序错误,可能发生重复计算结果、绕过单次交易限制、重复领取手续费、跨池状态污染、价格或额度检查失效等问题。v4 核心合约具有自身解锁和结算约束,但这不意味着 Hook 可以安全地进行任意外部调用,安全边界必须在每个 Hook 中单独建立。
4. 利用瞬时价格进行预言机操纵
FragileOracleHook 示例错误地直接使用当前池子瞬时价格,并据此触发清算或奖励逻辑。攻击者可在同一交易中通过闪电贷获得大量资产,然后对目标池进行大额 Swap,将瞬时价格推向极端,从而触发 Hook 的清算、奖励或抵押品估值逻辑。如果 Hook 把当前池价格当作可信预言机,攻击者可能在一个区块内完成操纵。
5. 阻止流动性退出
ExitBlockingHook 示例可让用户加入流动性,却无法移除流动性。常见触发条件包括:用户地址被加入黑名单、池子达到某个 TVL、某个时间戳之后、Hook 管理员调用隐藏开关、用户曾经通过聚合器交易、用户没有支付额外费用。
6. Gas Griefing
GasGriefHook 示例通过在交易中消耗异常 Gas 导致交易失败。更隐蔽的形式包括:遍历不断增长的地址数组、清理历史用户状态、对大量池子逐一查询余额、在失败前执行大量计算、调用多个恶意外部合约。
四、检测恶意 Hook 的方法
- 检查 Hook 地址权限位:确认 Hook 地址声明了哪些回调权限,并与实际字节码中的函数进行比对。如果地址声明了 beforeSwap、afterSwap、beforeAddLiquidity、beforeRemoveLiquidity,则需要逐一分析对应函数。
- 获取代码:可使用区块浏览器或 RPC 调用 eth_getCode(hookAddress),检查是否为代理合约、是否存在升级入口、是否存在自毁逻辑、是否包含未知外部调用、是否与已验证源码一致。
- 检查流动性池初始化交易:重点查看 PoolKey、currency0/currency1、fee、tick spacing、Hook 地址、初始化地址、管理员、资金接收地址。
- 模拟边界场景:至少模拟正常 Swap、极小金额 Swap、大额 Swap、零金额 Swap、价格极端变化、重复 Swap、添加后立即移除流动性、Hook 管理员变更、代币转账失败、外部调用回调等场景,比较用户实际支付和实际收到的代币数量、Hook 余额变化、PoolManager delta、事件记录和 Gas 消耗。
结语
Uniswap v4 Hook 旨在让 Uniswap 更具可扩展性,但也引入新的攻击面和被恶意利用的可能。对于普通用户而言,Hook 安全最重要的判断标准是:这个 Hook 是否经过验证、源码是否公开、权限是否受限。对于整个 DeFi 生态来说,DeFi 协议与安全公司需采取更多措施,如检测工具和针对流动性池的审查,以提高链上交易的安全性和可靠性。
