基于 Openzeppelin 的可升级合约解决方案的注意事项

注意事项

构造函数

在编写可升级合约时请不要使用构造函数contructor(),我们知道可升级合约运行时逻辑与数据分离的,合约数据保存在代理合约中,我们编写的合约是逻辑合约,当合约部署时,逻辑合约调用contructor()初始化的数据是逻辑合约的,代理合约中的数据并没有被初始化,所以是无效的。
包括全局变量声明时赋值初始值,因为这种做法相当于在构造函数contructor()中设置这些值。

父类合约初始化

如果MyContract继承自合约 BaseContract, 那么BaseContract合约的初始化函数 initialize() 的modifier(修饰器) 必须使用 onlyInitializing,比如:

contract BaseContract is Initializable {uint256 public y;function initialize() public onlyInitializing {y = 42;}
}
// BaseContract 继承自 Initializable,这里无需重复显式继承 Initializable
contract MyContract is BaseContract {int storageValue;// modifier(修饰器) initializer 可以确保initialize只会被调用一次function initialize(int initValue) public initializer {BaseContract.initialize();storageValue = initValue;}......
}

声明状态变量

  • 声明状态变量时,不能对其赋值 初始值

像这样做是错误的

contract MyContract is Initializable {int storageValue = 666; //初始值无效function initialize() public initializer {}......
}

因为这种做法相当于在构造函数contructor()中设置这些值,因此不适用于可升级的约定。

  • 定义常量状态变量仍然可以

像这样是可以的

contract MyContract is Initializable {// constant 常量关键字int public constant storageValue = 666; //有效function initialize() public initializer {}......
}

在合约代码中创建新合约实例

  • 不要在合约中创建新的合约实例,创建出的合约是不可升级的

像这样,即使MyContract是可升级的,但 ERC20 实例不可升级

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";contract MyContract is Initializable {ERC20 public token;function initialize() public initializer {token = new ERC20("Test", "TST"); // 这个合约是不可升级的}......
}
  • 如果你希望在MyContract引用其他可升级合约,那么将已部署好的可升级合约实例注入到MyContract中,是很好的解决方案

像这样

import "@openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol";contract MyContract is Initializable {IERC20Upgradeable public token;function initialize(IERC20Upgradeable _token) public initializer {token = _token;}......
}

升级合约时声明状态变量

在编写合约的新版本时,无论是由于新功能还是 bug 修复,还有一个额外的限制需要遵守:不能更改合约状态变量的声明顺序,也不能更改其类型。

比如当前版本(V1)合约状态变量布局

contract MyContractV1 {uint256 private x;string private y;
}

那么在编写新版本合约时,请避免一下错误操作:

  • 更改变量的类型

这是错误的

contract MyContractV2 {string private x;string private y;
}
  • 更改声明它们的顺序

这是错误的

contract MyContractV2 {string private y;uint256 private x;
}
  • 在现有变量之前引入一个新变量

这是错误的

contract MyContractV2 {bytes private a;uint256 private x;string private y;
}

这是正确的

contract MyContractV2 {uint256 private x;string private y;bytes private a;
}
  • 删除现有变量

这是错误的

contract MyContractV2 {string private y;
}

参考文档:
Openzeppelin编写可升级合约:https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable

