从 OpenZeppelin CLI 迁移
本指南适用于从已弃用的旧 CLI 迁移。 |
本指南将引导您将项目从 OpenZeppelin CLI 迁移到用于 Truffle 或 Hardhat 的 OpenZeppelin Upgrades 插件。
Instructions are available for both Truffle and Hardhat. Choose your preference using this toggle! |
如果您想在示例 OpenZeppelin CLI 项目上尝试这些说明,您可以克隆 OpenZeppelin/openzeppelin-upgrades-migration-example 并在继续之前按照自述文件中的设置说明进行操作。 |
差异
CLI 和插件之间的主要区别在于,前者用于跟踪您的可升级(和不可升级)部署。 这在某些情况下很方便,因为您不必过多担心代理、实现或地址,您可以只关注诸如升级或将交易发送到您的合约等操作,只需通过它们的名称即可。
但是让 CLI 跟踪您的部署,代价是限制了您与其他工具和工作流程集成的自由。 并且由于插件被设计为独立于 CLI 工作,因此我们解除了该限制,因此现在您可以灵活地以您认为最佳的方式跟踪您的代理。
撇开这一点不谈,其他一切都保持不变,因为 CLI 和插件都在底层使用了相同的已知 Proxy
和 ProxyAdmin
合约,从而构成了管理它们的两种不同的接口。 这意味着迁移您的项目不会触及链上的任何内容,一切都是安全和本地的。
安装
安装 Hardhat,并在初始化时,选择 Create an empty hardhat.config.js
选项。
$ npm install --save-dev hardhat
$ npx hardhat
然后安装 Upgrades 插件:
$ npm install --save-dev @openzeppelin/hardhat-upgrades
$ npm install --save-dev @nomiclabs/hardhat-ethers ethers # peer dependencies
完成后,通过添加以下行在 Hardhat 配置文件中注册该插件:
// hardhat.config.js
require('@openzeppelin/hardhat-upgrades');
module.exports = {
// ...
};
安装 Truffle,然后初始化您的项目。
当 Truffle 询问时,选择不覆盖合约或测试目录。 通过不覆盖,您将不会获得 初始迁移。 确保创建 Migrations.sol 和初始迁移。
|
$ npm install --save-dev truffle
$ npx truffle init
然后安装 Upgrades 插件:
$ npm install --save-dev @openzeppelin/truffle-upgrades
迁移 CLI 项目
这是一个单向过程。 确保您保留 .openzeppelin/ 文件夹的备份或版本控制副本。
|
现在,让我们通过运行以下命令来迁移我们的项目:
$ npx migrate-oz-cli-project
✔ Successfully migrated .openzeppelin/rinkeby.json
✔ Migration data exported to openzeppelin-cli-export.json
✔ Deleting .openzeppelin/project.json
These were your project's compiler options:
// 这些是您项目的编译器选项:
{
"compilerSettings": {
"optimizer": {
"enabled": false,
"runs": "200"
}
},
"typechain": {
"enabled": false
},
"manager": "openzeppelin",
"solcVersion": "0.6.12",
"artifactsDir": "build/contracts",
"contractsDir": "contracts"
}
此脚本随插件一起安装,它的作用是删除 CLI 项目文件并将您的旧网络文件(所有这些文件都位于 .openzeppelin
目录下)转换为其 Upgrades 插件等效文件。 同样,链上的任何内容都不会更改,只有本地文件。 另请注意,一旦您运行此命令,除非您通过备份或版本控制还原更改,否则您将无法再使用 CLI 来管理此项目的合约。
迁移脚本还将 openzeppelin-cli-export.json
文件导出到您的工作目录中,其中包含 CLI 用于为您管理的所有数据,现在您可以自由地以您认为最佳的方式使用它。 这包括您的编译器设置,为了方便起见,这些设置也会在迁移结束时打印出来。 让我们将它们添加到我们的新项目配置中:
将编译器设置复制到 Hardhat 配置文件中的 solidity
字段
// hardhat.config.js
// ...
module.exports = {
// ...
solidity: {
version: "0.6.12",
settings: {
optimizer: {
enabled": false,
runs": 200
}
}
}
}
将编译器设置复制到我们 Truffle 配置文件的 compilers
字段
// truffle-config.js
module.exports = {
// ...
compilers: {
solc: {
version: "0.6.12",
settings: {
optimizer: {
enabled": false,
runs": 200
}
}
}
}
}
solidity 编译器配置格式在 truffle-config.js 和 hardhat.config.js 文件中是不同的
|
就是这样,您已成功迁移您的 CLI 项目。 现在让我们尝试使用您的新设置来升级您的迁移合约之一。
升级到新版本
假设我们在 CLI 项目中有一个 Box
合约,已部署到 Rinkeby 网络。 然后,如果我们打开我们的导出文件,我们将看到类似这样的内容:
// openzeppelin-cli-export.json
{
"networks": {
"rinkeby": {
"proxies": {
"openzeppelin-upgrades-migration-example/Box": [
{
"address": "0x500D1d6A4c7D8Ae28240b47c8FCde034D827fD5e",
"version": "1.0.0",
"implementation": "0x038B86d9d8FAFdd0a02ebd1A476432877b0107C8",
"admin": "0x1A1FEe7EeD918BD762173e4dc5EfDB8a78C924A8",
"kind": "Upgradeable"
}
]
}
}
},
"compiler": {
// we'll ignore compiler settings for this
// 我们将忽略此编译器的设置
}
}
我们在这里看到的是地址方面可升级合约的 JSON 表示形式:
-
address
: 代理地址(代理合约包含您的可升级合约状态) -
implementation
: 实现地址(您的可升级合约逻辑) -
admin
: 代理管理员的地址,除非您另行设置,否则它可能属于ProxyAdmin
合约
如果我们决定使用插件和此导出文件将我们的 Box
合约升级到 BoxV2
合约,它将如下所示:
这些脚本只是如何使用导出数据的示例。 我们不对是否按原样保留该文件或如何处理其数据提出任何建议。 这现在取决于用户。
// scripts/upgradeBoxToV2.js
const { ethers, upgrades } = require("hardhat");
const OZ_SDK_EXPORT = require("../openzeppelin-cli-export.json");
async function main() {
const [ Box ] = OZ_SDK_EXPORT.networks.rinkeby.proxies["openzeppelin-upgrades-migration-example/Box"];
const BoxV2 = await ethers.getContractFactory("BoxV2");
await upgrades.upgradeProxy(Box.address, BoxV2);
}
main();
$ npx hardhat run scripts/upgradeBoxToV2.js --network rinkeby
// migrations/2_upgrade_box_contract.js
const { upgradeProxy } = require('@openzeppelin/truffle-upgrades');
const OZ_SDK_EXPORT = require("../openzeppelin-cli-export.json");
const BoxV2 = artifacts.require('BoxV2');
module.exports = async function (deployer) {
const [ Box ] = OZ_SDK_EXPORT.networks.rinkeby.proxies["openzeppelin-upgrades-migration-example/Box"];
const instance = await upgradeProxy(Box.address, BoxV2, { deployer });
console.log("Upgraded", instance.address);
};
$ npx truffle migrate --network rinkeby
就是这样! 您已将您的 OpenZeppelin CLI 项目迁移到 Truffle 或 Hardhat,并使用插件执行了升级。