当前位置: 首页 > news >正文

使用OpenZeppelin编写可升级智能合约(代理) - all-in

开发环境:VSCode + Foundry

一、创建项目

执行$forge init ProxyDemo 创建Foundry项目,并创建2个版本的逻辑合约:

  • LogicV1.sol

    // SPDX-License-Identifier: UNLICENSED
    pragma solidity ^0.8.30;import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol";contract LogicV1 is Initializable {uint256 public number;function initialize(uint256 initialValue) public initializer {number = initialValue;}function changeNumber() public {number++;}
    }
    
  • LogicV2.sol

    // SPDX-License-Identifier: UNLICENSED
    pragma solidity ^0.8.30;import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol";contract LogicV2 is Initializable {uint256 public number;function setNumber(uint256 newValue) public {number = newValue;}function changeNumber() public {number += 10;}
    }
    

普通合同和可升级合同的最大区别在于,可升级合同没有constructor()

二、使用OpenZeppelin Upgrades 插件部署LogicV1

2.1 安装库

安装OpenZeppelin可升级合约库:

forge install OpenZeppelin/openzeppelin-foundry-upgrades
forge install OpenZeppelin/openzeppelin-contracts-upgradeable

然后更新remappings.txt文件:forge remappings > remappings.txt

如果你想在升级或部署时,运行OpenZeppelin自带的升级安全检查,请执行:

  1. 安装node.js

  2. foundry.toml里配置ffi、 ast、 build info和storage layout:

[profile.default]
ffi = true
ast = true
build_info = true
extra_output = ["storageLayout"]

2.2 编写部署脚本

