OpenZeppelin SDK 可升级合约速食指南 – Mark.Ro
配置全局工具
# 全局 ganache可以用GUI版本
yarn global add truffle ganache-cli
yarn global @openzeppelin/cli
项目初始化
truffle init
# 生成相关配置
.openzeppelin
openzeppelin init
# 链接以太坊包,如果是测试环境则需要push openzeppelin link @openzeppelin/contracts-ethereum-package
# 执行完成后,会出现
.openzeppelin文件夹,内有[net]-[chainId].json配置文件
新增合约Conter.sol
pragma solidity ^0.5.0;
contract Counter
}
编译合约
openzeppelin compile
# 可以不使用truffle compile --all ➜ zacian git:(develop)
✗ openzeppelin compile
✓ Compiled contracts with solc 0.5.13 (commit.5b0b510c)
部署合约
openzeppelin create
# 这里会选择部署的合约名称,不再是编写部署脚本
➜ zacian git:(develop)
✗ openzeppelin create Nothing to compile, all contracts are up to date.
? Pick a contract to instantiate Counter
? Pick a network development
✓ Added contract Counter
✓ Contract Counter deployed All contracts have been deployed
? Call a function to initialize the instance after creating it? No
✓ Setting everything up to create contract instances
✓ Instance created at 0x379e8403632013fFf3D0C03d14AD71C958071FAf
调用合约
openzeppelin send-tx
# 可以直接解析着调用
➜ zacian git:(develop)
✗ openzeppelin send-tx
? Pick a network development
? Pick an instance Counter at 0x379e8403632013fFf3D0C03d14AD71C958071FAf
? Select which function increase()
✓ Transaction successful. Transaction hash: 0xa6415d16225bc65e158a5187fca2984402b7d57ca9154d61527d0c559c8417e7
查询合约
openzeppelin call
➜ zacian git:(develop)
✗ openzeppelin call
? Pick a network development
? Pick an instance Counter at 0x379e8403632013fFf3D0C03d14AD71C958071FAf
? Select which function value()
✓ Method 'value()' returned: 1 1
变更合约的逻辑
pragma solidity ^0.5.0;
contract Counter
}
升级已部署合约逻辑
openzeppelin compile openzeppelin upgrade
➜ zacian git:(develop)
✗ openzeppelin compile
✓ Compiled contracts with solc 0.5.13 (commit.5b0b510c)
➜ zacian git:(develop)
✗ openzeppelin upgrade
? Pick a network development Nothing to compile, all contracts are up to date.
✓ Contract Counter deployed All contracts have been deployed
? Which instances would you like to upgrade
? Choose by name
? Pick an instance to upgrade Counter
? Call a function on the instance after upgrading it? No
✓ Instance upgraded at 0x379e8403632013fFf3D0C03d14AD71C958071FAf. Transaction receipt: 0x1d9c2979439a0fad48f9d3a6095610ba23524ea3fa0f974677f027d5867e110b
✓ Instance at 0x379e8403632013fFf3D0C03d14AD71C958071FAf upgraded
openzeppelin 不允许使用construtor需要初始化器,OpenZeppelin SDK提供了一个基本Initializable合同,其中包含一个initializer负责此工作的修饰符
yarn add @openzeppelin/upgrades
合约使用constane声明的变量不占用存储槽 所以可以替换
contract MyContract
如果合约内有合同时 应该作为传参传入
import "@openzeppelin/upgrades/contracts/Initializable.sol";
import "@openzeppelin/contracts-ethereum-package/contracts/token/ERC20/ERC20.sol";
contract MyContract is Initializable
}
如果需要在合约内创建可升级合同,则使用App作为创建的SDK
import "@openzeppelin/upgrades/contracts/Initializable.sol";
import "@openzeppelin/upgrades/contracts/application/App.sol";contract MyContract is Initializable
function createNewToken() public returns(address)
}
合约中避免使用selfdestruct 和 delegatecall,如果需要使用则需要在无法初始化的逻辑上使用
关于变量
声明后无法改变类型和顺序或者在已有变量声明中间插入新的变量声明,也不可删除现有变量 加入新变量要在最后加入
重命名变量可行
如果无意修改了父合同的变量或者引用顺序,也会改变实际的存储方式
解决方案是预先保留插槽
Published at Thu, 21 Nov 2019 03:52:56 +0000
{flickr|100|campaign}
