KeyFrame內部研究專用

DeFi Security 101 - 2023 - 04 - Dimitri Kamenski & Richard Skinner

DeFi Security Summit - DSS·7月14日週五·23 min英文

三句話摘要

智能合約代理模式的設計對比、實現方法與安全最佳實踐。 選擇 UUPS 或透明代理應基於具體場景權衡,但最重要是理解初始化風險、避免混淆兩種模式、並使用成熟框架進行防護性實現。 代理的核心機制:代理合約持有指向實現合約的參考,透過委托調用執行實現合約的代碼,但使用代理自身的存儲空間。這樣升級時只需改變指向的實現合約地址,用戶存儲與資金保持不變。

重點整理

重點
  • 1

    代理的核心機制:代理合約持有指向實現合約的參考,透過委托調用執行實現合約的代碼,但使用代理自身的存儲空間。這樣升級時只需改變指向的實現合約地址,用戶存儲與資金保持不變。

  • 2

    透明代理 vs UUPS 的關鍵差異:透明代理在代理合約中內置升級邏輯與管理員檢查,每次調用都需檢查調用者身份(gas 開銷高);UUPS 將升級邏輯移到實現合約,降低普通調用的 gas 成本,但要求實現合約實現訪問控制。

  • 3

    初始化函數的風險:由於代理無法使用傳統構造函數,需用初始化函數執行初始配置。但初始化函數仍可被直接調用,攻擊者可繞過代理直接初始化實現合約。必須在實現合約構造函數中呼叫 `disableInitializers()` 防止此漏洞。

  • 4

    常見配置誤區:同時使用透明代理與 UUPS 模式會造成控制流混亂與人為錯誤風險,鑽石代理模式過於複雜,不建議無特殊需求時使用。應在部署和初始化於同一交易完成,防止交易排序攻擊導致前置初始化。

實用技巧與重點

乾貨
  • 代理概念相關
  • 兩種調用類型:標準調用(使用被調用合約的代碼、存儲、地址)vs 委托調用(使用被調用合約的代碼,但用調用者自身的存儲、地址、調用者身份)
  • 代理合約本身代碼最少,只含必要的代理邏輯,實現合約包含業務邏輯
  • 升級時改變代理中的實現合約地址指針即可
  • 透明代理特性
  • 升級邏輯在代理合約內部處理
  • 需要管理員用戶或白名單合約
  • 每次調用都需檢查 `msg.sender` 是否為管理員(產生 gas 開銷)
  • 管理員調用回退函數觸發升級,更新實現合約地址
  • UUPS 特性
  • 所有調用委托轉發到實現合約
  • 實現合約負責實現升級邏輯與訪問控制
  • 升級檢查只在升級時執行,普通調用無額外 gas 開銷
  • 可將 UUPS 合約升級至無升級功能的版本,實現永久鎖定
  • 初始化函數保護
  • OpenZeppelin Zeppelin 代理庫中使用 `disableInitializers()` 內部函數
  • 在實現合約構造函數中呼叫此函數,防止直接初始化
  • 部署和初始化應在同一交易完成,防止交易排序攻擊
  • 其他模式
  • 鑽石代理(Diamond Proxy):極其複雜,解決合約大小限制,除非必要否則不建議使用
  • 建議:無特殊需求不用代理;必須升級時選擇 Transparent 或 UUPS;優先使用現成成熟庫而非自建

結論

結論

選擇 UUPS 或透明代理應基於具體場景權衡,但最重要是理解初始化風險、避免混淆兩種模式、並使用成熟框架進行防護性實現。

完整解析

詳細

以太坊智能合約部署後代碼基本不可更改,這既是優點(保證可信度),也是缺點(無法修復漏洞或增加功能)。代理模式通過引入中間層解決此問題。代理合約本身代碼簡潔,只持有一個指向實現合約地址的變量。當用戶在代理上調用函數時,代理透過委托調用借用實現合約的代碼邏輯,但執行時使用代理自身的存儲空間。這樣同一份代碼可被多個代理使用,每個代理維護獨立存儲;升級時只需改變代理指向的實現合約地址,無需遷移用戶資金或更改用戶交互地址。

講者介紹了兩種主流實現方式。透明代理在代理合約中內置升級邏輯——管理員調用代理的特定回退函數時,代理不轉發調用,而是直接修改內部存儲槽以更新實現合約地址。為了區分管理員操作與普通用戶調用,代理需在每次調用時檢查 `msg.sender` 是否為管理員,只有非管理員的調用才被轉發到實現合約。這個檢查在每次交互都執行,產生固定的 gas 開銷。UUPS(通用可升級代理標準)採用不同策略——代理無條件將所有調用委托到實現合約,升級邏輯實現在實現合約自身,由實現合約判斷調用者權限決定是否執行升級。這樣普通用戶調用時無額外檢查,gas 成本更低,升級檢查僅在升級時執行。UUPS 還提供更強的靈活性:可將合約升級至完全移除升級功能的版本,實現永久鎖定;而透明代理的升級邏輯內置於代理本身,無法完全移除。

