The Art of Manually Guided Fuzzing - DeFi Security Summit 2025
三句話摘要
使用 Python 語言對 Solidity 智能合約進行有狀態模糊測試(Stateful Fuzzing),以 Wake 框架實作不變量驗證與差異化測試。 Wake 將 Python 的建模彈性與即時偵錯能力帶入 Solidity 模糊測試,差異化測試搭配主網 Fork 是發現細微業務邏輯漏洞最有效的組合。 Flow 是有狀態模糊測試的核心執行單元:每個 Flow 對應一筆合約交易,測試者在 `pre_sequence` 中部署合約、在 Flow 中準備隨機輸入並調用合約,模糊測試器依照設定的權重(weight)隨機排列 Flow 序列來探索狀態空間。這種設計讓成功率接近 100%,因為複雜的前置條件(例如 approve)可直接在 pre-execution 中手動完成。
重點整理
重點- 1
Flow 是有狀態模糊測試的核心執行單元:每個 Flow 對應一筆合約交易,測試者在 `pre_sequence` 中部署合約、在 Flow 中準備隨機輸入並調用合約,模糊測試器依照設定的權重(weight)隨機排列 Flow 序列來探索狀態空間。這種設計讓成功率接近 100%,因為複雜的前置條件(例如 approve)可直接在 pre-execution 中手動完成。
- 2
差異化測試(Differential Testing)可捕捉細微邏輯錯誤:測試者在 Python 中維護一份與 Solidity 合約邏輯對應的狀態模型(例如用 `defaultdict` 追蹤餘額),Invariant 只與 Python 模型比對,不直接讀取合約 view function,這樣才能驗證「合約行為是否符合預期」而非「合約是否自我一致」。
- 3
可重現性與除錯能力是 Wake 的關鍵優勢:每次模糊測試從固定隨機種子(seed)開始,發現問題時可保存種子重現相同序列;`-d` 旗標在失敗時自動附加 Python 偵錯器,允許直接在模糊測試運行時探索合約狀態、呼叫 view function、設置斷點,大幅縮短除錯循環。
- 4
主網 Fork 讓測試貼近真實環境:無需部署 Mock token,可直接傳入 USDC、USDT 等真實合約地址進行測試,能快速發現合約對非標準 ERC20(如 USDT)的相容性問題,這類問題在純模擬環境中幾乎不會被發現。
實用技巧與重點
乾貨- 工具名稱:Wake(原名 woke)、Python fuzzing 框架,安裝指令 `pip install eat`,版本約 420
- 核心元件:`FuzzTest` 基底類別、`@flow` 裝飾器、`@invariant` 裝飾器、`pre_sequence` 函式
- 作弊碼:`mint_erc20(contract, token, receiver, amount)` 直接鑄造測試代幣
- 包裝器:`may_revert()` 捕獲交易回滾例外,可枚舉所有可能的回傳路徑
- 除錯旗標:`-d` 在失敗時自動啟動 Python 偵錯器;`--seed <值>` 重現特定序列
- 序列設定:`sequence_count=10, flow_count=100` 表示執行 10 條序列,每條執行 100 個 Flow
- Flow 權重:預設 weight=100;設為 10 代表觸發概率約為其他 Flow 的 10%
- Flow 前提條件:可用 `precondition=lambda: <bool>` 在條件不滿足時跳過該 Flow(不減少 Flow 配額)
- 主網 Fork 方式:指定 RPC 節點 URL 及區塊高度,本地直接使用真實合約地址
- Python 類型提示:`pytypes` 模組提供 Solidity 綁定,自動生成建構子參數提示
- 有序集合建議:模糊測試中使用 `set` 會破壞隨機種子的可重現性,應改用有序集合
- 日誌建議:使用 `logger.info()` 而非 `print()`,可動態調整 log level 避免長時間運行產生過多輸出
- 回滾比例策略:講者慣用 10% 允許回滾 + 90% 有效交易,避免模糊測試器浪費時間在無效路徑
結論
結論“Wake 將 Python 的建模彈性與即時偵錯能力帶入 Solidity 模糊測試,差異化測試搭配主網 Fork 是發現細微業務邏輯漏洞最有效的組合。”
完整解析
詳細智能合約安全審計的一大挑戰是如何系統性地驗證合約在所有可能狀態下都維持正確行為。傳統手動審查難以窮舉所有路徑,而現有的 Solidity 原生模糊測試工具(如 Foundry)雖然強大,但測試語言與合約語言相同,缺乏引入外部數學模型或圖形分析的彈性。講者在捷克理工大學開發的 Wake 框架,選擇以 Python 作為測試語言,正是要借用 Python 生態系的豐富性——從統計分析到儀表板可視化,都可在同一個測試活動中完成。
Wake 的測試架構以「狀態機」為核心。測試者繼承 `FuzzTest` 類別,在 `pre_sequence` 中部署合約並初始化 Python 側的狀態追蹤(例如用 `defaultdict` 紀錄每個帳戶的存款餘額),接著定義多個以 `@flow` 裝飾的函式,每個 Flow 代表一筆合約交易。模糊測試器依照各 Flow 的權重隨機排列執行順序,每執行一個 Flow 後,自動執行所有 `@invariant` 函式檢查合約狀態是否仍符合預期。序列(sequence)與 Flow 的數量可獨立調整,讓測試者在「廣度探索」與「深度路徑」之間取得平衡。
差異化測試是 Wake 最具威力的技術之一。講者示範了一個 ERC20 金庫合約(Vault),在 Python 中同步維護一份存款總量的計算模型,Invariant 只與這個 Python 模型比對,而非從合約的 view function 讀取。這樣的好處在於:一旦合約的狀態轉移邏輯與預期不符,差異立刻暴露;而在撰寫模型的過程中,測試者也被迫仔細審視每一個邊界條件,許多 bug 往往在這個建模階段就已被發現。講者特別強調,view function 僅用於 Invariant 最終比對,中間過程的狀態追蹤一律由 Python 模型負責。
在工程細節上,Wake 提供了幾個實用機制大幅提升效率。`may_revert()` 包裝器讓測試者可以優雅地捕獲交易回滾,搭配錯誤分類邏輯決定要繼續還是標記為失敗;`-d` 旗標在測試失敗時自動附加 Python 偵錯器,可直接在模糊測試的當下狀態中調用合約函式、檢查儲存值,這種即時除錯能力是 Solidity 原生工具難以達到的。主網 Fork 功能則讓測試者直接使用 USDC、USDT 等真實合約,講者曾以此發現某個協議雖宣稱支援 USDT,但合約邏輯實際上並不相容——這類問題在使用 Mock token 的環境中完全無法察覺。
關鍵時刻
Pipeline v2帶時間戳的重點,會在逐字稿層級分析上線後產生。目前請先透過原始影片觀看。
事實查核
Pipeline v2說法查證是下一次管線升級的一部分。KeyFrame 只會顯示它真正能驗證的內容。

