id:BSN_2021
公众号:BSN研习社

背景:在开发或维护solidity语言的智能合约时,经常会因为业务逻辑变动而变动合约内的逻辑,这就要考虑在不影响以前智能合约中已上链的数据的同时,修改或扩展新的业务逻辑,所以合约第一次开发时就需要考虑其本身支持可升级功能

目的:本篇文章是为了让读者快速上手使用hardhat并搭配openZeppelin的uups升级模式对合约进行可升级适配以及指导后续如何进行合约升级

适用对象:适用于BSN开放联盟链武汉链(基于ETH),也可适用于其他支持solidity语言的链框架

如何使用hardhat进行合约uups模式升级

  • 安装hardhat
  • 初始化项目
  • 编写合约
  • 编写测试文件
  • 编辑配置文件
  • 执行项目
  • 参考

安装hardhat
1.创建空的文件夹demo-uups并进入文件夹里面,执行npm init
2.执行安装命令npm install --save-dev hardhat
3.安装依赖npm install --save-dev @nomiclabs/hardhat-waffle ethereum-waffle chai @nomiclabs/hardhat-ethers ethers
4.安装openZeppelin的uups可升级合约包 npm install --save-dev @openzeppelin/contracts-upgradeable
5.安装测试工具mocha npm install --save-dev mocha
初始化项目
执行npx hardhat选择Create a basic sample project

初始化完成后的目录结构为

编写合约

在contracts目录下面新建两个名称分别为MyLogicV1和MyLogicV2的.sol文件并进行代码编写。实现openZeppelin的uups升级模式必须要引入openZeppelin相关库文件,且必须在constructor()方法上加@custom:oz-upgrades-unsafe-allow constructor字样注释


// contract/MyLogicV1.sol// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";contract MyLogicV1 is Initializable, UUPSUpgradeable, OwnableUpgradeable {function initialize() initializer public {__Ownable_init();__UUPSUpgradeable_init();}/// @custom:oz-upgrades-unsafe-allow constructorconstructor() initializer {}function _authorizeUpgrade(address) internal override onlyOwner {}mapping(string => uint256) private logic;event logicSetted(string indexed _key, uint256 _value);function SetLogic(string memory _key, uint256 _value) external {logic[_key] = _value;emit logicSetted(_key, _value);}function GetLogic(string memory _key) public view returns (uint256){return logic[_key];}
}

// contract/MyLogicV2.sol// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";contract MyLogicV2 is Initializable, UUPSUpgradeable, OwnableUpgradeable {function initialize() initializer public {__Ownable_init();__UUPSUpgradeable_init();}/// @custom:oz-upgrades-unsafe-allow constructorconstructor() initializer {}function _authorizeUpgrade(address) internal override onlyOwner {}mapping(string => uint256) private logic;event logicSetted(string indexed _key, uint256 _value);function SetLogic(string memory _key, uint256 _value) external {logic[_key] = _value;emit logicSetted(_key, _value);}function GetLogic(string memory _key) public view returns (uint256){return logic[_key]+100;}
}

MyLogicV1实现了一个对于logic的map的写入方法和读取方法,MyLogicV2只是改写了MyLogicV1的GetLogic方法中的处理逻辑,使得每次返回的值加了100

编写测试文件
在test目录下创建生成名称为update-test的.js文件并进行代码编写


// test/update-test.ts
const { expect } = require('chai');
const { ethers, upgrades } = require('hardhat');let myLogicV1;
let myLogicV2;describe('uups mode upgrade', function () {it('deploys', async function () {const MyLogicV1 = await ethers.getContractFactory('MyLogicV1');myLogicV1 = (await upgrades.deployProxy(MyLogicV1, {kind: 'uups'}));console.log(myLogicV1.address);})it('myLogicV1 set', async function () {await myLogicV1.SetLogic("aa", 1);expect((await myLogicV1.GetLogic("aa")).toString()).to.equal('1');})it('upgrades', async function () {const MyLogicV2 = await ethers.getContractFactory('MyLogicV2');myLogicV2 = (await upgrades.upgradeProxy(myLogicV1, MyLogicV2));console.log(myLogicV2.address);})it('myLogicV2 get', async function () {expect((await myLogicV2.GetLogic("aa")).toString()).to.equal('101');})
})

测试文件步骤详解

  • deploys: 调用upgrades中的deployProxy方法以uups的方式部署MyLogicV1合约
  • myLogicV1 set:调用MyLogicV1合约中的SetLogic方法将值传入,并调用GetLogic方法确认返回值为1
  • upgrades:调用upgrades中的upgradeProxy方法升级
  • myLogicV2 get:调用MyLogicV2合约中的GetLogic方法确认返回值为101

编辑配置文件
编辑hardhat.config.js文件


require("@nomiclabs/hardhat-waffle");
require('@openzeppelin/hardhat-upgrades');// This is a sample Hardhat task. To learn how to create your own go to
// https://hardhat.org/guides/create-task.html
task("accounts", "Prints the list of accounts", async (taskArgs, hre) => {const accounts = await hre.ethers.getSigners();for (const account of accounts) {console.log(account.address);}
});// You need to export an object to set up your config
// Go to https://hardhat.org/config/ to learn more/*** @type import('hardhat/config').HardhatUserConfig*/
module.exports = {solidity: {version: "0.8.4",settings: {optimizer: {enabled: true,runs: 200}}},mocha: { timeout: 60000 }
};

执行项目
1.执行编译合约
npx hardhat compile

2.启动本地测试节点
npx hardhat node

3.新开一个窗口运行测试文件
npx hardhat test test/update-test.js --network localhost

测试通过,合约地址都为代理合约地址,测试说明成功升级改写了GetLogic中的处理逻辑,使得每次返回的值都在原来的基础上多加了100

参考

Hardhat官方文档:Overview | Hardhat | Ethereum development environment for professionals by Nomic Foundation[1]

OpenZeppelin官方文档:Using with Upgrades - OpenZeppelin Docs[2]

References

[1] Overview | Hardhat | Ethereum development environment for professionals by Nomic Foundation: https://hardhat.org/getting-started/
[2] Using with Upgrades - OpenZeppelin Docs: https://docs.openzeppelin.com/contracts/4.x/upgradeable

如何使用hardhat进行合约uups模式升级相关推荐

  1. 固化EOS智能合约,监管升级权限,净化EOS DAPP生态

    最近EOS版的Fomo 3D狼人杀游戏骗局引发了大家对EOS智能合约的安全性的大讨论. 和以太坊智能合约的不可升级不同,EOS智能合约可升级,因而保存在智能合约中的数据称不上去中心化,因为智能合约的管 ...

  2. 手机淘宝轻店业务 Serverless 研发模式升级实践

    简介:随着 Serverless 在业界各云平台落地,阿里内部 Serverless 研发平台.各种研发模式也在业务中逐步落地,如火如荼.在此契机下,淘系团队启动了轻店 Serverless 研发模式 ...

  3. 合约 cd 模式_CD的完整形式是什么?

    合约 cd 模式 CD:光盘 (CD: Compact Disc) CD is an abbreviation of "Compact Disc". CD是" Compa ...

  4. AutoScaling 成本优化模式升级--混合实例策略

    伸缩组成本优化模式以成本为目标,始终创建最低价的实例,同时,通过多可用区,多实例规格分布,以此来提高服务稳定性.但是,对于成本优势最大化的竞价实例,伸缩组难以防范竞价实例大范围回收可能导致的服务雪崩, ...

  5. 开启xmp1还是2_“吃鸡”新版本倒计时1天,2个经典模式升级回归,老玩家泪目了!...

    早在此次体验服开启11月份新版本测试之后,数以百万计的玩家们就已经开始等待正式服的新版本跟新了.现如今,光子也终于正式官宣:"流星雨"主题的新版本倒计时1天. 而接下来本期的&qu ...

  6. 人人车否认破产称地方经营型模式升级为合伙人模式

    原标题:人人车否认破产辟谣撤离地方分公司传言称地方经营型模式升级为合伙人模式 ■本报记者 李乔宇 春节刚过,又有一家互联网公司"被破产". 日前,关于汽车交易服务平台人人车宣布破产 ...

  7. 懒猫社长新便民工程119模式升级:践行“便利店+”战略,推进多元化产业链构建

    就在4月初刚刚结束的"『实体大趋势 零售新未来』2019年互联网+新零售财富峰会暨懒猫社长新便民工程119模式升级发布会"上,猫友股份杨迎宾首次公布全新升级内容,融合多9大商业场景 ...

  8. 华为数字化转型之道 实践篇 第九章 数字化运营:实现业务运营模式升级

    第九章 数字化运营:实现业务运营模式升级 业务运营是为了帮助企业基于自身业务战略,更好地达成企业经营与运营目标,这中间包含业务沿着流程周而复始地运转,以及在作业过程中识别并推动问题解决等过程. 而数字 ...

  9. GMTC 2021 演讲 《字节跳动基于 Serverless 的前端研发模式升级》

    点击上方 程序员成长指北,关注公众号 回复1,加入高级Node交流群 大家好,我叫王磊,来自于字节跳动 Web Infra,今天由我给大家分享<字节跳动基于 Serverless 的前端研发模式 ...

最新文章

  1. 《强化学习周刊》第32期:上海交大华为 | 可解释强化学习研究综述
  2. 德国Renusol进军南非市场 瞄准屋顶光伏
  3. 并查集 poj1182
  4. 【ARM】Tiny4412裸板编程之异常(软中断)
  5. ClassUtils常用方法总结,java核心技术第九版百度网盘
  6. No module named MNIST_NBA十大面具侠:NO.1 竟然是他!
  7. 小学的题 大学的解法
  8. Java Integer 对象的比较
  9. 用SPSS做正态分布检验
  10. 二级c语言vc2010下载,全国计算机等级考试二级C语言考试系统下载
  11. 在python2里怎么使用ttk_关于用户界面:python 2.7中的Tkinter和ttk
  12. 手机无线鼠标服务器.zip,无线鼠标遥控器_Remote Mouse 1.0双版 用手机遥控你的电脑...
  13. 将hexo博客部署到阿里云服务器
  14. 2020第四届全球程序员节观后感
  15. SVN中tag和branch的区别
  16. Log4j 2.x入门
  17. oracle实体视图日志,Oracle案例02——ORA-12034: SCOTT.USER_TABLE 上的实体化视图日志比上次刷新后的内容新...
  18. 前端入门自学资料汇总
  19. VS中使用 loadimage()函数载入图像报错与图像无法载入的解决办法
  20. SUNDE桌面云推动班班通工程建设步伐

热门文章

  1. Apache 屏蔽YisouSpider一搜蜘蛛神马的方法
  2. 外包公司,真的是互联网“二等公民”吗?
  3. OpenStack 运维 - 部署Nova组件 [T版]
  4. svg loading效果(上百个)
  5. 开始学习SHAREPOINT 2003。
  6. word中的字号相当于多少px
  7. 深度学习笔记3——AlexNet
  8. Axure无法同时打开多个.rp文件
  9. Ubuntu开机黑屏且左上角闪烁光标,登录页面键盘鼠标无响应的解决方法
  10. CPU到计算机刷新速度,计算机CPU运算速度是多少