Uniswap毒池陷阱,29小時收13萬美元
Blockbeats原文標題:《報價 0%,執行 12.8%:Uniswap v4 "毒池"動態費率陷阱復盤》
原文作者:王子豪,BitsLab
2026 年 8 月 22 日到 23 日,BNB Chain 上一個 Uniswap v4 USDC/WBNB 動態費率池在聚合器報價裡顯示 0% 費率,用戶實際成交卻被收取 12.8% 的 LP fee。約 29 個小時裡,這個池子成交 21,086 筆、累計手續費 131,888 美元,隨後註銷。所有受害交易都成功了:合約未被盜,輸出高於用戶設定的下限,沒有任何異常信號——差額安靜地變成了手續費。
本文以其中一筆樣本交易為入口:
(0x7615dec2ce80506ec461a47739eb8533ac2bc7c605ca56c255964481b76363d0:用戶投入 5,926.90 USDT,到手比預期少 757.43 USDT),拆解這個池子如何做到「報價 0%、執行 12.8%」:費率函數的三層判定、被架空的滑點保護、把其他 LP 擋在門外的白名單。全部結論基於鏈上數據與本地受控驗證。
01 從報價到執行的鏈路
用戶在聚合器前端發起兌換後,整條鏈路是這樣走的:

這條鏈路上有兩個背景事實,後面每一層判定都建立在這兩點之上。
先看 v4 這一側:它允許 Hook 逐筆覆蓋費率。PoolKey.fee = 0x800000 聲明動態費率池;Hook 在 beforeSwap 的第三個返回值攜帶 0x400000 | fee。v4-core 裡接收這個返回值的代碼(Pool.sol:303-305):

isOverride() 檢查覆蓋標誌,removeOverrideFlagAndValidate() 剝掉 0x400000 並校驗不超過 MAX_LP_FEE = 1,000,000(100%),然後按該費率執行本筆 swap 並寫入 Swap 事件。也就是說,Hook 返回什麼,用戶就付什麼——只要輸出仍高於 amountOutMin。這是正式功能,按波動率、庫存調費率都是正當用途。
再看這個 Hook 本身:它只宣告了兩項權限。v4 把權限編碼在合約地址低 14 位(Hooks.sol:29-47),部署時校驗、事後不可改。v4-core 側的標誌位定義與地址解碼對讀:

鏈上實測 getHookPermissions() 返回與位圖一致:僅這兩位為真。
Hook 無源碼。本文從字節碼反編譯出費率函數全文——以下是對這份已在鏈上運行過的邏輯的行為拆解:

接下來逐層看。前兩層回答的都是「這是不是一次模擬」,第三層決定真實交易付多少。
02 費率函數的三層判定
判定一:區分調用者
費率函數被調用後,先比對 tx.origin:等於三個常量地址中的任何一個,就直接返回回退檔。回退檔當前配置為 0%。
三個地址不是隨便選的。eth_call 未指定 from 時,交易的 origin 落在零地址上——聚合器批量詢價通常不指定。本地 fork 中直接驗證:

第一層只認這三個地址。下一層看指定了普通地址之後,Hook 還能怎麼區分。
判定二:檢查 gas
把 tx.origin 換成普通地址重試,返回仍是 0%——第一層被繞過了,費率卻沒變。這說明第一層不是唯一的判定,定位到第二層:gasleft() * 10100 / 10000 >= gate。
聚合器報價習慣給很高的 gas,防止候選路線在模擬中因 gas 不足失敗;真實交易進 Hook 前,gas 已被 Router、授權、前置跳消耗。同一份代碼,三種 gas:

分界線實測位於 16.85M–16.9M gas 之間。30M 與 2.59M 的差異,就是"報價"與"執行"的差異。
判定三:逐筆偽隨機
前兩層都過的真實交易進入第三層:把區塊環境指紋雜湊後對 10,000 取模,按結果所在的區間返回對應費率檔。當前配置三檔 8% / 10% / 10%,落空則回退 0%。
這層有兩個值得注意的設計。指紋裡混入了 calldata 的三個欄位——聚合器報價的 calldata 和真實路由的 calldata 本來就不同,指紋自然也不同。另外,逐筆偽隨機讓費率帶分布,單看幾筆很難察覺規律,簡單的規則枚舉攔不住。
全部 21,086 筆鏈上事件中出現 19 檔歷史費率(6.8%–28%),說明費率檔一直由管理員函數按需重配;樣本交易成交時生效的是 12.8%。
三層合併的圖景

至此可以給「毒池」下一個定義——同時滿足三個條件的 v4 池:PoolKey.fee 攜帶動態費率標誌;費率決策讀取執行環境信號(gas、origin、區塊環境),而不讀公開市場狀態;報價模擬與鏈上執行的費率出現系統性分叉,受益方為毒池部署者。分界就在費率讀什麼:對任何調用者返回同一費率的,是可編程市場設計;按「是誰在問價」返回不同費率的,是對路由系統的欺騙。
到這裡,費率分叉的機制已經完整。但費率收走之後,交易為什麼還能成功,是下一個問題。
03 滑點保護為什麼沒有回退
先看這筆交易的完整路徑與金額:

