How Do You Even Write Secure Code Anyways, Samczsun - DeFi Security Summit 2022
三句話摘要
如何在區塊鏈智能合約開發中應用 NASA 編碼標準原則,撰寫高安全性代碼。 撰寫安全代碼的核心是建立多層防守:通過編碼標準提升可讀性降低審計難度、用分層測試涵蓋邊界情況、優先加固小型基礎函數、用污點分析追蹤用戶控制流。 編碼標準提升可讀性:bZx 協議缺乏編碼規範導致代碼跳躍複雜難審計,而 Compound V2 採用描述性變數名、線性邏輯流、立即退出機制等標準使代碼易維護,任何審計員都能快速理解邏輯。
重點整理
重點- 1
編碼標準提升可讀性:bZx 協議缺乏編碼規範導致代碼跳躍複雜難審計,而 Compound V2 採用描述性變數名、線性邏輯流、立即退出機制等標準使代碼易維護,任何審計員都能快速理解邏輯。
- 2
測試需分四層執行:正向單元測試驗證功能正確,負向單元測試測試邊界與失敗情況(如平方根傳負數),集成測試驗證整體協議功能,主動測試(Active Test)在主網 fork 上驗證當前鏈上狀態假設(如流動性充足、預言機正常初始化)。
- 3
基礎函數是安全瓶頸:路徑驗證、用戶輸入驗證、安全計算等小型輔助函數雖然代碼少,但處理用戶輸入且執行關鍵操作,是導致漏洞的主要源頭,應該優先進行單元測試。
- 4
污點分析追蹤用戶控制流:從數據源(Source)追蹤到敏感操作點(Sink),驗證用戶輸入是否被驗證後才進入關鍵邏輯;ENS 名稱定價案例中需測試空字串、特殊 Unicode 字符等邊界條件。
實用技巧與重點
乾貨- NASA JPL C 編碼標準摘錄:
- 所有代碼必須通過靜態分析,無警告或錯誤(包括誤報)
- 禁止動態邊界循環與遞迴
- 變數作用域盡可能緊湊
- 每個函數返回值必須使用或顯式丟棄
- 每個函數起始處驗證所有參數
- 超過 1 個操作的表達式使用括號明確運算次序
- 函數最長 60 行,超過 10 行須包含至少 1 個斷言
- 測試類型定義:
- 正向單元測試:factorial(2)=2, factorial(0)=1
- 負向單元測試:factorial(-1)=?, factorial(1.5)=?, factorial(∞)=?
- 整合測試:完整購票→領獎流程驗證
- 主動測試:fork 主網驗證鏈上流動性、預言機狀態、代理初始化
- 輔助函數優先測試列表:
- 數值參數:測試極大值、極小值、0、2^256 等邊界
- 字符串參數:測試空字串、超長字串、畸形 Unicode
- 地址參數:測試零地址、自身、惡意合約地址
- 陣列操作:測試重複元素、空陣列
- 案例代碼位置:
- bZx 借貸函數跨越多合約(borrowArcTrade → pool → borrower trade → initialize interest → settle fee rewards...)
- Compound V2:線性邏輯流、早期返回、描述性變數名
- ENS 定價函數:需驗證正常字串、空字串、重音字符、阿拉伯字符、表情符號
結論
結論“撰寫安全代碼的核心是建立多層防守:通過編碼標準提升可讀性降低審計難度、用分層測試涵蓋邊界情況、優先加固小型基礎函數、用污點分析追蹤用戶控制流。”
完整解析
詳細演講者以 NASA Curiosity Rover 為切入點,說明安全代碼的重要性。該項目耗資 32 億美元、2011 年發射、由 30 人團隊編寫 250 萬行 C 代碼,NASA 為確保投資回報而制訂 JPL 機構編碼標準。雖然這些標準含有 C 語言特定內容,但許多原則可移植到 Solidity,例如強制靜態分析、禁止動態邊界循環和遞迴、函數長度限制 60 行等。
演講者隨後提出撰寫安全代碼的五個方法。第一個是編碼標準。他對比了兩個 DeFi 協議的代碼。bZx 的借貸函數缺乏命名規範,使用模糊變數名(如 Saint Patrick's 代表接收地址、values[3]),且邏輯分散於多個合約,審計員需要來回跳躍才能理解流程。相比之下,Compound V2 使用描述性變數名(如 repayAmount、mathErrors、accountBorrows)、線性邏輯流、立即返回失敗條件等標準,使代碼易於審計。簡單規則包括:用描述性變數名、限制活躍變數數量、消除冗餘邏輯、儘早返回、關聯代碼聚合、刪除未使用代碼。
第二個是測試。測試必須分層進行。正向單元測試驗證函數正確功能(如平方根函數傳入 4 返回 2、9 返回 3)。負向單元測試測試失敗案例(如平方根傳負數、浮點數、零),這是開發者容易遺漏的環節。集成測試驗證整個協議功能如完整購票流程。演講者引入「主動測試」概念,即在主網 fork 上運行測試以驗證當前鏈上狀態假設(如流動性充足、預言機返回價格、代理已初始化),若假設不符則主動測試失敗,提示需要修正。
第三個是基礎建設。小型輔助函數雖代碼少,但通常處理用戶輸入、執行安全計算或數據清理,是安全瓶頸。例如 ENS 定價函數中計算字符串長度的函數是關鍵,若計算錯誤則攻擊者可以廉價購買短名稱。應優先為這類函數編寫單元測試,包括邊界條件:正常字串、空字串、包含重音符號的字串、特殊 Unicode 字符(如阿拉伯字符)、表情符號。
第四個是污點分析。在大型代碼庫中逐行審計不現實,應優先審視攻擊者可控的路徑。污點分析從數據源(用戶輸入進入點)開始,追蹤該數據流向敏感操作點(Sink,如代幣鑄造)。數據在流經函數或被變換時仍保持「污染」狀態,直到被驗證(檢查範圍、地址合法性等)才清潔。演講者以某協議的 createVault 函數為例,該函數可設置任意 X 代幣地址並配合無價值資產,使攻擊者能用垃圾資產換取高價值代幣。通過污點分析可快速識別此漏洞。
關鍵時刻
Pipeline v2帶時間戳的重點,會在逐字稿層級分析上線後產生。目前請先透過原始影片觀看。
事實查核
Pipeline v2說法查證是下一次管線升級的一部分。KeyFrame 只會顯示它真正能驗證的內容。

