智能合約安全與審計

模糊測試

模糊測試以大量隨機或半隨機的輸入轟擊合約、並觀察是否有某個性質被打破,藉此測試合約,而非倚賴少數幾個手寫的範例案例。人類寫下涵蓋自己想到情境的幾個測試;模糊測試器則探索他們沒想到的廣袤輸入空間,浮現出那些假設悄悄失效的邊界案例、極端值與奇異組合。它是尋找真實智能合約漏洞中收益最高的自動化技術之一。

實務上,智能合約的模糊測試是基於屬性的:你斷言的不是一個固定的預期輸出,而是一個對所有輸入都應成立的性質,模糊測試器則搜尋任何能將其證偽的輸入。覆蓋率導向的模糊測試器,會把隨機性導向尚未探索的程式碼路徑,並在找到失敗時把反例收縮到仍能觸發它的最小輸入。主流工具是 Echidna、Foundry 內建的模糊測試器(對測試參數做參數模糊、以及有狀態的不變量模糊),與 Medusa。

模糊測試的好壞,全看你所斷言的性質。一個沒有有意義檢查的模糊測試,只不過確認程式碼能跑而不崩潰;真正的本事在於把「什麼絕不能發生」——不從無中生有任何價值、沒有使用者能提領出多於其存入的——編碼成一個模糊測試器能試圖違反的精確斷言。隨機探索也可能漏掉藏在冗長、特定呼叫序列之後的狀態,這正是有狀態的不變量模糊與設計良好的 handler 之所以重要、也是模糊測試之所以互補而非取代形式化驗證的原因。

// Foundry parameter fuzzing
function testFuzz_NoFreeMoney(uint96 amount) public {
    vm.assume(amount > 0);
    vault.deposit{value: amount}();
    uint256 before = address(this).balance;
    vault.withdraw(amount);
    assertLe(address(this).balance, before + amount);
}

斷言一個性質;讓模糊測試器去搜尋反例。

模糊測試的好壞全看你斷言的性質。一個沒有有意義不變量的模糊測試器只是確認程式碼能跑;本事在於把什麼絕不能發生編碼成一個工具能攻擊的可檢查斷言。

又稱
property-based testing屬性測試