本文介绍了如何使用@openzeppelin/truffle-upgrades 插件在 Truffle 迁移和测试中部署和升级合约的代理。 包括使用 deployProxy
和 upgradeProxy
函数部署和升级普通代理,以及使用 deployBeacon
、deployBeaconProxy
和 upgradeBeacon
函数来部署和升级信标代理。
此包已弃用。 建议的替代方案是使用 Hardhat 以及 Hardhat Upgrades 插件。 |
此包将函数添加到你的 Truffle 迁移和测试中,以便你可以为你的合约部署和升级代理。
尚不支持从 Truffle 外部脚本 使用。 |
查看 分步教程,展示了从创建、测试和部署,一直到使用 Gnosis Safe 进行升级的全过程。 |
$ npm install --save-dev @openzeppelin/truffle-upgrades
此包需要 Truffle 版本 5.1.35 或更高版本。
要在你的迁移中部署合约的可升级实例,请使用 deployProxy
函数:
// migrations/NN_deploy_upgradeable_box.js
const { deployProxy } = require('@openzeppelin/truffle-upgrades');
const Box = artifacts.require('Box');
module.exports = async function (deployer) {
const instance = await deployProxy(Box, [42], { deployer });
console.log('Deployed', instance.address);
};
这将自动检查 Box
合约是否是升级安全的,设置代理管理员(如果需要),为 Box
合约部署一个 implementation contract(除非之前部署中已经存在一个),创建一个代理,并通过调用 initialize(42)
来初始化它。
然后,在未来的迁移中,你可以使用 upgradeProxy
函数将已部署的实例升级到新版本。 新版本可以是不同的合约(例如 BoxV2
),或者你可以只修改现有的 Box
合约并重新编译它-插件会注意到它已更改。
// migrations/MM_upgrade_box_contract.js
const { upgradeProxy } = require('@openzeppelin/truffle-upgrades');
const Box = artifacts.require('Box');
const BoxV2 = artifacts.require('BoxV2');
module.exports = async function (deployer) {
const existing = await Box.deployed();
const instance = await upgradeProxy(existing.address, BoxV2, { deployer });
console.log("Upgraded", instance.address);
};
该插件将负责比较 BoxV2
和以前的版本,以确保它们兼容升级,部署新的 BoxV2
实现合约(除非之前部署中已经存在一个),并将现有代理升级到新的实现。
你还可以使用此插件通过 deployBeacon
函数为你的合约部署一个可升级的信标(beacon),然后通过使用 deployBeaconProxy
函数部署一个或多个指向它的信标代理。
// migrations/NN_deploy_upgradeable_box.js
const { deployBeacon, deployBeaconProxy } = require('@openzeppelin/truffle-upgrades');
const Box = artifacts.require('Box');
module.exports = async function (deployer) {
const beacon = await deployBeacon(Box);
console.log('Beacon deployed', beacon.address);
const instance = await deployBeaconProxy(beacon, Box, [42], { deployer });
console.log('Box deployed', instance.address);
};
在未来的迁移中,你可以使用 erc1967.getBeaconAddress
函数从已部署的信标代理实例中获取信标地址,然后调用 upgradeBeacon
函数将该信标升级到新版本。 升级信标后,所有指向它的信标代理都将使用新的合约实现。
// migrations/MM_upgrade_box_contract.js
const { erc1967, upgradeBeacon } = require('@openzeppelin/truffle-upgrades');
const Box = artifacts.require('Box');
const BoxV2 = artifacts.require('BoxV2');
module.exports = async function (deployer) {
const existing = await Box.deployed();
const beaconAddress = await erc1967.getBeaconAddress(existing.address);
await upgradeBeacon(beaconAddress, BoxV2, { deployer });
console.log("Beacon upgraded", beaconAddress);
const instance = await BoxV2.at(existing.address);
};
你也可以从你的 Truffle 测试中使用插件的函数,以防你想为升级你的合约添加测试(你应该这样做!)。 API 与迁移中的 API 相同,只是没有 deployer
参数。
const { deployProxy, upgradeProxy } = require('@openzeppelin/truffle-upgrades');
const Box = artifacts.require('Box');
const BoxV2 = artifacts.require('BoxV2');
describe('upgrades', () => {
it('works', async () => {
const box = await deployProxy(Box, [42]);
const box2 = await upgradeProxy(box.address, BoxV2);
const value = await box2.value();
assert.equal(value.toString(), '42');
});
});
const { deployBeacon, deployBeaconProxy, upgradeBeacon } = require('@openzeppelin/truffle-upgrades');
const Box = artifacts.require('Box');
const BoxV2 = artifacts.require('BoxV2');
describe('upgrades', () => {
it('works', async () => {
const beacon = await deployBeacon(Box);
const box = await deployBeaconProxy(beacon, Box, [42]);
await upgradeBeacon(beacon, BoxV2);
const box2 = await BoxV2.at(box.address);
const value = await box2.value();
assert.equal(value.toString(), '42');
});
});
- 原文链接: docs.openzeppelin.com/up...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!