在“智能合约升级原理01---起源”中介绍了合约升级的主要有三种方式:
  1. Diamond Implementation       
  2. Transparent Implementation   
  3. UUPS Implementation             
我们将只关注最常用的Transparent和UUPS,本文通过一个代码示例学习UUPS方式,最后还将给出合约升级的注意事项。
示例说明:
第一个版本的业务合约 Box,内部一个value数据,实现读、取两个方法。
第二个版本Box,稍微修改下代码。
部署后将得到代理合约地址,供应用端访问该地址。业务合约Box版本升级并不会引起代理合约地址变动,因此应用端的访问地址是稳定不变的。
1 合约代码
// SPDX-License-Identifier: MIT
pragma solidity >=0.4.22 <0.9.0;
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
contract Box is Initializable, OwnableUpgradeable, UUPSUpgradeable {
    function initialize() public initializer {
        __Ownable_init();
        __UUPSUpgradeable_init();
    }
    uint256 private value;
                          
    event ValueChanged(uint256 value);
    function store(uint256 _value) public {
        value = _value;
        emit ValueChanged(_value);
    }
    function retrieve() public view returns (uint256) {
        return value;
    }
    function _authorizeUpgrade(address newImplementation)
        internal
        onlyOwner
        override
    {}
}
2 部署智能合约
在Remix中创建新的合约文件Box.sol, 编译器版本指定为0.8.14, 编译通过。
在部署页面,Deploy按钮下方有三个可选项:
(1)DEPLOY WITH PROXY:   使用代理部署
(2)UPGRADE WITH PROXY: 使用代理升级
(3)PUBLISH TO IPFS:             发布到IPFS上
我们选择使用第一项,将自动创建代理合约,并使用代理合约部署业务合约。
点击Deploy按钮后弹出提示框,含义是部署一个实现合约,连接到一个ERC1967代理合约,并且完成实现合约的初始化。直接点击“Proceed”。

 

部署成功,在debug区域看到两笔交易,在左侧栏看到两个合约地址:
BOX合约地址: 0xf8e81D47203A594245E36C48e151709F0C19fBe8
代理合约地址: 0xD7ACd2a9FD159E69Bb102A1ca21C9a3e3A5F771B
3测试代理合约
现在我们来测试下代理合约,看看是否能读写一个基本数据:
调用代理合约的store方法, 设置value=100
调用代理合约的retrieve方法, value=100
结果是成功的。这里就证实了我们只用操作代理合约就好,不再直接操作业务合约啦!
4 升级业务合约
Box合约做个小小改动:
function retrieve() public view returns (uint256) { 
    // 修改方法 
    return value + 100; 
}
在部署页面,Deploy按钮下方有三个可选项,升级就选择第二项:
(2)UPGRADE WITH PROXY: 使用代理升级
第二项下方的“Use last deployed ERC1967 contract”,含义是使用最后一次部署的代理合约,这样就不用你手动填写代理合约地址啦。
部署成功, 左侧任务栏看到又多出了两个合约地址,一个是新版本的Box合约,一个是原来的ERC1967代理合约,这个代理合约的地址是不会改变的。
读取代理合约的retrieve方法,得到的数据是200,表明新的业务合约代码生效,原有数据也被保留下来了。
大功告成,成功的实现了业务合约的UUPS升级测试。

Logo

纵情码海钱塘涌,杭州开发者创新动! 属于杭州的开发者社区!致力于为杭州地区的开发者提供学习、合作和成长的机会;同时也为企业交流招聘提供舞台!

更多推荐