未开源 · 部署于 2026-08-20 · 已挂接 20 个池 · 审查日期 2026-08-21
该 hook 把「这个池收多少手续费」的决定权,完整交给了一个外部账户(EOA)。这个账户可以在任意时刻、对任意挂接了本 hook 的池子,把单笔交易手续费直接改成 99%——没有时间锁、没有更低的上限、没有多签、改完下一笔交易立即生效。
这不是理论推演。链上记录显示该账户已经实际把费率设到过 99.00% / 95.84% / 89.20% / 88.88%;在分叉环境中复现,一笔 30,586 gas 的普通交易,就让当前仍在运行的 KII/USDT 池的下一位交易者损失 98.95% 的本金。
所有事实均取自 BNB Smart Chain 公开链上数据与公开区块浏览器 API。
| 项目 | 值 | 含义 |
|---|---|---|
| 合约类型 | PancakeSwap Infinity CL Hook | 不是 Uniswap V4;挂在 Pancake Infinity 的 CL PoolManager 上 |
| 源码验证 | 未开源 | BscScan / Sourcify / Blockscout 三处均无源码,只能逆向字节码 |
| 代码体积 | 2,893 字节 | 极小,编译器 solc 0.8.26 |
| 部署方式 | CREATE2(通用确定性部署器) | 部署交易发起者与 owner 是同一个 EOA |
| 部署时间 | 2026-08-20 04:00 UTC | 审查时仅上线约 1 天 |
| owner | 0x973d1b35…89d3f9 | 普通外部账户,非多签、非合约 |
| 可升级性 | 不可升级 | 无代理、无 delegatecall 到外部实现 |
| 所有权转移 | 不存在该函数 | 既不能转让也不能放弃——owner 永久锁定为该 EOA |
| 权限位图 | 0x42 | 仅注册 afterInitialize + beforeSwap |
整段运行时字节码里只有 两条 SSTORE,都写向手续费表,owner 所在的存储槽从不被写入。好处是外人无法夺权;代价是这个 EOA 的私钥一旦泄露或丢失,控制权将永久落在攻击者手里,且团队自己也无法通过「放弃所有权」来向用户证明池子已经安全。
逆向出的 17 个函数中,只有一个是外部可写入口。
PancakeSwap Infinity 允许池子声明「动态手续费」(fee = 0x800000)。这类池每次交易前都会回调 hook 的 beforeSwap,并采纳 hook 返回的费率覆盖池子原本的设定。本 hook 对这个机制的实现是:
// afterInitialize —— 建池时把该池费率初始化为 0
customFees[poolId] = 0
// beforeSwap —— 每笔交易前,无条件返回表里的值 + 覆盖标志位
return (selector, 0, customFees[poolId] | 0x400000)
// setCustomFeeById —— 唯一的外部写入口
function setCustomFeeById(bytes32 poolId, uint24 fee) {
require(msg.sender == owner, "Not owner");
require(fee <= 990000, "Fee too high"); // = 99%
customFees[poolId] = fee;
}
三个要点决定了风险性质:
beforeSwap 不做任何判断——不看交易大小、不看方向、不看价格冲击。池子的真实费率永远等于 owner 在表里写的那个数。PUSH3 0f1b30(990000)是唯一的护栏。作为对照,PancakeSwap 官方的动态费 hook 把自己封顶在 5%。setCustomFeeById 接受任意 poolId。只要某个池在建池时挂了这个 hook,无论建池人是谁、流动性是谁提供的,费率都由本 hook 的 owner 说了算。目前唯一仍有实际流动性的 KII/USDT 池,并非由 hook 的 owner 创建(建池者是另一个地址),且池中有 15 个不同地址提供过流动性。也就是说,一批第三方的资金,正暴露在一个与他们无关的 EOA 的单方面定价权之下。
该 hook 自部署以来的全部 72 次费率变更记录,按池分组还原。
| 时间 (UTC) | 池 | 设定费率 | 状态 |
|---|---|---|---|
| 08-20 04:36 | USDT / SpaceXcoin | 89.20% | 极端 |
| 08-20 05:01 | USDT / SpaceXcoin | 99.00% | 触顶 |
| 08-20 06:13 | USDT / ぬいぬい | 95.36% | 极端 |
| 08-20 06:14 | USDT / ぬいぬい | 95.84% | 极端 |
| 08-20 06:22 | USDT / ぬいぬい | 90.00% | 至今未改 |
| 08-20 07:03 | MCT / USDT | 88.88% | 持续约 4.5 小时 |
| 08-20 15:37 | USDT / KII | 4.50% | 当前值 |
在这些高费率窗口内,没有任何一笔交易真正以 ≥5% 的费率成交——623 笔历史成交中,最高档位是 4.53%。也就是说:目前没有证据表明已有用户因此被实际收割。从行为模式看(代币叫 “My Clean Token”、“Liability Vortex”,池子随后被抽空、当前流动性为 0),更像是开发者在主网上测试自己的费率上限。
但这不改变风险评级。「能力已经就位、只是还没被使用」与「不具备该能力」是两件完全不同的事——而且其中一个池此刻仍挂着 90% 的费率,任何人现在在那里交易都会立刻损失九成。
在 BNB Smart Chain 主网分叉环境(Foundry anvil)中,对当前仍在运行的 KII/USDT 池执行完整攻击路径。
用 PancakeSwap 官方 CLQuoter 报价:1,000 USDT → 14,802.30 KII(当时费率 4.50%)。
以 owner 身份调用 setCustomFeeById(poolId, 990000)。交易成功,消耗 30,586 gas,无需任何前置条件。
同样 1,000 USDT,现在只能换到 155.29 KII。
| 方向 | 投入 | 4.50% 档位 | 99% 档位 | 损失 |
|---|---|---|---|---|
| 买入 USDT → KII | 1,000 USDT | 14,802.30 KII | 155.29 KII | −98.95% |
| 卖出 KII → USDT | 10,000 KII | 613.50 USDT | 6.44 USDT | −98.95% |
买卖双向对称受损——这意味着它既能吃掉买家的本金,也能把已经持币的人锁在池子里(卖出等于放弃 99%),效果等同于一个可以随时开关的貔貅盘。
这套机制的危险之处在于,它可以被组合成一次原子化的、不依赖价格波动的提取。
BNB Smart Chain 上交易排序可通过 builder 影响,把自己的交易插到受害者之前并不困难。
① 在当前价位补一笔集中流动性(hook 未注册 beforeAddLiquidity,加减流动性完全不受限制);② 把费率设成 99%。
按 Infinity 核心逻辑 feeGrowthGlobal += feeAmount × Q128 / liquidity,这 99% 的手续费全额记入当前区间内的 LP 头寸——也就是刚刚补进去的那笔。
整个过程在一个区块内完成,池子价格几乎未动,链上看不出任何异常价差。
相比传统三明治攻击,这个路径不需要推动价格、不受滑点保护约束——受害者设置的滑点上限保护的是价格,而这里被拿走的是手续费。用户即便把滑点调到 0.1%,也拦不住这一笔。
一份有用的风险评估也需要说清边界。以下几项经字节码与权限位图确认为不成立。
| 常见担忧 | 结论 | 依据 |
|---|---|---|
| hook 能直接吞掉交易资金吗 | 不能 | 权限位图 0x42 未包含任何 ReturnsDelta 位,hook 无法在结算中截取代币 |
| 能阻止 LP 撤出流动性吗 | 不能 | 未注册 before/afterAddLiquidity 与 before/afterRemoveLiquidity,增减流动性不经过 hook |
| 能偷已经存在池外的代币吗 | 不能 | 合约无 transfer/approve 类调用;lockAcquired 仅原样回传数据,无资金动作 |
| 能被外人夺取控制权吗 | 不能 | 运行时无任何写 owner 槽的路径 |
| 会影响固定费率的池吗 | 不会 | 核心库仅在 fee == 0x800000(动态费)时才采纳 hook 返回值;20 个池中有 2 个是固定费率,不受影响 |
| 能升级成别的逻辑吗 | 不能 | 非代理合约,无 delegatecall 到可变实现 |
换句话说:这个 hook 的全部危险都集中在一处——一个不受约束的费率旋钮。但因为手续费在集中流动性做市中会流向 LP,而 LP 头寸是可以在同一个区块里临时补上的,这一个旋钮已经足以构成完整的资金提取路径。
该 hook 的设计意图(可调的动态手续费)本身是合理的,问题全在缺少约束。要达到可用于第三方资金的标准,至少需要:① 开源并验证合约;② 把上限从 99% 降到一个做市意义上合理的数值(官方同类实现封顶 5%);③ 费率上调加时间锁,让用户有退出窗口;④ 把 owner 换成多签;⑤ 限制只有建池者本人能设置自己池子的费率,而不是由 hook owner 统管所有池。
在这五项落地之前,无论开发者的实际意图如何,其他人的资金放在这里都是没有保护的。