OpenZeppelin 可昇級合約插件 2/9 專有名詞解釋及FAQ

以太坊 ethereum andy 4年前 (2020-10-12) 1399次浏览 已收录 0个评论 扫描二维码
文章目录[隐藏]

OpenZeppelin 可昇級合約插件 2/9 專有名詞解釋及FAQ

合約昇級可以更換 Solidity 的編譯器嗎?

可以, Solidity 保証存儲格式是跨編譯器的。

為什麼有這個錯誤訊息”Cannot call fallback function from the proxy admin”?

這是由於 透明代理模式 的限制。正確使用 OpenZeppelin 的可昇級合約插件不會有這個訊息。插件使用 ProxyAdmin 合約來管理所有代理合約。
但是如果使用 OpenZeppelin 建議的合約代理寫法來寫程式,就可能潛在地引發這個錯誤。解決的方式就是使用一般的帳號地址來跟合約交互,而不要使用 代理管理的帳號地址。除非你指定調用代理合約本身的函數。
透明代理模式 請參考 https://docs.openzeppelin.com/upgrades-plugins/1.x/proxies#transparent-proxies-and-function-clashes

什麼是可安全昇級的智能合約?

在部署合約的代理時,有一些合約代碼限制要遵守。特別是合約不能使用建構函數 constructor ,而且不應該使用 selfdestruct 或是 delegatecall

作為建構函數的替代品,一般使用 initialize 函數來初始化合約。可以繼承 Initialzable 合約,這個合約已經實作了一個只能調用一次的初始化函數。

OpenZeppelin 可昇級合約插件 2/9 專有名詞解釋及FAQ

Truffle 及 Buidler 插件都會驗証這些部署及編譯的規則,更詳細的內容可以參考 https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable

什麼是實現相容性?

當昇級代理合約時,這代表從一個功能實作合約昇級到另一個功能實作合約,這兩個合約的存儲(狀態變數等)必須要相容。這表示,就算完全改變代碼的功能,也不能修改已經存在的狀態變數。唯一可以的是增加新的狀態變數。

Truffle 及 Buidler 插件都會驗証新的功能實作合約是否相容於前一個。但是現在插件還不支持自訂型態(struct 跟 enum) 。可以在 deployProxyupgradeProxy 裡設定 unsafeAllowCustomTypes 為 True 來強制使用自訂類型。
如何修改功能實作合約成為存儲相容,可以參考 https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable#modifying-your-contracts.adoc

什麼是代理管理 proxy admin?

ProxyAdmin 是一個合約,是所有代理合約有擁有者。只有一個合約管理員被部署。當你開始一個項目,ProxyAdmin 的擁有者是部署者的地址,但你可以調用 transferOwnership 來轉換所有權。有關這個合約更詳細的內容可以參考 https://docs.openzeppelin.com/cli/2.8/contracts-architecture#proxyadmin.sol

什麼是功能實作合約 ?

可昇級的部署需要2種合約:代理合約跟功能實作合約。代理合約是跟用戶實作的那個合約。功能實作合約則是實際存放代碼的合約。如果你對功能實作合約調用 deployProxy 數次,就會部署數個代理合約,但是只有一個功能實作合約被使用。
如果你昇級代理合約到一個新的版本,新的功能實作合約應該是已經部署好的,代理合約也應該被設定為使用新的功能合約。更詳細的內容請參考代理昇級模式https://docs.openzeppelin.com/upgrades-plugins/1.x/proxies。

什麼是代理?

一個代理,表示是一個合約被委派了另一個合約的調用,另一個合約稱為功能實作合約。就是你調用 A代理合約的X函數,他會去調用 B功能實作合約的X函數,這個 A合約就是代理合約,代理了 B合約。
所有的狀能及資金都存放在代理合約,但是實際執行在功能實作合約上。所以代理合約,可以被管理員用不同的功能實作合約昇級。詳細內容參考代理昇級模式https://docs.openzeppelin.com/upgrades-plugins/1.x/proxies。

為什麼不能用 immutable 變數?

Solidity 0.6.5 介紹了關鍵字 immutable ,定義了變數只能在建構時分配一次,並且在建構之後是唯讀的狀態。做法是在合約建構時計算出變數的值,然後把值直接存在 bytecode 裡面(bytecode是存放代碼的地方,意思是把值當成代碼存放,好處是減少很多燃料消耗)

注意,這是不相容於可昇級合約的,理由有兩點:
1、可昇級合約沒有 constructor 建構函數,取而代之的是 intializer 初始化函數。因此無法使用 immutable 變數。
2、由於 immutable 變數的值存放於 bytecode 裡面,因此所有的代理合約都可以指向這個值,而不是每個代理合約的存儲位置。

為什麼不能使用擴展程式庫?

現在插件還不支持合約連結到擴展程式庫。這是因為在編譯時不知道要連結到哪個功能實作合約,這將會非常難以保証昇級安全成功。
有計畫在不久的將來加入某些限制來達成這個功能,使得這類的問題更容易解決,例如假設程式庫的代碼存在於代碼庫中。或是已經部署並上鏈,可以被拿來分析檢測。

為什麼不能使用自訂的 struct 或是 enums?

以目前 2020.10 來說,插件還不支持自訂類型實作的可昇級合約,包括自訂的 structs 或 enums 及擴展程式庫。這是因為需要檢查附加產生的複雜度所導致的。
同時 Openzeppeline 也鼓勵用戶,不要使用這些自訂類型,或者手動檢查存儲相容性,並且在 deployProxy upgradeProxy prepareUpgrade 函數裡利用 unsafeAllowCustomTypes 旗標。如果不知道如何手動檢查的話,可以在討論區 https://forum.openzeppelin.com/ 裡討論。

為什麼在 Truffle 環境底下必須重新編譯合約?

在 Truffle 的 build/contracts 目錄底下,每一個合約都有一個稱為 AST (abstract syntax tree) 的檔案,這些檔案以 JSON格式記錄合約的摘要。合約昇級插件用這個檔案來驗証合約是不是能被安全的昇級。
Truffle 有時只在這個檔案有變化時才會重新編譯合約。所以只有你手動的輸入 truffle compile --all 才能重新編譯所有的合約,或是刪除 build/contacts 底下的所有檔案。
技術上來說,Solidity 不會產生這些 AST 檔案,如果合約不是同一個編譯器來編譯的話,插件就無法正確地解析引用。

參考

https://docs.openzeppelin.com/upgrades-plugins/1.x/faq


神隊友學長Andy , 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权
转载请注明原文链接:OpenZeppelin 可昇級合約插件 2/9 專有名詞解釋及FAQ
喜欢 (0)
[[email protected]]
分享 (0)
andy
关于作者:
中年大叔,打拼 like young students.
发表我的评论
取消评论
表情 贴图 加粗 删除线 居中 斜体 签到

Hi,您需要填写昵称和邮箱!

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址