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

news/2025/11/23 20:29:00/文章来源:https://www.cnblogs.com/songlee/p/19261417

开发环境: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.mzph.cn/news/974202.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

实用指南:【逻辑回归】从线性模型到逻辑回归

实用指南:【逻辑回归】从线性模型到逻辑回归pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", &qu…

vuepress2.x支持vue2吗?

VuePress 2.x 不支持 Vue 2。✅ 官方明确说明 VuePress 2 是 完全基于 Vue 3 重构 的版本,其底层依赖包括:Vue 3(Composition API、新的响应式系统) Vite(作为默认构建工具) Vue Router 4📌 官方文档明确指出:…

贪心专题 1 做题记录

贪心专题 1 做题记录 A P4006 小 Y 和二叉树 考虑先固定一个点,我们考虑第一个输出的点,他应该是度数 \(\le 2\) 的点中最小的。固定之后我们开始往父亲构造。分类讨论一下当前点的度数:\(d=1\),则只有一个相邻点。…

static 静态变量

嗯学到了。。很受用。。

【IO多路转接】IO 多路复用之 select:从接口解析到服务器实战 - 详解

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

java sql注入的危害有哪些

Java SQL注入是一种常见的网络攻击手段,其危害主要包括以下几个方面:数据泄露:攻击者可以通过SQL注入攻击获取数据库中的敏感信息,如用户账号、密码、电话号码等,从而导致数据泄露。 数据篡改:攻击者可以通过SQL…

单片机控制继电器及其原理

工作原理当继电器线圈通电后,线圈中的铁芯产生强大的电磁力,吸动衔铁带动簧片,使触点1、2断开,1、3接通。当线圈断电后,弹簧使簧片复位,使触点1、2接通,1、3断开。我们只要把需要控制的电路接在触点1、2间(1、…

【Linux】 层层递进,抽丝剥茧:调度队列、命令行参数、环境变量 - 指南

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

字符串大小写转换

函数和Ascii码都要会 Ascii码强制转换 #include<bits/stdc++.h> using namespace std; int main() {string s;while(getline(cin,s)){for(int i=0;i<s.size();i++){if(s[i]>=a&&s[i]<=z) cout&…

vitepress如何支持vue2组件

VitePress 默认不支持 Vue 2 组件,因为:✅ VitePress 是基于 Vue 3 + Vite 构建的静态站点生成器; ❌ 它的运行时环境是 Vue 3,无法直接渲染 Vue 2 组件(Vue 2 和 Vue 3 的 API、响应式系统、虚拟 DOM 结构都不兼…

2025.11.23

今天继续学习vue,然后开始细节微调界面

java linux环境变量

在 Linux 环境中,Java 的运行依赖于 JAVA_HOME 环境变量,它指向 Java 开发工具包(JDK)的安装目录。以下是关于 Java 环境变量的详细说明和相关命令:一、设置 Java 环境变量1. 设置 JAVA_HOME(推荐)export JAVA_…

java linux服务器

您提到的“Java Linux服务器”可能是指在Linux服务器上部署和运行Java应用。以下是一些常见的Java相关Linux命令和Shell脚本,帮助您管理Java应用、部署、监控和日志等:一、Java环境配置1. 安装JDK(Java Development…

贪心做题记录-2

贪心做题记录-2 CF1477D. Nezzar and Hidden Permutations 若一个点的度数为 \(n-1\),则其在 \(p,q\) 中的位置定然相同,因此可以先将这个点删去,缩减为子问题,直到剩下 \(n\) 个点且所有点的度数都小于 \(n-1\)。…

机器人世界杯物流联赛技术解析

本文深入探讨机器人世界杯物流联赛的技术细节,包括自主移动机器人导航、多机器人协作规划、实时执行监控与重规划系统,以及智能工厂环境下的生产物流挑战,展现了现代机器人系统的复杂技术架构。机器人世界杯物流联赛…

fcitx5要一统江湖了

为了面向未来,又装上fcitx5细细地品了一下。转换正确率很高。 于是apt source fcitx5-pinyin看了下,发现两个2012年的文件:1.4M 2012年12月 2日 py_stroke.mb359K 2012年11月25日 py_table.mb用这两个文件就能达到如…

2025 年上海金蝶软件定制开发代理商推荐榜出炉

🥇 推荐一:上海宝蝶信息技术有限公司 (金蝶铂金级定制开发专家)推荐指数:★★★★★ | 口碑评分:10分 (一)上海宝蝶信息科技有限公司品牌介绍上海宝蝶信息技术有限公司成立于 2016 年,是金蝶集团在上海地区授权…

【开发者导航】全自动 AI 视频创作与发布工具:LuoGen-agent - 教程

【开发者导航】全自动 AI 视频创作与发布工具:LuoGen-agent - 教程2025-11-23 19:54 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !…