智能合约通俗点说就是写在区块链上面的代码,代码里面编写着严谨完善的规则,一旦某个用户满足了合约里面的规则条件,就会触发里面的代码,执行某个方法。
二. 为什么要使智能合约达到可升级
智能合约的特点之一就是部署到链上之后不能修改,这一机制使得合约的交互方都可以信任合约。但也带来了一系列的问题,并且如果已部署的合约发现漏洞,也是无法修复的。假如发现了bug,致命性的,必须修复,那如何处理? 就是使用合约达到可升级优化才能满足需求
三. 升级合约的机制原理
- 什么是合约升级
使已经部署上链的合约做到可优化可更改,例如链上的业务逻辑代码和状态变量达到可增删改的功能.
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){
_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 0){
_mint(account,amount);
}
}
function burn(address account,uint256 amount) external {
if(account != address(0) && amount > 0){
_burn(account,amount);
}
}
}
此合约修改了mint的金额必须需要小于等于10,用于升级之后的逻辑检验。
五. 以上代码的使用逻辑介绍以remix做案例使用:
一.部署业务逻辑合约(可升级erc20合约)
第二步.部署工厂合约
第三步调用工厂合约创建可升级的erc20Token合约
调用createProxy传入第一步创建的可升级erc20合约地址
创建成功之后,点击logicProxy查看生成之后的代理地址
然后调用at方法,并且选择相应的逻辑合约即可调用.(at使用方式和原理可自行查看)
第四步 升级当前的erc20合约
打开工厂合约调用updateLogicProxy传入新合约的地址,即可完成升级.
(用户无感升级)
五. 升级逻辑
⚠️ 升级注意事项
1.插槽的冲突风险
2.升级之后继承关系
总结合约升级风险会比较大,尽量严谨,并且升级要做到只增不减不修改.
以上就是今天要讲的内容,本文仅仅简单介绍了delegateCall的升级使用,关于安全方面还是需要自行根据业务去加限制,如有其他不正确的欢迎指出,或者DM