在區塊鏈世界裡,代碼就是法律,確保代碼的安全性至關重要。
安全是編寫智慧合約的最重要的方面之一。開發人員可能熟悉傳統的單元測試來測試他們的代碼,但這只提供了基本的覆蓋範圍來測試代碼的功能和業務邏輯。然而,它們是在假設智慧合約在給定條件下的表現符合預期的基礎上運行的。為了進一步增強安全性,我們需要採用更高級的測試方法,如差異模糊測試(differential fuzzing)。
差異模糊測試是一種測試類型,它涉及執行相同功能或函數的不同實現,並比較結果。這種測試允許我們驗證不同實現之間是否是等價的,並且在提供無效或隨機輸入時表現一致。這與普通模糊測試不同,後者通常通過為單個實現提供廣泛的隨機輸入範圍並監控意外行為、崩潰或安全性漏洞來進行測試。
在這個項目中,我們使用 Foundry 對不同的定點庫(OpenZeppelin、Solmate、Solady 和 Prbmath)進行差異模糊測試。請注意,在 Solmate 庫的幾個主要版本中,我們使用了最新的(v6)的代碼庫,因為我們認為大多數選擇 Solmate 庫的新項目會選擇這個版本。我們希望檢查不同代碼庫對於相同的函數實現是否有顯著差異。在跑了一千萬次測試後,我們發現這些庫之間具有廣泛的相容性,但是在處理邊緣情況和燃氣費消耗方面存在一些差異。
具體差異 我們將通過以下示例來說明這些庫實現上的差異。 在 Log2 函數(返回以 2 為底的對數)中,如果輸入為 0,OpenZeppelin 和 Solady 的實現會返回不同的結果。OpenZeppelin 將直接返回 0,而 Solady 將返回 0x5be3aa5c(即 Log2Undefined() 的簽名)。
因此,我們在測試用例中添加 if (num != 0) 來避免這種差異。 在 mulDiv() 函數中也出現了類似的差異。我們需要確保除數不為零且沒有溢出。否則,OZ 和 solady 會報錯。例如,Solady 將返回 0xad251c27,這是 MulDivFailed() 的簽名,所以我們也添加了 if 語句。 如果你想要在測試中重現錯誤情況,請注釋掉 if 語句,然後使用特定測試用例。
並請參考庫實現來瞭解為什麼他們會這樣處理。
由於這些庫中的函數大多相互相容,我們對它們的燃氣費消耗進行了比較,來檢測哪一個資料庫是最省燃氣費的。 燃氣費快照可以在.gas-snapshot 文件中找到。為了更好的閱讀性,我們附上了簡化的燃氣費報告(每個函式呼叫的平均燃氣費消耗)。
solady 庫中所有比較的函數的燃氣費消耗相對較低,而且它提供了最全面的功能,這使得它成為高級開發人員的首選。但是,值得注意的是,只有 OpenZeppelin 和 Solmate 經過了外部安全團隊的審計。
即使是 Solmate 也並不是設計之初就簡單易用的,所以在你搬起石頭砸了自己的腳之前,應該徹底閱讀文檔並理解代碼庫。 好消息是,Cantina 決定將 Solady 庫作為公共專案進行審計,你可以在這裡監控他們的審計狀態。
為了確保模糊測試的正確性,我們進行了 9999999 次的模糊測試。通常,在開發過程中沒有必要運行這麼多次,但作為安全研究人員,我們希望覆蓋盡可能多的隨機輸入。 你可以在 [foundry.toml]中更改運行次數。更多的運行次數意味著有更多的隨機輸入輸入到函數中。如果你想要運行快速測試,例如用於持續集成,請根據你的需求調整配置。
在龐大的 Solidity 庫中,定點算術只是其中一個方面。為了擴大這項研究的範圍,我們可以比較處理不同功能的庫,使用不同的 pragma 版本。這將為我們提供跨不同用例和 Solidity 版本的安全的更廣泛理解。 此外,我們還可以記錄 Foundry 使用的隨機輸入並進行分析。這將使我們能夠判斷這些輸入是否真的隨機,並確保對庫進行公平和全面的評估。
我們進行差異模糊測試的主要目的是揭示 OpenZeppelin、Solmate、Solady 和 PRB-Math 的 Solidity 定點庫在輸出結果方面的顯著差異。雖然這些庫在相容性方面表現良好,但我們的測試發現它們在處理邊緣情況時存在細微差別,尤其是在 Log2 和 mulDiv 函數中。
雖然這些差異可能看似微小,但它們可能導致智慧合約出現意外行為,因此具有重要意義。 通過這項工作,我們希望為開發人員提供詳細的見解,以指導他們在為智慧合約應用程式選擇庫時做出決策。我們的研究沒有發現這些庫之間存在重大偏差。
然而,我們觀察到的細微差異提醒人們充分測試和理解所使用代碼的重要性。 在區塊鏈世界裡,代碼就是法律,確保代碼的安全性至關重要。對 Solidity 庫進行差異模糊測試是實現這一目標的一步,它提供了比單元測試更高級別的保證。我們期待看到一個更安全的加密生態。
免責聲明:
本文觀點僅代表作者個人觀點,不構成本平台的投資建議,本平台不對文章信息準確性、完整性和及時性作出任何保證,亦不對因使用或信賴文章信息引發的任何損失承擔責任
0.00