智能合约--如何实现可升级的智能合约

article/2025/9/13 5:27:48

一. 什么是智能合约

智能合约通俗点说就是写在区块链上面的代码,代码里面编写着严谨完善的规则,一旦某个用户满足了合约里面的规则条件,就会触发里面的代码,执行某个方法。

 

 二. 为什么要使智能合约达到可升级

智能合约的特点之一就是部署到链上之后不能修改,这一机制使得合约的交互方都可以信任合约。但也带来了一系列的问题,并且如果已部署的合约发现漏洞,也是无法修复的。假如发现了bug,致命性的,必须修复,那如何处理? 就是使用合约达到可升级优化才能满足需求

 

三. 升级合约的机制原理

  1.   什么是合约升级

使已经部署上链的合约做到可优化可更改,例如链上的业务逻辑代码和状态变量达到可增删改的功能.

   2.  合约升级的实现机制原理

 目前实现的方式根据存储区分有各种各样的模式,但是都离不开一个最底层的机制,就是使用delegatecall的特性去实现可升级的合约,达到合约可持续优化更改的效果.

delegatecall 介绍

目前调用合约的方式主要有三种

  • call
  • delegateCall
  • staticCall

共同点:都是去调用执行目标合约地址的方法

区别:delegateCall的执行环境和call和staticCall相反,正因为这样所以可利用这种特性实现可升级,在用户层面上无感知。

具体的delegateCall的介绍可以看我另外一篇文章

Solidity--call、delegatecall 和 callcode 的区别_Zeke Luo的博客-CSDN博客

 

四. 实现可升级的ERC20合约

代码概述

  • 编写InitializedProxy代理合约,此合约主要作用是转发和存储数据.

继承openzeppelin的StorageSlotUpgradeable合约,用于插槽工具类。

// SPDX-License-Identifier: GPL-3.0
import "@openzeppelin/contracts-upgradeable/utils/StorageSlotUpgradeable.sol";
pragma solidity >=0.7.0 <0.9.0;contract InitializedProxy {// address of logic contract// slot bytes32(uint256(keccak256('EIP1967.PROXY.CONFTI.IMPLEMENTATION')) - 1)bytes32 internal constant _IMPLEMENTATION_SLOT = 0x5f62ce3c9aebd463c7a36ab1b244d2bb94f07a2c13889b3b687940ebc467b9b3;// ======== Constructor =========constructor(address logic,bytes memory initializationCalldata) { require(logic != address(0),"Proxy :: Wrong proxy contract address");StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value = logic;// Delegatecall into the logic contract, supplying initialization calldata(bool _ok, bytes memory returnData) =logic.delegatecall(initializationCalldata);// Revert if delegatecall to implementation revertsrequire(_ok, string(returnData));}// ======== Fallback =========fallback() external payable {address _impl = StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value;assembly {let ptr := mload(0x40)calldatacopy(ptr, 0, calldatasize())let result := delegatecall(gas(), _impl, ptr, calldatasize(), 0, 0)let size := returndatasize()returndatacopy(ptr, 0, size)switch resultcase 0 {revert(ptr, size)}default {return(ptr, size)}}}// ======== Receive ===receive() external payable {} // solhint-disable-line no-empty-blocksfunction upgradeVersion(address newAddress_) public{ StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value = newAddress_;}
}

1.constructor构造函数拥有初始化数据,并且保存指向的业务逻辑合约

2.fallback转发接收所有业务逻辑合约的方法,

3.upgradVersion 用于升级的方法

替换指定插槽的旧逻辑合约地址,更换新的逻辑合约

  • 实现自己的业务逻辑合约(可升级的erc20)
import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
contract logicA  is ERC20Upgradeable{function initialize(string memory tokenName_ ,string memory symbol_) initializer external {__ERC20_init(tokenName_, symbol_);}function mint(address account,uint256 amount)  external  {if(account != address(0) && amount > 0){_mint(account,amount);}}function burn(address account,uint256 amount)  external  {if(account != address(0) && amount > 0){_burn(account,amount);}} }
  • 部署工厂合约

此合约的主要作用是,创建可升级的逻辑合约,并且管理升级等.

contract  testtFactory{address public logicProxy;function createProxy(address logiAddress_,string memory tokenName_,string memory symbol_) public {bytes memory _initializationCalldata = abi.encodeWithSignature("initialize(string,string)",tokenName_,symbol_);logicProxy = address (new InitializedProxy(logiAddress_,_initializationCalldata));}function updateLogicProxy(address updataTemplate_) public { (bool _ok, bytes memory returnData) = logicProxy.call(abi.encodeWithSignature("upgradeVersion(address)",updataTemplate_));require(_ok, string(returnData));} }

