关于智能合约:OpenZeppelin可升级智能合约

3次阅读

共计 2041 个字符,预计需要花费 6 分钟才能阅读完成。

可降级智能合约

明天分享下 openzeppelin 的 Upgradeable Smart Contract,就是可降级智能合约。

咱们先看下如何用这个提供的插件来写智能合约,而后再来介绍下外面的原理和实现逻辑。

首先咱们来看一个失常的合约,一个合约里有初始化构造方法,咱们把这个构造方法替换成 initialize 办法。咱们先不思考为什么这么做,先看下应用,前面再去看原理。

比方这个 MYcontract 合约,把它的构造方法换成 initialize,因为构造方法其实只能被调用一次,为了防止出现被谬误调用,所以这里加了一些条件限度。

很早以前某篇文章里介绍智能这种编程形式也叫,面向条件的编程。无论是一般合约逻辑的编写,还是在平安方面做的一些爱护,比方防重入攻打,都有这个条件编程的思维。

咱们接着介绍。

其实每次这样去写这个 initialize 的办法很麻烦。

所以 openz 帮咱们实现了一些逻辑,咱们只有继承就好,平时写合约的时候,实际上还有一些合约继承的货色,这种状况就要略微解决下:

如果应用 erc20 这种合约呢?

其实 openz 也提供了规范可降级的 erc20 的实现,把原来继承 erc20,间接替换掉就好了。

还要留神一点,就是在变量申明的时候,不要做初始化,Avoiding Initial Values in Field Declarations。

比方这个:

这种相当于,咱们写了一个构造方法,而后在构造方法里初始化这个 storage。须要把它改成上面这样的。

还有一种是常量:

这种实际上是编码在合约code里的。

咱们在部署合约的时候,evm 实际上在实现构造方法后,构造方法这段代码实际上就没有保留在合约地址下的 code 的,因为反正只是在部署的时候用。

然而初始化的常量实际上会追随这个合约 code,保留在合约地址下的代码里。这个初始化里结构的变量也是以 storage 的模式存下来的。在初始化合约的时候,可能在初始化办法中会创立一个新的合约实例。

比方这种:

这外面的 erc20 合约实际上是不反对降级的,如果想要这个合约反对降级怎么解决呢?

理论就是先部署外面的合约,而后在初始化的时候把这个合约地址再传进去就好了:

在降级合约的时候也要留神几点:

第一,不要更改原有的 storage。

比方原来是这样:

咱们不能把这个变量类型改掉。

也不能换程序。

也不能在后面插入一个变量。

能做的是,能够给这个变量换个名字,或者在前面追加一个变量,比方这个:

就是加在最初。

当然还有其余的谬误应用状况,大家能够看它们的官网文档。

这个原理的实现其实很简略,就是用了一个代理合约:

用户调用的始终都是这个代理合约,具体的实现合约能够换掉,而后把地址绑定到这个代理合约之内。

咱们看下这个代理合约的大抵的逻辑思路:

这个是 assembly 写的。

第一步就是把 calldata 拷贝进去,就是交易里的 data,第二步骤就是用这个 delegatecall,而后第三就是获取 return data,第四就是再把这个 returndata 返回。

咱们次要看这个 delegatecall。

solidity 里有几种 call,大家能够比照下这几个的区别。

这个其实就是把指标合约的 code 在以后合约的环境下执行,应用以后合约的 storage,逻辑合约的代码其实是被执行了,然而逻辑合约的 storage 其实是没有用的,它用的是在代理合约的 storage。所以合约在初始化的时候,如果用 solidity 的构造方法,storage 就留在逻辑合约里了,所以后面的把结构合约该成 init 就是这个情理,通过代理合约来调用 iinit,这些 storage 就留在这个代理合约里了。

前面就能够继续降级。

方才讲到在代理合约里保留逻辑合约的 stroage,这里就有一个问题,就是原来代理合约因为也要保留逻辑合约的地址。比方在代理合约里申明了一个 stroage,因为在 solidity 实现的时候,它会把这个 storage 给一个 postion,而后实际上是依照它申明的地位来确定最终在合约上面的形象模型里的 kv 里存的地位的。

比方咱们申明了三个变量:

这三个实际上存在哪里是跟他的 position 无关的,就是变量的程序。

而后这里可能就有一个问题:

Proxy 这里的 storage,比方第一个和逻辑合约里的第一个 storage,因为都是第一个,都存到 proxy 合约里,就抵触了。

这时,给它一个随即的 slot 就能够了。

原理很简略,理论就是算一个随机的数,而后用 solidity 的 assembly 语言里的一个设置 stroage 的命令,设置这个值就好了,这样就解决了代理合约和实现合约里的 stroage 抵触的问题。

在实现合约里,因为 stroage 无论怎么降级都是专用的代理合约里的,所以这里不能批改原来的 stroage,要不然就抵触了。

在应用上,openz 和 truffle 也好,还有和一些其余的合约开发工具都是做了集成,应用起来都还是比拟不便的。

文章起源:溪塔科技
文章原题目:《技术沙龙 | 可降级智能合约》
如有侵权请与咱们分割删除。

正文完
 0