# 透明可升级合约在hardhat中实现

By [web3zoom](https://paragraph.com/@web3zoom) · 2025-08-05

---

1、首先安装npm包

yarn add @openzeppelin/hardhat-upgrades

2、hardhat.config.ts文件中添加配置：

    import "@openzeppelin/hardhat-upgrades";
    

2、两个基本合约如下：

    // BoxV1
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.28;
    
    import "@openzeppelin/contracts/proxy/utils/Initializable.sol";
    
    contract BoxV1 is Initializable {
        uint public x;
    
        function initialize(uint _val) external initializer {
            x = _val;
        }
    
        function cal() external {
            x = x + 1;
        }
    }
    

    // BoxV2
    // SPDX-License-Identifier: MIT
    pragma solidity ^0.8.28;
    
    import "@openzeppelin/contracts/proxy/utils/Initializable.sol";
    
    contract BoxV2 is Initializable {
        uint public x;
    
        function initialize(uint _val) external initializer {
            x = _val;
        }
    
        function cal() external {
            x = x * 2;
        }
    }
    

目标：需要将原有合约（BoxV1）升级到合约（BoxV2）。

下面则是测试脚本内容：

    import {
        time,
        loadFixture,
    } from "@nomicfoundation/hardhat-toolbox/network-helpers";
    import { anyValue } from "@nomicfoundation/hardhat-chai-matchers/withArgs";
    import { expect } from "chai";
    import hre from "hardhat";
    
    
    describe("TPUProxy", function () {
    
        it("test_TPUProxy_Boxv1", async function () {
            // 分配EOA账户
            const [admin] = await hre.ethers.getSigners();
            console.log("admin address: " + admin.address);
            // 部署box1、boxv2合约
            const boxv1 = await hre.ethers.getContractFactory("BoxV1");
            const boxv1Instance = await hre.upgrades.deployProxy(boxv1, [1], { initializer: "initialize" });
            await boxv1Instance.waitForDeployment();
    
            // 0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512
            console.log("proxy address: " + await boxv1Instance.getAddress());
            // 获取字节码
            // const creationcode = await boxv1Instance.interface.encodeFunctionData("initialize", [1]);
        });
    
        it("test_TPUPProxy_Boxv2", async function () {
            const boxv2 = await hre.ethers.getContractFactory("BoxV2");
            const boxv2Instance = await hre.upgrades.upgradeProxy(
                // 部署的BoxV1地址
                "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512",
                boxv2
            );
            await boxv2Instance.waitForDeployment();
    
            console.log(await boxv2Instance.getAddress());
            console.log(await boxv2Instance.x());
            await boxv2Instance.cal();
            console.log(await boxv2Instance.x());
        });
    });
    

总结：

1、透明可升级合约的基本原理还是基于delegatecall方法进行扩展的；

2、升级合约（BoxV2）中的变量x还保留了BoxV1的状态，并且在此基础上进行方法调用和计算。

3、特点就是使用下面的方法代理合约：

    const boxv2Instance = await hre.upgrades.upgradeProxy(
                // 逻辑合约（Boxv1）
                "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512",
                // 代理合约
                boxv2
            );

---

*Originally published on [web3zoom](https://paragraph.com/@web3zoom/hardhat)*