createProxy  : 生成可升级的代理合约

updateLogicProxy :  升级合约

  • 部署V2合约也就是升级之后的合约
contract logicA2 is ERC20Upgradeable{function mint(address account,uint256 amount)  external  {require (amount <= 10 ,"must be <= 10" );  if(account != address(0) && amount > 0){_mint(account,amount);}}function burn(address account,uint256 amount)  external  {if(account != address(0) && amount > 0){_burn(account,amount);}} }

此合约修改了mint的金额必须需要小于等于10,用于升级之后的逻辑检验。

 

五. 以上代码的使用逻辑介绍

以remix做案例使用:

一.部署业务逻辑合约(可升级erc20合约)

7b2d9257688e4bd99cf252e64456a0cc.png第二步.部署工厂合约 

e0b0b45f7eb34fef91b8a16110056722.png

第三步调用工厂合约创建可升级的erc20Token合约

调用createProxy传入第一步创建的可升级erc20合约地址

创建成功之后,点击logicProxy查看生成之后的代理地址

3f1b788ee44b423994f987f59fe162f0.png

 

然后调用at方法,并且选择相应的逻辑合约即可调用.(at使用方式和原理可自行查看)

 

第四步 升级当前的erc20合约

打开工厂合约调用updateLogicProxy传入新合约的地址,即可完成升级. 

(用户无感升级)

 

五. 升级逻辑

56c87094b0c44b8cb0c293a7a19deae1.png

 

⚠️ 升级注意事项

1.插槽的冲突风险

2.升级之后继承关系


总结

合约升级风险会比较大,尽量严谨,并且升级要做到只增不减不修改.

以上就是今天要讲的内容,本文仅仅简单介绍了delegateCall的升级使用,关于安全方面还是需要自行根据业务去加限制,如有其他不正确的欢迎指出,或者DM

 

 


http://chatgpt.dhexx.cn/article/K8dZZpyM.shtml

相关文章

智能合约简单介绍

本学期学习了区块链的课程&#xff0c;作业是对于智能合约学习后的报告&#xff1a; 1 智能合约简单了解 1.1智能合约是什么 智能合约是由事件驱动的、具有状态的、部署于可共享的分布式数据库上的计算机程序&#xff0c;多用IF-THEN语句。狭义来说&#xff0c;智能合约是设计…

智能合约

智能合约&#xff08;英语&#xff1a;Smart contract &#xff09;是一种旨在以信息化方式传播、验证或执行合同的计算机协议。智能合约允许在没有第三方的情况下进行可信交易。这些交易可追踪且不可逆转。[1]智能合约概念于1994年由Nick Szabo首次提出。智能合同的目的是提供…

[EOS源码分析]6.EOS特殊智能合约eosio

这里说的eosio智能合约不是泛指eos的智能合约&#xff0c;它是一个特殊的具体的合约。它本事可大了&#xff0c;我们一起来看看它有哪些功能 负责智能合约部署 大家有注意到如下红色字体的log吗 $ cleos set contract hello.code ../eos-contract/hello -p hello.code Publish…

EOS智能合约开发(一)

一、 智能合约功能二、 通讯模式 2.1 运行机制2.2 内联通信2.3 延迟通信2.4 交易和动作2.5 交易确认2.6 动作处理程序和动作的apply上下文2.7 交易限制 三、文件结构 3.1 创建框架3.2 apply处理程序3.3 EOSIO_ABI 宏 四、多索引数据库API 4.1 EOSIO多索引API4.2 EOSIO多索引迭代…

EOS系列 - WASM智能合约 - 特性

构造函数 addressbook(name receiver, name code, datastream<const char*> ds):contract(receiver, code, ds) {}#单例表&#xff08;code和scope都用receiver的表&#xff09;也可在初始化列表中实例化 singleton_example( name receiver, name code, datastream<c…

EOS智能合约开发(十五)EOS 状态机架构解析

好久没有写文章了&#xff0c;最近公司事情比较忙。非常感谢上次杭州团队一位负责EOS状态机的同事精彩分享。今天查阅很多资料后&#xff0c;整理这篇文章&#xff0c;希望对大家有所帮助。 EOS状态机是什么&#xff1f; 简单讲就是数据库&#xff0c;是EOS记录智能合约执行结…

接口测试时,输入所有参数的参数值后,接口返回“参数错误:所有参数都不能为空”

问题原因&#xff1a; 参数名称输入有误&#xff0c;前台&#xff08;pwd&#xff09;和后台&#xff08;password&#xff09;的参数名称不一致 &#xff0c;保持一致后即可

matlab 错误使用 connector.internal.autostart.run输入参数的数目不足。

