Moving Access Control Away From Smart Contracts' Code
三句話摘要
將 Solidity 智能合約的存取控制邏輯從編碼時期移至代理層,實現部署配置時期靈活管理的設計模式。 把三行存取控制查詢放進代理,即可讓所有實作合約的業務邏輯與安全策略徹底解耦——合約更小、測試更簡單、權限配置從此在鏈上透明可查。 現有模式的共同缺陷是「編碼時期決策」:Ownable、AccessControl、Pausable、AccessManaged 雖靈活度遞增,但開發者都必須在寫程式時決定哪些方法受保護、對應哪個角色,部署後無法在不改合約的情況下調整,且將測試複雜度強加到每個方法上。
重點整理
重點- 1
現有模式的共同缺陷是「編碼時期決策」:Ownable、AccessControl、Pausable、AccessManaged 雖靈活度遞增,但開發者都必須在寫程式時決定哪些方法受保護、對應哪個角色,部署後無法在不改合約的情況下調整,且將測試複雜度強加到每個方法上。
- 2
代理攔截取代修飾器:新方案在標準 ERC 代理的委託呼叫前插入 AccessManager 查詢,功能上等同於對所有方法加 `restricted`,但存取邏輯完全與實作合約分離,實作合約得以保持純業務邏輯。
- 3
部署時期的彈性配置:可在部署代理時傳入「跳過方法」列表(如 view function),讓這些方法繞過權限查詢;對於需要細粒度參數級別控制的場景,可在方法內部構造假選擇器(fake selector)再向 AccessManager 查詢,不改架構即可實現更精細授權。
- 4
可觀察性是最深遠的效益:所有存取規則集中儲存在鏈上 AccessManager,任何人可程式化查詢協議的完整權限配置,搭配 manifest 文件與監控工具可實時比對鏈上配置與預期一致性,讓安全審計與透明度大幅提升。
實用技巧與重點
乾貨- OpenZeppelin v5(2023 年 12 月)引入 AccessManager + AccessManaged 模式,是本方案的直接基礎
- 代理層加入查詢後,合約體積縮減 10–20%(移除 Pausable 效果更顯著)
- 跳過方法(skip methods)gas overhead:0(與普通代理完全相同)
- 非跳過方法 gas overhead:約 1,500 gas(與 OZ AccessManaged 模式相當)
- 核心實作:在代理 fallback 函數中,用 `msg.sig`(4 bytes selector)呼叫 `AccessManager.canCall(caller, target, selector)`
- 假選擇器技巧(fake selector):方法內部用部分參數生成 4 bytes 偽選擇器,再向 AccessManager 查詢細粒度權限
- 緊急暫停:呼叫 AccessManager 的 `setTargetClosed(contract, true)`,取代傳統 Pausable
- 測試輔助:配套 JavaScript 函式庫可在測試環境部署「全開放代理」,略過所有存取控制
- 工具鏈:manifest 文件 + 鏈上監控工具,確保 onchain 配置與 manifest 一致
- 社群提案 ERC-7746:建議 middleware hook 傳入完整 calldata 而非只傳 selector,支援更複雜的參數級別過濾
- 專案連結:Insuro 的 Access Manager Proxy GitHub repo(最小實作)、已向 OpenZeppelin 提交 issue 建議納入標準庫
結論
結論“把三行存取控制查詢放進代理,即可讓所有實作合約的業務邏輯與安全策略徹底解耦——合約更小、測試更簡單、權限配置從此在鏈上透明可查。”
完整解析
詳細智能合約的存取控制長期面臨一個根本性困境:開發者必須在編寫程式碼時就決定哪些方法需要保護、使用哪種角色模型,這些決策一旦部署便幾乎無法更改,同時也讓測試負擔倍增——每個受保護方法都要撰寫授權與非授權的重複測試案例。Insuro 的 CTO Guillermo(25 年以上軟體工程資歷)以自家基於區塊鏈的再保險協議為背景,分享了一套將存取控制邏輯從實作合約完全剝離、移至代理層的設計模式。
Solidity 生態現有四種主流存取控制方案,靈活度遞增但問題本質相同。`Ownable` 只有單一管理員,缺乏角色細分;`AccessControl` 支援命名角色,但角色與方法的對應關係仍寫死在修飾器中;`Pausable` 基於協議狀態而非使用者身份來限制存取,用於緊急暫停;OpenZeppelin v5 在 2023 年 12 月推出的 `AccessManaged` 最接近理想,它把規則集中到外部 AccessManager 合約,但開發者仍須在每個方法上加 `restricted` 修飾器。這意味著「哪些方法受保護」的決策依然停留在編碼時期,可觀察性差(必須讀原始碼才能理解存取配置)、合約體積臃腫、測試複雜度居高不下等問題並未根本解決。
Insuro 的解法極為簡潔:在標準 ERC 代理的 `fallback` 函數中,於委託呼叫前插入約三行程式碼,用 `msg.sig`(方法選擇器)向 AccessManager 查詢當前呼叫者是否有執行權限。如此一來,實作合約中的所有存取控制修飾器皆可刪除,業務邏輯保持純粹。對於不需要限制的方法(如 view function),可在部署代理時傳入「跳過方法」列表,讓這些呼叫直接委託而不觸發查詢,gas overhead 降為零。若需要更細粒度的參數級別控制,可在方法內部構造「假選擇器」再向 AccessManager 查詢,在不改變整體架構的前提下實現精細授權。
這個模式帶來了多層次的實際收益:合約體積縮減 10–20%,移除 Pausable 後效果更明顯;測試環境可一鍵部署「全開放代理」,完全略過存取控制,讓工程師專注在業務邏輯的驗證上;緊急暫停直接透過 AccessManager 的 `setTargetClosed` 實現,不再需要 Pausable 合約。而最深遠的效益在於可觀察性——所有存取規則集中在鏈上 AccessManager,任何人可程式化查詢,Insuro 已建立 manifest 文件搭配自動監控工具,實時比對鏈上配置與預期的一致性。這讓安全審計、治理透明度與多協議的標準化監控成為可能;反觀 Morpho v2 等優秀專案仍在自行實作存取控制,使外部追蹤與比較變得困難,凸顯標準化的重要性。Guillermo 最後也呼籲 Solidity 語言層面能引入「pre-dispatch hook」機制,讓這套模式可在不依賴代理的情況下原生實現。
關鍵時刻
Pipeline v2帶時間戳的重點,會在逐字稿層級分析上線後產生。目前請先透過原始影片觀看。
事實查核
Pipeline v2說法查證是下一次管線升級的一部分。KeyFrame 只會顯示它真正能驗證的內容。

