您现在的位置是:首页 > 编程 > 

Foundry之使用OpenZeppelin插件进行智能合约升级

2025-07-26 15:38:21
Foundry之使用OpenZeppelin插件进行智能合约升级 合约的可升级性智能合约在部署后,通常无法像传统软件一样直接进行修改或更新。这是因为区块链上的智能合约一旦被部署,就会被记录在区块链上,并且其代码是不可更改的。这种不可变性是区块链的一个重要特性,但也带来了一些问题,尤其是在智能合约的升级和维护方面。具备可升级性的智能合约可以帮助开发者在合约的生命周期内进行必要的修改和优化,而不必担心

Foundry之使用OpenZeppelin插件进行智能合约升级

合约的可升级性

智能合约在部署后,通常无法像传统软件一样直接进行修改或更新。这是因为区块链上的智能合约一旦被部署,就会被记录在区块链上,并且其代码是不可更改的。这种不可变性是区块链的一个重要特性,但也带来了一些问题,尤其是在智能合约的升级和维护方面。

具备可升级性的智能合约可以帮助开发者在合约的生命周期内进行必要的修改和优化,而不必担心修改后会破坏已有的协议或数据。具体来说,智能合约的可升级性主要有以下几个原因和优势:

  1. 修复漏洞和错误:智能合约在开发和部署后,可能会发现潜在的漏洞或缺陷,无法通过传统方式进行修复。如果合约没有可升级性,一旦发现问题,必须重新部署一个新的合约,用户可能还需要迁移数据和资金。具备可升级性的合约允许开发者修复漏洞,而不需要重新部署整个合约。
  2. 添加新功能或修改逻辑:随着业务需求变化或新技术的出现,智能合约的功能可能需要扩展或修改。如果合约不能升级,添加新功能可能需要完全重写合约,这不仅增加了复杂性,还可能导致新的安全风险。可升级合约支持在保持原有合约逻辑的基础上,灵活地添加或更新功能。
  3. 兼容性和用户体验:如果智能合约需要进行重大升级或修改,并且没有可升级性,用户可能需要手动迁移他们的资产或与新的合约进行交互,这会影响到用户体验和区块链的普及。通过设计可升级性,开发者可以保持合约的兼容性,让用户体验更加平滑,避免频繁的资产迁移。
  4. 符合监管和法律要求:区块链的监管环境可能会发生变化,可能需要合约根据新的法律法规进行调整。没有可升级性的合约无法进行这些调整,导致合约可能违反新的规定。具有可升级性的合约能更好地应对法律环境的变化。
  5. 提高合约的长期稳定性:区块链技术的演进速度很快,智能合约的设计可能随着技术的发展和社区的反馈而需要更新。通过在合约设计中引入可升级性,可以让智能合约在长期运行过程中更加稳定、可靠,避免因为技术迭代导致的过时和不兼容。
可升级合约开发

升级智能合约是一个多步骤且容易出错的过程,因此为了尽量减少人为错误的可能性,使用一个尽可能自动化该过程的工具是理想的。OpenZeppelin提供了一系列的插件,可以帮助开发者在Solidity智能合约中实现可升级性。下面以Foundry为例,介绍如何使用OpenZeppelin插件进行智能合约升级。

创建项目

代码语言:bash复制
# 使用vscode作为IDE,所以这里使用了 --vscode 参数
$ forge init foundry-upgrades --vscode && cd foundry-upgrades
# 安装依赖
$ forge install OpenZeppelin/openzeppelin-contracts-upgradeable
$ forge install OpenZeppelin/openzeppelin-foundry-upgrades
# for vscode
$ forge remappings > 

在项目的配置文件中 增加如下配置:

代码语言:ini复制
[profile.default]
src = "src"
out = "out"
libs = ["lib"]
# 新增
# 启用构建信息输出,生成包含详细编译器信息和合约源码的 build-info 文件,便于合约升级工具(例如 OpenZeppelin 的 @openzeppelin/upgrades-core)使用和验证。
build_info = true
# 启用存储布局的输出,帮助开发者分析合约存储变量的布局,特别是在合约升级时确保存储布局一致性,避免数据丢失。
extra_output = ["storageLayout"]
# 启用 Solidity 合约的抽象语法树(AST)输出,提供合约源码的结构化表示,帮助进行静态分析、代码优化和合约安全检查。
ast = true

创建合约

src目录下新增ContractA合约,作为我们的基础合约:

代码语言:solidity复制
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

contract ContractA is Initializable{
    uint256 public value;

    function initialize(uint256 _setValue) public initializer {
        value = _setValue;
    }
}

然后新增ContractB合约,用作升级使用:

代码语言:solidity复制
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

/// @custom:oz-upgrades-from ContractA
// 或者
/// @custom:oz-upgrades-from ./ContractA.sol:ContractA
contract ContractB is Initializable {
    uint256 public value;

    function initialize(uint256 _setValue) public initializer {
        value = _setValue;
    }

    function increaseValue() public {
        value += 10;
    }
}

/// @custom:oz-upgrades-from标签是OpenZeppelin Upgrades插件中的一个自定义注释,它用于指定合约的来源版本,确保新的逻辑合约与旧版本合约兼容。在实现可升级合约时,这个标签帮助工具识别合约之间的继承关系和存储结构的兼容性,从而支持平滑、安全的合约升级。