基于 Openzeppelin 的可升级合约解决方案的注意事项相关推荐

  1. conflux开发NFT智能合约(ERC721 工厂合约 可升级合约)

    以下场景可借鉴本文内容 需要创建很多合约 需要使用conflux代付机制(只需将工厂合约设置为代付,即可无限创建新合约) 合约想要有可升级的能力(如:特殊玩法 or 代码有bug) ERC-721 N ...

  2. #研发解决方案介绍#基于ES的搜索+筛选+排序解决方案

    郑昀 基于胡耀华和王超的设计文档 最后更新于2014/12/3 关键词:ElasticSearch.Lucene.solr.搜索.facet.高可用.可伸缩.mongodb.SearchHub.商品中 ...

  3. 基于XML的可升级矢量图像(SVG)浅析

    基于XML的可升级矢量图像(SVG)浅析 级别: 初级 吴高峰 (wugfeng@263.net )上海大学计算机系 2001 年 8 月 01 日 SVG是基于XML的专门为网络而设计的图像格式.本 ...

  4. 基于至强® 平台的内存数据库解决方案

    基于至强® 平台的内存数据库解决方案 英特尔与 SAP 之间的协作和联合开发已持续六年. · SAP HANA 平台的创新内存架构契合持久内存,仅需少量变更. · SAP HANA 平台是第一个支持英 ...

  5. 基于.Net的单点登录(SSO)解决方案

    基于.Net的单点登录(SSO)解决方案 前些天一位朋友要我帮忙做一单点登录,其实这个概念早已耳熟能详,但实际应用很少,难得最近轻闲,于是决定通过本文来详细描述一个SSO解决方案,希望对大家有所帮助. ...

  6. 基于webpack的前端工程化开发解决方案探索(一):动态生成HTML

    基于webpack的前端工程化开发解决方案探索(一):动态生成HTML 参考文章: (1)基于webpack的前端工程化开发解决方案探索(一):动态生成HTML (2)https://www.cnbl ...

  7. Spring Boot之基于Redis实现MyBatis查询缓存解决方案

    转载自 Spring Boot之基于Redis实现MyBatis查询缓存解决方案 1. 前言 MyBatis是Java中常用的数据层ORM框架,笔者目前在实际的开发中,也在使用MyBatis.本文主要 ...

  8. 数字孪生体技术白皮书_基于Flownex的数字孪生体解决方案 系列介绍之二:数据中心应用实例...

    致力于数字孪生体技术的研究与发展 通过解决方案和工程化应用造福人类 来源:数字孪生体实验室原创 作者:王永康 转载请注明来源和出处 导  读 <基于Flownex的数字孪生体解决方案>是我 ...

  9. 遇见未来 | 基于软件定义存储的数据加速解决方案:让你的系统加速跑

    在互联网和大数据的压力下,很多企业面临着经济增长下滑.跨行业竞争激烈,用户需求越来越个性化.于是如何实现转型.业务创新和盈利增长成为企业的共同诉求. 而依靠硬件的提升获取系统性能大幅度提升的日子已经一 ...

最新文章

  1. 特斯拉打响自动驾驶芯片反击战!
  2. 加速100倍,性能媲美SOTA,浙大知识蒸馏新方法FastDFKD
  3. Linux中SysRq的使用[zt]
  4. php excel 读取日期问题
  5. byte 8位有符号 与 char 16位无符号
  6. “蚂蚁行军”和彩色边框设计
  7. selenium 简介
  8. web mis系统构建
  9. 新计算机 安装win2000,虚拟机安装Windows 2000超详细教程
  10. 机器学习模型评估方法
  11. 搞机吧 | 利用magisk安装Xposed框架
  12. git add所有文件
  13. insmod 时报错“Unknown symbol”问题的解决
  14. 如何基于IM SDK从零开发移动端聊天功能
  15. 手机电子邮件设置exchange方式登录163邮箱
  16. 电视剧《天道》里的商业思维
  17. 关于斐讯K2路由器 j.s9w.cc 劫持的问题。
  18. mysql数据库怎么解锁表_MySQL数据库如何锁定与解锁数据库表?
  19. 安卓的绝对布局AbsoluteLayout
  20. 数据库从入门到删库跑路(二) - - PL/SQL

热门文章

  1. 如何利用API实现行式报表后台导入excel数据入库
  2. 想成为一名数据库工程师,你必须知道这些
  3. h5游戏接入googleplay时遇到的问题总结
  4. php程序主入口,主:(index.php)入口
  5. DELPHI中拖放的操作
  6. 文艺范儿的程序猿和攻城狮们
  7. 飞机上最安全的座位在哪里?
  8. Ubuntu 设置 OpenDNS
  9. 表格的列标题具有排序功能可便于读者查阅
  10. java中让步的_java 多线程—— 线程让步