智能合約開發

UUPS 代理

UUPS——通用可升級代理標準(EIP-1822)——是一種較精簡的可升級模式。與其讓代理攜帶升級機制,改由實作合約攜帶它。代理本身因此變得微小又便宜:它只是把一切 delegatecall 出去。你部署的每一個實作都必須記得包含升級函數,否則可升級性就會喪失。

具體而言,upgradeTo 邏輯住在實作裡(OpenZeppelin 的 UUPSUpgradeable 混入提供它),由一個你以自己的存取控制覆寫的 _authorizeUpgrade 鉤子把關——通常是 onlyOwner。由於沒有像透明模式那樣在每次呼叫都做「誰在呼叫」的管理員檢查,代理較小、每次呼叫的 gas 較低。管理員與使用者函數之間的選擇器碰撞在結構上被避免,因為升級函數單純住在實作自己的命名空間裡,而非代理的。

鋒利之處在於:可升級性如今是實作的屬性,而非代理的。若你曾升級到一個忘了繼承升級函數(或其 _authorizeUpgrade 會回滾)的實作,該合約就變成磚塊:永遠凍結在那個版本,因為唯一能把代理指向別處的程式碼,剛被一段缺少它的程式碼取代了。OpenZeppelin 在升級時加入回滾/相容性檢查來捕捉這點,但底層的責任——每個新實作都必須維持可升級——永遠不會消失。

contract MyLogic is UUPSUpgradeable, OwnableUpgradeable {
  function _authorizeUpgrade(address newImpl)
    internal override onlyOwner {}
  // upgradeTo() lives here, in the implementation
}

代理更便宜,但每個實作都必須維持可升級。

UUPS 的危險與其經濟性源於同一處:升級函數住在實作裡。發布一個沒有它的實作,合約就再也無法升級——每次升級前都要驗證可升級性。

又称
Universal Upgradeable Proxy Standard