如何利用delegatecall進行以太坊智慧合約升級

語言: CN / TW / HK

以太坊智慧合約升級

在以太坊智慧合約的開發過程中,對於一些複雜的合約開發,要開發出完美沒有bug的智慧合約,要求是相當高的。即使編寫出來的智慧合約能完美沒有bug,也很難保證以後的需求和應用業務邏輯一成不變。所以,在開發智慧合約的同時,就要考慮好以後的合約更新和升級問題。

思路

以太坊智慧合約的更新和升級,其中一種思路就是:在智慧合約的編寫過程中,要做到資料和應用邏輯的分離。簡單來說,就是把資料和應用邏輯分別放在2個獨立的合約裡(本文稱之為資料合約和業務合約)。我們在升級合約時,保證存放資料的資料合約裡的資料結構不改變,改變的只是存放應用邏輯的業務合約。這樣才能保證原有的業務資料不被破壞和能夠繼續使用。

Solidity有三種合約間的呼叫方式 call、delegatecall 和 callcode。其中,delegatecall可作為智慧合約升級的一個較好的途徑。關於合約間的呼叫方式 call、delegatecall 和 callcode,詳見我另一篇文章<<圖文並茂詳細介紹Solidity的三種合約間的呼叫方式 call、delegatecall 和 callcode>>,有興趣的同學們可以看一下。原文連結: https://blog.csdn.net/powervip/article/details/104330170

例子

假設我們要計算一個求和公式:numC = numA + numB 我把資料numA、numB、numC作為資料存放在資料合約contract A中,把求和的業務邏輯放在資料合約contract B中。為了演示合約升級,我故意把contract B中的業務邏輯函式calcSum()中的加法運算故意寫成乘法運算,以便後面進行合約升級。程式碼不是很複雜,程式碼如下:

我們先部署合約A,再部署合約B。通過合約A的setNumA()函式把NumA設為1,通過合約A的setNumB()函式把NumB設為2,再複製合約A的地址 0x692a70D2e424a56D2C6C27aA97D1a86395877b3A。

然後,我們部署合約B,並把合約A的地址貼上到函式run_sum()的引數欄中,見下圖。執行函式run_sum()(直接點選函式名即可)。這時候,我們再點選numC,會看到numC的值為2。顯然,這不是我們想要的求和結果。

我們把函式calcSum()的 return a * b; 這句註釋掉,把 return a + b; 這句的註釋去掉,變成下面的程式碼:

先刪掉合約B(點選合約B位址列右邊的"x"),重新編譯和部署合約B,並把合約A的地址貼上到函式run_sum()的引數欄中重新執行run_sum()。這時候,我們再點選numC,會看到numC的值為3。合約B升級成功,由原來的乘法運算升級為加法運算。合約A原來的NumA和NumB的內容完美地保留了下來。

如果你覺得這篇文章寫得還可以,請幫忙點個贊,謝謝! 你的鼓勵,我的動力!

我的github: https://github.com/powervip

本文首發於: https://blog.csdn.net/powervip/article/details/105367928