該跳的 Swap 事件把生效費率記在 fee 欄位裡:128000。v4 的費率單位以 1,000,000 為 100%,128000 就是 12.8%。這筆交易的損失可以從兩個角度衡量:從池子看,費率對 WBNB 輸入收取;從整條路線看,穩定幣進出差額 757.43 USDT,折損 12.7794%,其中還含前置跳費用與脫錨偏差。兩個數字只差 0.02 個百分點,說明折損的主要來源就是這個池子的 LP fee。
amountOutMin 只校驗最終輸出下限,不看中間每一跳收了多少費:

12.8% 的費率整個落在 20.32% 的緩衝之內,輸出仍高於底線——交易成功,不回退。主流穩定幣路線的常規默認是 0.1%–1%,這條路線給了 20 倍以上的空間。用戶以為寬緩衝是「穩一點」,實際上是把路徑上每一個合約都交給了對端自律。把這筆賬畫成圖:

04 毒池部署者的操作
白名單:把其他 LP 擋在門外
白名單邏輯在 beforeAddLiquidity 裡,反編譯結果如下:

加流動性要過三道門:先是任何 v4 Hook 都有的 PoolManager 調用檢查,然後必須經由官方 PositionManager,最後核對頭寸持有人的白名單。不在名單上的地址在這裡被合約回退,其他 LP 進不來,手續費收入不會被稀釋,全部歸部署者。名單本身由一個管理員函數(選擇器 0xc4452e52)按地址維護。
0% 檔與刷量
把 21,086 筆交易放在一起看,分佈呈現出清晰的模式:0% 檔 6,946 筆、成交 12,947,751 美元,筆均 1,864 美元;收費檔 14,140 筆、成交 1,120,106 美元,筆均 79 美元。大額成交集中在 0% 檔,收費集中在小額交易上。大額 0% 最合理的解釋是部署者自己用高 gas 自成交:高額 gas 與聚合器報價命中的是同一個判定,自成交的手續費成本接近零。刷出來的成交量把池子推上行情站排行(快照顯示 24h 成交約 1,082 萬美元、16,671 筆),在聚合器眼裡,這就是一個深度好、費率低的池子。
費率檔按需重配
判定三提到過 19 檔歷史費率,它們來自反編譯出的費率配置函數(選擇器 0x4d909a45,未收錄公開簽名):

四個費率檔與閾值整體打包,寫入 keccak(poolId, 2) 這個存儲槽。鏈上實測該槽讀數為 0x0138800186a00186a0,與函數的打包格式逐段對應。費率檔在這裡是隨時可以調整的參數,並非部署時定死。
生命週期
這個池子 08-22 06:57 建池,07:13 出現第一筆 swap,21:39 是本文的樣本交易;08-23 12:25 最後一筆成交,之後註銷。整個活躍期約 29 小時,總成交 14,067,857 美元,手續費收入 131,888 美元(未扣部署者成本)。複核時註冊標誌已經回到啟用——池子還在,隨時可以再次啟用。
05 完整路徑
把整條攻擊鏈連起來:

整條鏈的因果都在上面這張圖裡,三個條件缺一不可:模擬命中前兩層、真實交易落第三層、緩衝大於費率。任何一個不成立,這套手法都會失效。
06 修復與建議
第一處在聚合器的報價方式。根因是模擬和執行走的不是同一條路:報價用理想化的池級查詢,配上零地址和高 gas;真實交易帶著真實身份和已被消耗的 gas。Hook 恰好能讀出這些差異,費率於是分叉。對治的辦法是讓模擬貼近執行——用實際要發的 Router calldata、真實的 from/to、接近鏈上交易的 gas 做模擬;成交之後解碼 Swap 事件核對 fee,與報價對不上就降權或下線。
第二處在用戶的滑點設置。根因是 min_out 給得太鬆:20.32% 的緩衝把 12.8% 的費率整個吞掉,交易照常成功。主流穩定幣路線 0.1%–1% 足夠日常使用,發起交易前看一眼這個數字;錢包和前後端把默認值收緊,能替用戶擋掉大部分風險。
第三處在路由准入。根因是任何動態費率池都能直接參與報價競爭:沒有開源、沒有審計記錄的 Hook,一樣能靠刷出來的成交量進入推薦路線。對沒有可信檔案(profile)的動態費率池,默認不進路由或顯著降權,是最穩妥的處理。
數據與說明
·樣本交易:
https://bscscan.com/tx/0x7615dec2ce80506ec461a47739eb8533ac2bc7c605ca56c255964481b76363d0(區塊 117497524)
·池初始化交易:
https://bscscan.com/tx/0x8fa72ef72d77b61f715dc9ce90548249ab045c6d78716078cd5ab425bbe69a05
·PoolManager:
0x28e2ea090877bf75740558f6bfb36a5ffee9e9df
·Pool ID:
0x36e5540e9dedc02229fe8a82aa5b10c0bf07d1fa74e4f2ffe0efd00fa1a36aea
·Hook:
0xd111b3ddd92e627f1864520c770e913ec04e0880(無原始碼,虛擬碼為本文獨立反編譯;管理員 0x08b03e1a5444d469f4dc954e74d3f662c94a6b13)
·成交與手續費:該池全部 21,086 筆 Swap 事件逐筆累計(eth_getLogs),WBNB 按同筆執行價折算;收入為毛值,未扣部署者成本
以上內容僅用作資訊或教育之目的,不構成與BTCC相關的任何投資建議。 BTCC竭力但無法保證上述全部內容的真實性、準確性和原創性。