编写测试合约

下面需要对我们的合约进行测试,确保它们能正常运行。在test目录下新增sol测试合约:

代码语言:solidity复制
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "forge-std/Test.sol";
import "openzeppelin-foundry-upgrades/Upgrades.sol";
import "../src/ContractA.sol";
import "../src/ContractB.sol";

contract UpgradesTest is Test {
    function testTransparent() public {
        // 部署一个以 ContractA 作为实现的透明代理,并使用 10 作为 ContractA 的初始化参数
        address proxy = Upgrades.deployTransparentProxy(
            "ContractA.sol",
            msg.sender,
            (ContractA.initialize, (10))
        );

        // 获取合约实例
        ContractA instance = ContractA(proxy);

        // 获取代理的实现地址
        address implAddrV1 = Upgrades.getImplementationAddress(proxy);

        // 获取代理的 admin 地址
        address adminAddr = Upgrades.getAdminAddress(proxy);

        // 确保 admin 地址有效
        assertFalse(adminAddr == address(0));

        // 记录初始之
        cole.log("----------------------------------");
        cole.log("Value before upgrade --> ", instance.value());
        cole.log("----------------------------------");

        // 验证是否符合预期
        assertEq(instance.value(), 10);

        // 将代理升级到 ContractB
        Upgrades.upgradeProxy(proxy, "ContractB.sol", "", msg.sender);

        // 获取升级后的新实现地址
        address implAddrV2 = Upgrades.getImplementationAddress(proxy);

        // 验证 admin 地址并未改变
        assertEq(Upgrades.getAdminAddress(proxy), adminAddr);

        // 验证实现地址发生了变化
        assertFalse(implAddrV1 == implAddrV2);

        // 调用 increaseValue
        ContractB(address(instance)).increaseValue();

        // 记录并验证升级后的新值
        cole.log("----------------------------------");
        cole.log("Value after upgrade --> ", instance.value());
        cole.log("----------------------------------");
        assertEq(instance.value(), 20);
    }
}

编译测试

使用下面的命令进行验证测试:

代码语言:bash复制
$ forge clean && forge test -vvv --ffi --mt testTransparent
[⠊] Compiling...
[⠰] Compiling 6 files with Solc 0.8.28
[⠑] Solc 0.8.28 finished in 2.4s
Compiler run successful!

Ran 1 test for test/sol:UpgradesTest
[PASS] testTransparent() (gas: 42618471)
Logs:
  ----------------------------------
  Value before upgrade -->  10
  ----------------------------------
  ----------------------------------
  Value after upgrade -->  20
  ----------------------------------
  ----------------------------------
  Value after upgrade -->  0
  ----------------------------------

Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 1166.5s (1166.5s CPU time)

Ran 1 test suite in 1166.7s (1166.5s CPU time): 1 tests passed, 0 failed, 0 skipped (1 total tests)

#感谢您对电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格的认可,转载请说明来源于"电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格

本文地址:http://www.dnpztj.cn/biancheng/1178543.html

相关标签:无
上传时间: 2025-07-21 22:15:12
留言与评论(共有 20 条评论)
本站网友 花斑癣图片
11分钟前 发表
代码优化和合约安全检查
本站网友 蝙蝠侠战车
3分钟前 发表
ContractA contract ContractB is Initializable { uint256 public value; function initialize(uint256 _setValue) public initializer { value = _setValue; } function increaseValue() public { value += 10; } }/// @custom
本站网友 甘宁
10分钟前 发表
但也带来了一些问题
本站网友 以来
16分钟前 发表
可能会发现潜在的漏洞或缺陷
本站网友 青岛万达东方影都
2分钟前 发表
安全的合约升级
本站网友 红姐图库118
18分钟前 发表
使用一个尽可能自动化该过程的工具是理想的
本站网友 双眼皮贴怎么剪
6分钟前 发表
避免频繁的资产迁移
本站网友 租房网站
0秒前 发表
无法通过传统方式进行修复
本站网友 吉大租房
8分钟前 发表
确保新的逻辑合约与旧版本合约兼容
本站网友 小儿癫痫
27分钟前 发表
而不需要重新部署整个合约
本站网友 风杀
10分钟前 发表
智能合约的设计可能随着技术的发展和社区的反馈而需要更新
本站网友 恩施晚报
21分钟前 发表
可能需要合约根据新的法律法规进行调整
本站网友 ipo和上市的区别
1分钟前 发表
通常无法像传统软件一样直接进行修改或更新
本站网友 王小石事件
8分钟前 发表
符合监管和法律要求:区块链的监管环境可能会发生变化
本站网友 百度人才
7分钟前 发表
开发者可以保持合约的兼容性
本站网友 天津英华国际学校
26分钟前 发表
智能合约的设计可能随着技术的发展和社区的反馈而需要更新
本站网友 劳动手册怎么办
17分钟前 发表
可靠
本站网友 廊下生态园
4分钟前 发表
oz-upgrades-from ContractA // 或者 /// @custom
本站网友 牛鞭是什么
3分钟前 发表
在test目录下新增sol测试合约: 代码语言:solidity复制// SPDX-License-Identifier