matlab打开后提示&#xff1a; 错误使用 connector.internal.autostart.run输入参数的数目不足 原因&#xff1a;自己写的一个函数和matlab自带的函数重名了 参考&#xff1a;警告: 在 matlabrc 中初始化 Java 首选项失败 – MATLAB中文论坛MATLAB中文论坛MATLAB 基础讨论板块…

Matlab 自带遗传算法函数 ga() 运行报错:“ fitnessfcn() 输入参数的数目不足。”

原始程序 %主程序 m [1 2]; R [1.5 1]; epsilon [2^R(1)-1 2^R(2) - 1]; A [-1 epsilon(1); 0 -1]; b [0 0]; Aeq [1 1]; Beq 1;%matlab自带函数包 [x_optimal, fval] ga(fitnessfcn, 2, A, b, Aeq, Beq, [0;0], [1;1], []); ---------------------------------…

matlab函数参数不足,调用函数显示输入参数不足

问题描述.png (29.7 KB, 下载次数: 1) 2015-1-27 09:34 上传 %Gauss-Newton算法实现如下 function[x,minf] = GN(f,x0,var,eps)formatlong; ifnargin == 3 %如果没有设置eps,则eps=1.0e-6eps = 1.0e-6; end m = 0; S =transpose(f)*f; %trnspose是转…

matlab 函数不定参数,matlab function定义一个函数,但一直出来说输入参数数目不足。我用的是2014版本,不知道数目原因啊?...

www.mh456.com防采集。 h 5;g 1; % g取源0有问题% 被积函数2113可以化5261简成f 4102(a,b,r)(r*h-r^16532*cos(a-b))/(h^2r^2g^2-2*h*r*cos(a-b))^1.5;% 求积分quadv((r)quadv((b)quadv((a)f(a,b,r), 0, 2*pi), 0, 2*pi), 0, h) 错误在于&#xff0c;调用函数f( x )缺一个…

matlab plot输入参数太多,输入参数太多问题

版本&#xff1a;R2016a 利用SCE-UA调用新安江模型进行率定时&#xff0c;显示参数太多&#xff0c;求大神指导。 clear; clc; spathcd P0(textread([spath,\matlabxingshanjiangyu.txt])); PP0(2,:);%降水量(mm) EI0(textread([spath,\matlabxingshanzhengfa.txt])); EIEI0(2,…

参数输入太多

参数输入太多 在向platEMO平台添加新的算法时&#xff0c;可能会出现参数输入太多的错误提示 可能是由于输入的参数内包含逗号&#xff0c;比如 a[1,2],b[3,4] 从而造成”输入参数太多“的错误提示。

MATLAB S-function(教程分享) 报错 flag = 3(output), at time 0.0. 输入参数的数目不足。

前言 从上周开始用S-function做仿真&#xff0c;之前已经学过的&#xff0c;我觉得很好的教程网址是 【0基础直接带你上手matlab simulink仿真&#xff08;不是标题党&#xff0c;讲解超级细致用心&#xff09;&#xff08;非线性系统自适应控制器的搭建&#xff09;】 https…

matlab报错“输入参数的数目不足”

图片源自下方链接 原文链接MATLAB中出现参数数目不足的错误提示 - 爱上对方过后就哭了忆 - 博客园 (cnblogs.com)

错误使用 max 输入参数的数目不足。

相比大多数人熟悉的在调用自己编写的函数时出现的 “输入参数的数目不足” 问题&#xff0c;该情况下&#xff08;即在同一脚本或同一函数中&#xff09;也会出现matlab内部函数调用问题&#xff08;如max、min等&#xff09;&#xff0c;在编程时应注意此点&#xff01;

Matlab运行自定义函数显示“输入参数的数目不足”

问题描述 很多初学者在刚开始学习使用Matlab自定义函数时&#xff0c;可能遇到程序上没有问题&#xff0c;但一运行就显示输入参数的数目不足这个问题。 比如自定义一个函数&#xff1a;查找最小的m&#xff0c;使得m满足12…m > k&#xff08;k为任意一个整数&#xff09;…

浏览器播放视频倍速方法

1.右击播放页面 2.选择检查 4.选择console&#xff0c;如图&#xff1a; 5.在下面输入 &#xff1a;videojs.getPlayers("video-player").html5player.tech_.setPlaybackRate(1.5)&#xff0c;括号里的数字就是要加倍的倍速。

浏览器播放RTSP

浏览器播放RTSP 由于现在浏览器不直接支持RTSP&#xff0c;然后很多监控厂商如海康大华等又不提供RTMP的情况下&#xff0c;项目需要实现HTML中播放监控视频。之前做过转流的方案&#xff0c;在服务器中把RTSP转成RTMP&#xff0c;这种方案开发量大而且转码不稳定&#xff0c;…