「读书笔记」可升级智能合约 Upgradable Smart Contract

为什么需要可升级智能合约?

由于区块链的不可篡改性,合约在部署至区块链后,其代码无法更改。

常见的情况是,当发现合约有bug,或者需要加入新功能时,则需重新发布合约,而且要将数据进行转移,同时还要通知所有用户使用新的合约地址,整个过程十分繁琐。

可升级智能合约就是为了解决以上问题。

什么是可升级智能合约?

可升级合约采用「代理 - 实现」模式,只需要更改delegatecall所指向的合约地址,就可以做到宛如修改了合约内容一样的效果。

能实现上述代理效果,理解delegatecall非常重要。

post image

Call和delegatecall

Call和delegatecall是Solidity中调用其他合约的两种方法,两者有较大区别。

当合约A使用call调用合约B时,使用的是合约B的上下文,修改的是合约B的内存插槽值。

当合约A使用delegatecall调用合约B时,使用的是合约A的上下文,修改的也是合约A的内存插槽值。

Delegatecall可以被简单理解为将合约B的代码复制粘贴到A中执行,因为只是复制粘贴,因此所有状态和数据都保存在A中。

两种可升级智能合约模式

  1. Transparent Proxy Pattern

  2. UUPS Proxy (Universal Upgradeable Proxy Standard)

下面的部分,首先会通过Transparent Proxy Pattern来进一步理解可升级合约的原理,接下来再指出UUPS Proxy的不同之处。

Transparent Proxy Pattern

Transparent Proxy Pattern包含三个部分,「代理合约」,「管理者合约」和「逻辑/实现合约」。

post image

代理合约:EOA是与代理合约进行交互。代理合约在收到交互请求后,通过delegatecall调用逻辑/实现合约内的程式码进行处理。由于delegatecall的特征,所有业务数据(例如合约的state和合约内的财产),都依然保存在代理合约中。

管理者合约:管理者合约是代理合约的管理员,可以对指定代理合约进行逻辑升级。

逻辑/实现合约:逻辑/实现合约包含真正的合约业务逻辑,也是我们能‘修改’的合约内容所在。同一时间代理合约只会指向一个逻辑/实现合约。

UUPS Proxy

Transparent Proxy Pattern和UUPS Proxy的实现基础是一样的,都是使用delegatecall将逻辑合约剥离主合约。

两者最明显的差异是升级逻辑所在的位置:UUPS Proxy的升级逻辑是由逻辑/实现合约完成。而Transparent Proxy的升级逻辑是由代理合约完成,且需要部署额外的管理员合约。

由于UUPS Proxy的升级是由逻辑/实现合约控制,人们可以随时终止合约的可升级性。

UUPS Proxy合約的部署成本低于Transparent Proxy。

Etherscan能识别出可升级合约

当在contract页面看到Read as Proxy和Write as Proxy两个按钮,则说明这是一个可升级合约。

  • 如果你要执行代理合约的函数,则用原本的Read和Write。

  • 如果你要执行逻辑/实现合约的函数,则使用Read as Proxy和Write as Proxy。

post image

在contract name处有时也会标注出是否为代理合约,例如ERC721DropProxy,TransparentUpgradeableProxy,CErc20Delegator等。

post image

当点击Read as Proxy/Write as Proxy,可以看到逻辑/实现合约的地址,以及该可升级合约所用的模式是什么。

post image

最后,你也可以使用Etherscan提供的Proxy Contract Verification来查询该合约是否为可升级合约。

几个可升级合约的例子:

Reference

本篇读书笔记是对以下文章的内容摘抄和观点提炼,更详细的内容可以阅读以下文章哇,尤其是具体的合约部署方法~