与 Hardhat 一起使用 - OpenZeppelin 文档

本文介绍了如何在Hardhat项目中使用@openzeppelin/hardhat-upgrades插件来部署和升级代理合约以及信标代理合约。文章提供了安装插件、在脚本和测试中使用的示例代码,以及升级代理合约和信标合约的步骤,并提及了完整的API文档。

与 Hardhat 一起使用

此包向你的 Hardhat 脚本添加函数,以便你可以为你的合约部署和升级代理。依赖于 ethers.js

查看分步教程,展示了从创建、测试和部署,一直到使用 Gnosis Safe 进行升级的全过程。

安装

$ npm install --save-dev @openzeppelin/hardhat-upgrades
$ npm install --save-dev @nomicfoundation/hardhat-ethers ethers # peer dependencies

并在你的 hardhat.config.js 中注册该插件:

require('@openzeppelin/hardhat-upgrades');

在脚本中使用

代理

你可以在 Hardhat 脚本 中使用此插件,通过 deployProxy 函数部署你的合约的可升级实例:

// scripts/create-box.js
const { ethers, upgrades } = require("hardhat");

async function main() {
  const Box = await ethers.getContractFactory("Box");
  const box = await upgrades.deployProxy(Box, [42]);
  await box.waitForDeployment();
  console.log("Box deployed to:", await box.getAddress());
}

main();

这将自动检查 Box 合约是否是升级安全的,为 Box 合约部署一个实现合约(除非之前部署过一个),创建一个代理(如果需要,还会创建一个代理管理员),并通过调用 initialize(42) 来初始化它。

然后,在另一个脚本中,你可以使用 upgradeProxy 函数将已部署的实例升级到新版本。新版本可以是不同的合约(例如 BoxV2),或者你可以只修改现有的 Box 合约并重新编译它 - 插件会注意到它已更改。

// scripts/upgrade-box.js
const { ethers, upgrades } = require("hardhat");

async function main() {
  const BoxV2 = await ethers.getContractFactory("BoxV2");
  const box = await upgrades.upgradeProxy(BOX_ADDRESS, BoxV2);
  console.log("Box upgraded");
}

main();

注意:虽然此插件会跟踪你在每个网络上部署的所有实现合约,以便重用它们并验证存储兼容性,但它_不_跟踪你已部署的代理。这意味着你需要手动跟踪每个部署地址,以便在需要时将其提供给升级函数。

该插件将负责比较 BoxV2 与前一个版本,以确保它们与升级兼容,部署新的 BoxV2 实现合约(除非之前部署过一个),并将现有代理升级到新的实现。

信标代理

你还可以使用此插件通过 deployBeacon 函数为你的合约部署一个可升级的信标,然后通过使用 deployBeaconProxy 函数部署一个或多个指向它的信标代理。

// scripts/create-box.js
const { ethers, upgrades } = require("hardhat");

async function main() {
  const Box = await ethers.getContractFactory("Box");

  const beacon = await upgrades.deployBeacon(Box);
  await beacon.waitForDeployment();
  console.log("Beacon deployed to:", await beacon.getAddress());

  const box = await upgrades.deployBeaconProxy(beacon, Box, [42]);
  await box.waitForDeployment();
  console.log("Box deployed to:", await box.getAddress());
}

main();

然后,在另一个脚本中,你可以使用 upgradeBeacon 函数将信标升级到新版本。 当信标升级后,所有指向它的信标代理将使用新的合约实现。

// scripts/upgrade-box.js
const { ethers, upgrades } = require("hardhat");

async function main() {
  const BoxV2 = await ethers.getContractFactory("BoxV2");

  await upgrades.upgradeBeacon(BEACON_ADDRESS, BoxV2);
  console.log("Beacon upgraded");

  const box = BoxV2.attach(BOX_ADDRESS);
}

main();

在测试中使用

你还可以从你的 Hardhat 测试中使用该插件的函数,以防你想为升级你的合约添加测试(你应该这样做!)。API 与脚本中相同。

代理

const { expect } = require("chai");

describe("Box", function() {
  it('works', async () => {
    const Box = await ethers.getContractFactory("Box");
    const BoxV2 = await ethers.getContractFactory("BoxV2");

    const instance = await upgrades.deployProxy(Box, [42]);
    const upgraded = await upgrades.upgradeProxy(await instance.getAddress(), BoxV2);

    const value = await upgraded.value();
    expect(value.toString()).to.equal('42');
  });
});

信标代理

const { expect } = require("chai");

describe("Box", function() {
  it('works', async () => {
    const Box = await ethers.getContractFactory("Box");
    const BoxV2 = await ethers.getContractFactory("BoxV2");

    const beacon = await upgrades.deployBeacon(Box);
    const instance = await upgrades.deployBeaconProxy(beacon, Box, [42]);

    await upgrades.upgradeBeacon(beacon, BoxV2);
    const upgraded = BoxV2.attach(await instance.getAddress());

    const value = await upgraded.value();
    expect(value.toString()).to.equal('42');
  });
});

API

有关完整的 API 文档,请参见 Hardhat Upgrades API

← 概述

OpenZeppelin Defender 集成 →

  • 原文链接: docs.openzeppelin.com/up...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
OpenZeppelin
OpenZeppelin
江湖只有他的大名,没有他的介绍。