script/LogicV1.s.sol 中编写 LogicV1 合约的部署脚本

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.30;import {Script} from "forge-std/Script.sol";
import {LogicV1} from "../src/LogicV1.sol";
import {console} from "forge-std/console.sol";
import {Upgrades} from "openzeppelin-foundry-upgrades/Upgrades.sol";contract LogicV1Script is Script {function setUp() public {}function run() public {// 部署的账户私钥uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");vm.startBroadcast(deployerPrivateKey);// Deploy the upgradeable proxy and its first implementationaddress proxy = Upgrades.deployTransparentProxy("LogicV1.sol",vm.envAddress("ADMIN_ADDRESS"),abi.encodeCall(LogicV1.initialize, (22)));console.log("Proxy deployed at:", proxy);console.log("Implementation deployed at:", Upgrades.getImplementationAddress(proxy));console.log("Admin address at:", Upgrades.getAdminAddress(proxy));vm.stopBroadcast();}
}

执行 forge script 进行部署:

$ forge script script/LogicV1.s.sol --rpc-url https://sepolia.gateway.tenderly.co --broadcast --verify[⠒] Compiling...
No files changed, compilation skipped
Script ran successfully.== Logs ==Proxy deployed at: 0xDDDb96d38096Bc2acB1a43a0c5A29d4162ac0CB7Implementation deployed at: 0xF401a5f6E69bDC1c4BDa51e9Be7719338dB61096Admin address at: 0xCF5a9750169b0DA9408AEa6757912211692F1FCf

通过OpenZeppelin Upgrades 插件,我们部署了三个合约:

  1. Logic 合约:也叫 Implementation 合约,即LogicV1。

  2. Proxy 合约:透明代理合约,即TransparentUpgradeableProxy。

  3. ProxyAdmin 合约:代理管理员合约,ProxyAdmin。

对应地址:

  1. https://repo.sourcify.dev/11155111/0xF401a5f6E69bDC1c4BDa51e9Be7719338dB61096

  2. https://repo.sourcify.dev/11155111/0xDDDb96d38096Bc2acB1a43a0c5A29d4162ac0CB7

  3. https://repo.sourcify.dev/11155111/0xCF5a9750169b0DA9408AEa6757912211692F1FCf

这三个合约之间的关系如下:
image

管理员只能通过 ProxyAdmin 合约去调用 Proxy 合约的 upgradeToAndCall() 函数进行升级。

三、使用OpenZeppelin Upgrades 插件升级LogicV2

script/LogicV2.s.sol 中编写 LogicV1 -> LogicV2 的升级脚本:

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.30;import {Script} from "forge-std/Script.sol";
import {LogicV2} from "../src/LogicV2.sol";
import {console} from "forge-std/console.sol";
import {Upgrades} from "openzeppelin-foundry-upgrades/Upgrades.sol";
import {Options} from "openzeppelin-foundry-upgrades/Options.sol";contract LogicV2Script is Script {function setUp() public {}function run() public {// 部署的账户私钥uint256 deployerPrivateKey = vm.envUint("PRIVATE_KEY");// 代理合约地址address proxyAddress = vm.envAddress("PROXY_ADDRESS");// 升级选项,指定旧合约Options memory opts;opts.referenceContract = "LogicV1.sol";vm.startBroadcast(deployerPrivateKey);// 升级代理合约到 LogicV2,并调用 setNumber 函数设置新的值Upgrades.upgradeProxy(proxyAddress,"LogicV2.sol", // 要升级的合约abi.encodeCall(LogicV2.setNumber, (50)), // 调用新合约的函数opts);console.log("Proxy deployed at:", proxyAddress);console.log("New implementation deployed at:", Upgrades.getImplementationAddress(proxyAddress));vm.stopBroadcast();}
}

执行 forge script 进行升级:

$ forge script script/LogicV2.s.sol --rpc-url https://sepolia.gateway.tenderly.co --broadcast --verify[⠒] Compiling...
No files changed, compilation skipped
Script ran successfully.== Logs ==Proxy deployed at: 0xDDDb96d38096Bc2acB1a43a0c5A29d4162ac0CB7New implementation deployed at: 0x964D52fd3c94CA379Ab1ED3411f01EeFF8e99Bf5

新部署的LogicV2合约地址:https://repo.sourcify.dev/11155111/0x964D52fd3c94CA379Ab1ED3411f01EeFF8e99Bf5

查看Proxy合约的日志,可以看到有一次Upgraded调用更新了逻辑合约地址:
image

http://www.jsqmd.com/news/48639/

相关文章:

  • 实用指南:【逻辑回归】从线性模型到逻辑回归
  • vuepress2.x支持vue2吗?
  • 贪心专题 1 做题记录
  • static 静态变量
  • 【IO多路转接】IO 多路复用之 select:从接口解析到服务器实战 - 详解
  • java sql注入的危害有哪些
  • 单片机控制继电器及其原理
  • 2025-09-10-Wed-T-Milvus
  • 【Linux】 层层递进,抽丝剥茧:调度队列、命令行参数、环境变量 - 指南
  • 字符串大小写转换
  • vitepress如何支持vue2组件
  • 2025.11.23
  • 20231427田泽航第十周预习报告
  • java linux环境变量
  • java linux服务器
  • 机器人世界杯物流联赛技术解析
  • fcitx5要一统江湖了
  • 2025 年上海金蝶软件定制开发代理商推荐榜出炉
  • 【开发者导航】全自动 AI 视频创作与发布工具:LuoGen-agent - 教程
  • 2025-09-10-Wed-T-AI基础知识
  • JAX 核心特性详解:纯函数、JIT 编译、自动微分等十大必知概念
  • java linux 进程
  • 截图工具
  • linux 下定义常用路径环境变量
  • 人工智能之数据分析 numpy:第十二章 数据持久化
  • 榨干黑五VPS的7个姿势:Web3玩家的资源优化实战指南
  • anchor
  • 作为网易 UU 远程 macOS 版(内测版本 4.6.101)用户,我实测了这份完整指南 - 指南
  • 单克隆抗体在药物研发和治疗领域的应用前景
  • Jetson Orin Nano super -3 NVIDIA Jetson 平台的技术架构和NVIDIA JetPack