合約解析
DiamondApp
/contracts/Diamond.sol
核心設計 1.
abstract contract Diamond is IDiamond, Proxy, DiamondCutBase, DiamondLoupeBase, Initializable {
constructor(InitParams memory initDiamondCut) initializer {
_diamondCut(initDiamondCut.baseFacets, initDiamondCut.init, initDiamondCut.initData);
}
function _implementation() internal view override returns (address facet) {
facet = _facetAddress(msg.sig);
if (facet == address(0)) revert Diamond_UnsupportedFunction();
}
}
核心設計要點:
- 繼承結構:組合了
Proxy
(代理轉發)、DiamondCutBase
(切面管理)、DiamondLoupeBase
(切面資訊查詢)和Initializable
(可初始化)等核心功能 - 建構子:接受
InitParams
參數並透過_diamondCut
函數初始化基礎切面 - 代理邏輯:重寫
_implementation()
函數,根據函數簽章動態路由到對應切面(facet) - 抽象合約:自身不實現具體業務邏輯,僅提供Diamond模式的核心框架
/contracts/apps/TokenUnlocker/App.sol
設計 2.
contract TokenUnlockerApp is Diamond {
constructor(InitParams memory initDiamondCut) Diamond(initDiamondCut) {}
}
/contracts/apps/TuringMarket/App.sol
設計 3.
contract TuringMarketApp is Diamond {
constructor(InitParams memory initDiamondCut) Diamond(initDiamondCut) {}
}
應用合約設計要點:
- 輕量級實作:僅繼承
Diamond
合約並傳遞初始化參數 - 應用隔離:每個應用程式(TokenUnlocker和TuringMarket)有獨立的Diamond實例
- 建構子轉送:將
InitParams
直接傳遞給父合約,保持初始化邏輯統一
整體架構設計亮點
- 模組化設計:
- 透過Diamond模式將功能拆分為獨立切面(facets)
- 應用層與核心框架分離,方便維護與升級
- 可擴展性:
- 支援動態新增/取代/刪除功能切面
- 新應用程式只需繼承
Diamond
合約即可快速構建
- 升級安全:
- 使用
Initializable
確保初始化邏輯只執行一次 - 代理模式保證位址不變的情況下實現功能升級
- 路由機制:
- 基於函數簽章的動態路由,高效率轉送調用
- 不存在的函數會觸發
Diamond_UnsupportedFunction
異常
設計模式應用
- 代理模式:透過
Proxy
實現功能與資料分離 - 工廠模式:
InitParams
參數結構標準化初始化流程 - 組合模式:透過多重繼承組合不同功能模組
- 模板方法模式:
Diamond
合約定義框架,具體應用繼承並擴展
這種設計符合EIP-2535標準,為複雜DApp提供了模組化、可升級的架構基礎,同時保持了程式碼的簡潔性和可維護性。