初始化函數是代理使用中的關鍵議題。由於構造函數只在部署時執行後被丟棄,無法在代理升級後被調用,代理模式改用初始化函數(通常命名 `initialize`)執行初始配置。然而初始化函數仍保留在實現合約代碼中,攻擊者可直接調用實現合約的初始化函數而非通過代理,導致實現合約被直接初始化。為防止此攻擊,OpenZeppelin 庫提供 `disableInitializers()` 函數——在實現合約的構造函數中呼叫它,告訴實現合約已被初始化,任何重複初始化嘗試都會失敗。另一個風險是代理部署與初始化若在不同交易進行,惡意用戶可在中間插入交易搶先初始化,接管合約控制權。建議將部署和初始化合併在同一交易中完成。

講者強調了幾個常見誤區。同時使用透明代理與 UUPS 模式極易發生,特別是自動化部署工具或框架默認值混合使用時。由於兩種模式在技術上兼容,這種配置看似正常運作卻不是預期行為,增加人為錯誤風險(如透明代理的管理員權限遺忘在他人手中)。鑽石代理模式雖在某些場景能解決合約大小限制,但複雜度極高,無特殊需求不應使用。最佳實踐總結為:無升級需求就不用代理;選定一種代理模式並堅持;優先使用經過驗證的現成庫如 OpenZeppelin,而非自行實現。

關鍵時刻

Pipeline v2

帶時間戳的重點,會在逐字稿層級分析上線後產生。目前請先透過原始影片觀看。

事實查核

Pipeline v2

說法查證是下一次管線升級的一部分。KeyFrame 只會顯示它真正能驗證的內容。

更多「Web3 安全」的內容

IF YOU OWN XRP YOU NEED TO SEE THIS PRICE MANIPULATION! ⚠️
8 min
Web3 安全英文8月14日

IF YOU OWN XRP YOU NEED TO SEE THIS PRICE MANIPULATION! ⚠️

Zach Humphries

  • 機構支撐的積極意義:價格操縱常被視為負面,但Ripple掌握大量XRP供應與escrow,在熊市期間提高價格下限,實際上替零售投資者鎖定了低風險的積累區間,這不是剝削而是市場穩定機制。
  • 歷史模式驗證:2024年7月至11月XRP在50美分附近橫盤整理,低點觸及42美分(wick),高點65美分;隨後11月5日至12月5日單月上漲456%,年底到2025年初累計漲幅534%,這個歷史周期正在1美元價位重演。
  • 比特幣聯動邏輯:講者在4-5月就預測「如果比特幣跌至60k以下,XRP會跌至1美元或更低」,此預測精準應驗,反映出熊市中兩者的明確連動關係。
Minimmit, Multimmit and the New Consensus Frontier with Patrick O'Grady
72 min
Web3 安全英文PODCAST8月5日

Minimmit, Multimmit and the New Consensus Frontier with Patrick O'Grady

Zero Knowledge

  • 反向 Linux 架構:Commonware 刻意暴露棧各層級控制,讓開發者自訂執行環境、共識機制、密碼學實現,而非像 Cosmos SDK 只允許應用層以上定制。2-3 個月能組裝一條定製鏈,代價是額外深度但回報是長期維護成本降低及效能優化彈性。
  • 容錯假設的典範轉移:Alpine Glow(Solana 2025)實現單輪投票定終的關鍵是將容錯預算分離為獨立的 Byzantine 和 Crash 容限。傳統系統把 33% 當一個整體預算;新模型允許 20% 惡意加 20% 崩潰,打破了 PBFT 理論界線,釋放單輪設計空間。
  • Minimet 與 Multimet 的遞進:Minimet 是 5F+1 設定下的乾淨構造,實現更短視圖延遲;Multimet(剛發布)進一步允許並行 mini-commits 且驗證者可推翻領導者審查,使用者交易在全球分布式網路達到 200-300 毫秒端到端定終。
Private Information Retrieval (PIR) with Alex Hoover
64 min
Web3 安全英文PODCAST7月29日

Private Information Retrieval (PIR) with Alex Hoover

Zero Knowledge

  • PIR 保護的是訪問模式,不是資料本身
  • PIR 與加密不同,它關注的是隱藏「客戶端查詢了什麼」,而非「資料是否加密」。在公開資料庫(如區塊鏈)上,客戶端可以在不洩露查詢對象給伺服器的情況下檢索特定條目,解決了輕量級客戶端的隱私和防審查問題。
  • 客戶端預處理方案是突破瓶頸的關鍵