如何利用delegatecall进行以太坊智能合约升级

如何利用delegatecall进行以太坊智能合约升级

## 以太坊智能合约升级 在以太坊智能合约的开发过程中,对于一些复杂的合约开发,要开发出完美没有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()中的加法运算故意写成乘法运算,以便后面进行合约升级。代码不是很复杂,代码如下: ![img](https://img-blog.csdnimg.cn/20200407170304228.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3Bvd2Vydmlw,size_16,color_FFFFFF,t_70) 我们先部署合约A,再部署合约B。通过合约A的setNumA()函数把NumA设为1,通过合约A的setNumB()函数把NumB设为2,再复制合约A的地址 0x692a70D2e424a56D2C6C27aA97D1a86395877b3A。 然后,我们部署合约B,并把合约A的地址粘贴到函数run_sum()的参数栏中,见下图。运行函数run_sum()(直接点击函数名即可)。这时候,我们再点击numC,会看到numC的值为2。显然,这不是我们想要的求和结果。 ![图2 部署合约B,并把合约A的地址粘贴到函数run_sum()的参数栏中](https://img-blog.csdnimg.cn/20200407170902987.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3Bvd2Vydmlw,size_16,color_FFFFFF,t_70) 我们把函数calcSum()的 return a * b; 这句注释掉,把 return a + b; 这句的注释去掉,变成下面的代码: ![图3 升级后的合约代码](https://img-blog.csdnimg.cn/2020040717185873.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3Bvd2Vydmlw,size_16,color_FFFFFF,t_70) 先删掉合约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

以太坊智能合约升级

在以太坊智能合约的开发过程中,对于一些复杂的合约开发,要开发出完美没有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

本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

  • 发表于 2021-10-20 16:05
  • 阅读 ( 362 )
  • 学分 ( 6 )
  • 分类:智能合约

评论