區塊鏈研究實驗室|以太坊智能合約版本升級的核心方法

本文主要說明以太坊的註冊表合約、代理合約、繼承的存儲可升級性,以及更多的可升級性方法。

在軟件工程中,當發現新的bug和安全風險時,通常會對它們進行修補,並實時推送更新的版本。在智能合約開發中,可升級性並不是那麼簡單。因此,我們必須採取不同的做法。

以太坊仍處於起步階段,關於如何升級智能合約版本的爭議很多,但我們將介紹一些當今最好的選擇。

注意:智能合約版本的可升級性仍然是研究的活躍領域。以下任何一種方法都可能由於濫用或新發現的漏洞而導致智能合約失敗。

智能合約可升級性的基本方法

在這裡,我們將介紹一些更平易近人但不太適合的智能合約可升級性解決方案。儘管這些不是最佳方法,但它們是當今使用的核心。

註冊合約

註冊表合約可能是最簡單的可升級性方法,但是在這種方法,簡單性帶來了一些嚴重的缺陷。

它使用兩個智能合約的工作:註冊表合約和邏輯合約。註冊表協定僅用於將用戶指向邏輯協定的當前版本。每當邏輯合約被升級時,註冊表合約的所有者就可以更新邏輯合約被升級的地址。

區塊鏈研究實驗室|以太坊智能合約版本升級的核心方法

這種方法是非常不利的,因為當用戶想要使用合約時,他們必須首先查找當前地址。否則可能導致資金損失。將數據遷移到新合約中也非常困難,因此必須仔細考慮此過程以避免失敗。

代理合約

代理合約用於將數據和調用轉發到邏輯合約。使用代理合約,用戶可以始終調用相同的合約地址,並且將其簡單地轉發到當前邏輯合約。

區塊鏈研究實驗室|以太坊智能合約版本升級的核心方法

這種方法通過使用DELEGATECALL操作碼來工作。DELEGATECALL是EVM提供的用於程序集的操作碼。它的工作方式與普通調用類似,只是目標地址的代碼是在調用協定的上下文中執行的。這意味著像“msg.sender”和“msg.value”這樣的值將被保留。實際上,DELEGATECALL允許目標協定代表被調用方進行調用。

區塊鏈研究實驗室|以太坊智能合約版本升級的核心方法

儘管這種方法避免了與註冊表合同有關的問題,但它也有其自身的問題。 例如如果管理不當,數據存儲很容易失敗。如果新合約的存儲佈局與以前的合約不同,則數據可能已損壞。此實現還防止您從函數接收返回值,從而限制了其用例。

儲存合約

與以前的方法一樣,此方法需要您的邏輯合約以及輔助合約。在這種情況下,輔助合約是永久存儲合約。該技術通過分離邏輯和數據來起作用。邏輯合約可以隨時升級,並且由於數據存儲在外部,因此您的數據受到保護。

區塊鏈研究實驗室|以太坊智能合約版本升級的核心方法

當然,這種方法也存在根本缺陷。如果在存儲合約中發現錯誤或漏洞,則在不破壞當前數據存儲的情況下無法對其進行升級。 這種方法的另一個問題是邏輯協定需要使用額外的氣體來進行外部調用以查看或修改數據。

更合適的升級方法

現在讓我們來看看一些更復雜、更合適的智能合約升級方法。

繼承的存儲可升級性

這種技術使用三種不同的合約:代理合約來委託調用並充當永久存儲;邏輯合約將處理數據;還有存儲合約。代理合約和邏輯合約都繼承自存儲合約,因此它們的存儲引用是對齊的。

區塊鏈研究實驗室|以太坊智能合約版本升級的核心方法


當邏輯合約更新時,我們只需要更改代理合約所指向的位置即可使用僅管理員功能。由於代理和邏輯協定具有相同的存儲指針,因此無需進行外部調用即可查看和修改數據。

不幸的是,這種方法也有其自身的陷阱。由於代理合約和存儲合約都是永恆的,因此,如果在任何一個合約中發現錯誤或漏洞,都無法修復。 因此務必仔細考慮您的代理和存儲結構。

非結構化存儲可升級性

非結構化存儲可能是當前最大的可升級性方法,它使我們能夠利用存儲中狀態變量的佈局。此方法僅需要兩個合約-代理合約和實施合約-實施合約包含數據和存儲。

該技術的工作原理是將可升級性所需的數據保存在存儲中的固定位置,以防止被新數據覆蓋。我們可以使用SLOAD和SSTORE操作碼進行彙編。由於存儲插槽只是從0x0開始遞增,因此我們使用很高的存儲插槽來防止覆蓋 我們可以通過對常量變量進行散列來生成存儲槽。 由於恆定狀態變量不會佔用存儲空間,因此我們不必擔心它會被覆蓋。

區塊鏈研究實驗室|以太坊智能合約版本升級的核心方法

由於代理不再從存儲合約繼承而來,因此我們現在也可以更新存儲,從而防止存儲錯誤/漏洞變成災難性的。 但是在升級實施合約時,我們必須繼承以前的合約。由於不需要更改實施合約,因此該方法甚至可以與現有合約一起使用。

區塊鏈研究實驗室|以太坊智能合約版本升級的核心方法

儘管這可能是當前可升級性最好的方法,但也有不少批評。代理所有者擁有巨大的權力,並且需要一定程度的信任。對於更復雜的系統,這可能也不是合適的解決方案。

升級依賴於構造函數的合約

當使用依賴於構造函數的合約來設置一些初始狀態時,與代理工作並不太簡單。由於構造函數只運行一次,而代理不知道邏輯合約構造函數中設置的值,因此我們需要一種方法在代理中初始化其中的一些值。

創建邏輯合約後,EVM會丟棄構造函數,因此我們不能簡單地重用代碼。相反,我們必須採取獨特的方法來解決此問題。

初始化函數
一種可能的替代方法是在常規函數中使用構造函數代碼。我們只需確保這個函數(我們將調用初始化函數)只能運行一次。

區塊鏈研究實驗室|以太坊智能合約版本升級的核心方法

在使用初始值設定項函數時,必須打起十二分精神。考慮邏輯合約繼承的基本合約也很重要。這部分特別複雜,因為Solidity也支持多重繼承。

結論

確保智能合約是可升級的,並仔細考慮可升級過程,這兩點都很重要。雖然這並不是一個關於智能合約可升級性的選項的詳盡列表,但這應該是關於這個主題的適當指南。



分享到:


相關文章: