在REMIX中使用OpenZeppelin集成透明升级合约和在HARDHAT中集成透明升级合约演示

目录

1.在REMIX中集成透明升级合约

2.在HARDHAT中集成透明升级合约


合约一旦部署,是不可以更改了,项目初期必须提前设计,决定是否需要升级,否则是无法升级的,只要提前用代理模式,就能升级。演示一下升级的过程。BoxV1升级到BoxV2过程。

1.在REMIX中集成透明升级合约

BoxV1.sol代码:

复制代码
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;

import "@openzeppelin/contracts/proxy/utils/Initializable.sol";

contract BoxV1 is Initializable {
    uint public x;

    function initialize(uint _val) external initializer {
        x = _val; // set initial value in initializer
    }

    function call() external {
        x += 1;
    }

    function showInvoke() external pure returns (bytes memory) {
        return abi.encodeWithSelector(this.initialize.selector, 1);
    }
}

BoxV2.sol

复制代码
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;

import "@openzeppelin/contracts/proxy/utils/Initializable.sol";

contract BoxV2 is Initializable {
    uint public x;

    function initialize(uint _val) external initializer {
        x = _val; // set initial value in initializer
    }

    function call() external {
        x *= 2;
    }

    function showInvoke() external pure returns (bytes memory) {
        return abi.encodeWithSelector(this.initialize.selector, 1);
    }
}

TPUProxy.sol

复制代码
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.26;

import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";

contract TPUProxy is TransparentUpgradeableProxy {
    constructor(
        address _logic,
        address _initialOwner,
        bytes memory _data
    ) payable TransparentUpgradeableProxy(_logic, _initialOwner, _data) {}

    function proxAdmin() external view returns (address) {
        return _proxyAdmin();
    }

    function getImplementation() external view returns (address) {
        return _implementation();
    }

}

在remix,分别编译和部署BoxV1,BoxV2合约

然后部署TPUProxy合约,部署前注意填写数据

参数解释:

参数 类型 作用
_logic address 业务逻辑合约地址(如BoxV1)
_initialOwner address 管理员地址(可以升级合约的人)
_data bytes 初始化数据(调用逻辑合约initialize函数)

_logic的值是复制BoxV1的地址

然后点击部署,部署TPUProxy时就已经调用了BoxV1的initialize(1)方法,在 TPUProxy 的存储上下文中,执行 BoxV1.initialize(1),initializer 来自 Initializable,该函数只能调用一次。

复制TPUProxy合约地址

然后挂载到BoxV1上

Remix 的界面会把 "At Address 绑定的操作入口" 和 "直接部署的合约" 放在同一区域,显示名称都是 "BoxV1",操作本质:给 TPUProxy 套了个 BoxV1 的 "操作界面",用 BoxV1 的按钮控制代理

现在要升级到BoxV2,只能由管理合约来升级

找管理员合约

可以对应上的。如果发现ProxyAdmin合约地址跟proxAdmin按钮显示的地址不一样,明显就是错了,那么不管填写什么值,都会报错。

参数 意思 怎么填
proxy 要升级的代理地址 你的 TPUProxy 地址
implementation 新逻辑合约地址 你的 BoxV2 地址
data 升级后要执行的函数 calldata 0x(不执行)或 abi.encode(...)

然后点击"transact",意思是发起一笔区块链交易,请求将代理合约(TPUProxy)的逻辑升级到新版本(如 BoxV2),并在升级后立即执行指定的初始化或迁移函数。

接下来,把代理合约挂载到BoxV2中,因为TPUProxy已经变了,我们再次复制这个TPUProxy合约地址

点击"Ar Address

点击"x:显示的值是之前Boxv1的值,状态没丢,然后点"call",发现值已经是乘法,升级成功了

完成合约。

用户/前端始终与 同一个地址 交互:TPUProxy,即使升级了 10 次逻辑合约,这个地址永远不会变,看这个TPUProxy地址,始终都没变。

2.在HARDHAT中集成透明升级合约

首先安装依赖

复制代码
npm install --save-dev @openzeppelin/hardhat-upgrades
或
yarn add -D @openzeppelin/hardhat-upgrades

在hardhat.config.ts文件添加依赖

复制代码
require("@nomicfoundation/hardhat-toolbox");
require("@openzeppelin/hardhat-upgrades")

把BoxV1.sol和BoxV2.sol复制到hardhat中

然后在test目录下新建BoxV1.js文件

javascript 复制代码
const hre = require("hardhat");

async function deploy() {
  const BOXV1 = await hre.ethers.getContractFactory("BoxV1");

  // 通过v1版本部署代理
  const v1 = await hre.upgrades.deployProxy(BOXV1, [1], {
    initializer: "initialize",
  });
  await v1.waitForDeployment();

  console.log(await v1.getAddress());
  console.log(await v1.x());
  await v1.call();
  console.log(await v1.x());
}

deploy();

然后在package.json文件所在目录,打开命令提示符,输入

javascript 复制代码
#清理可能的缓存
npx hardhat clean

#重新编译
npx hardhat compile

#启动节点
npx hardhat node

启动另一个命令窗口,输入

javascript 复制代码
npx hardhat run test\BoxV1.js --network localhost

复制BoxV1.js变成BoxV2.js

javascript 复制代码
const hre = require("hardhat");

async function deploy() {
  //V2版本工厂
  const BOXV2 = await hre.ethers.getContractFactory("BoxV2");

  // 通过v2版本部署代理
  const v2 = await hre.upgrades.upgradeProxy(
    "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512",
    BOXV2
  );
  await v2.waitForDeployment();

  console.log(await v2.getAddress());
  console.log(await v2.x());
  await v2.call();
  console.log(await v2.x());
}

deploy();

再次要命令行执行

javascript 复制代码
npx hardhat run test\BoxV2.js --network localhost

成功了

相关推荐
唐僧洗头爱飘柔95275 小时前
【区块链技术(06)】为什么分布式系统会存在数据一致性问题?本文带你理解:CAP和FLP定理、拜占庭将军问题;Paxos和Raft两种分布式算法
分布式·区块链·数据一致性·raft算法·cap定理·paxos算法·拜占庭将军问题
野老杂谈7 小时前
【Solidity学习】合约基本结构与状态变量
学习·区块链
小明的小名叫小明16 小时前
区块链核心知识点梳理(6)-区块链浏览器解读
区块链
Sui_Network19 小时前
备受期待的 POP 射击游戏 XOCIETY 正式在 Epic Games Store 开启体验
人工智能·游戏·rpc·区块链·量子计算·graphql
友莘居士21 小时前
Solidity 抽象合约与接口合约详解
区块链·抽象合约·接口合约
lkbhua莱克瓦2421 小时前
BTC-密码学原理
区块链·密码学·btc
Web3VentureView21 小时前
培养全球Web3人才:SYNBO商学院正式启动运营
网络·金融·重构·web3·区块链
小明的小名叫小明21 小时前
区块链核心知识点梳理(8)-钱包与账户体系
区块链
小明的小名叫小明21 小时前
区块链核心知识点梳理(9)-加密算法详解
区块链