1、直接在代理合约上加代理的地址直接在代理合约上加代理的地址,这样只能加到原有合约的最下边,这样不会破坏存储空间顺序,这样会改动原有合约不建议使用。//https://nxf4usxfbgm.feishu.cn/docx/KmuadfFRVotvWIxw1jhc6KyHnof?openbrd=
直接在代理合约上加代理的地址,这样只能加到原有合约的最下边,这样不会破坏存储空间顺序,这样会改动原有合约不建议使用。
// https://nxf4usxfbgm.feishu.cn/docx/KmuadfFRVotvWIxw1jhc6KyHnof?openbrd=1&doc_app_id=501&blockId=Ah28dFItmoVDYixCMs1cI3Tpnig&blockType=whiteboard&blockToken=GiRuw7FDph0pWVbE8FVccXIhnDg#Ah28dFItmoVDYixCMs1cI3Tpnig
pragma solidity ^0.8.0;
contract CounterV1{
uint public count;
function addCount(uint256 i) public {
count+=1;
}
function getCount() public view returns (uint256){
return count;
}
address public impl;
}
contract ProxyCounter{
uint public count;
function addCount(uint i) public {
bytes memory callData =abi.encodeWithSignature("addCount(uint256)", i);
(bool succ, ) = address(impl).delegatecall(callData);
if (!succ) revert("delegatecall fail");
}
function getCount() external returns (uint256){
bytes memory callData =abi.encodeWithSignature("getCount()");
(bool succ, bytes memory data) = address(impl).delegatecall(callData);
if (!succ) revert("delegatecall fail");
return abi.decode(data, (uint256));
}
function upgrade(address addr) public {
impl = addr;
}
address public impl;
}
contract CounterV2{
uint public count;
function addCount(uint256 i) public {
count+=i;
}
function getCount() public view returns (uint256){
return count;
}
address public impl;
}
只需要更改代理合约,原有合约不需要改变,把需要升级的合约地址添加到upgradeTo方法即可
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;
contract CounterV1{
uint public count;
function addCount(uint256 i) public {
count+=1;
}
function getCount() public view returns (uint256){
return count;
}
}
contract ProxyCounter{
uint public count;
event Upgraded(address indexed implementation);
function addCount(uint i) external {
bytes memory callData =abi.encodeWithSignature("addCount(uint256)", i);
(bool succ, ) = _getImplementation().delegatecall(callData);
if (!succ) revert("delegatecall fail");
}
function getCount() external returns (uint256){
bytes memory callData =abi.encodeWithSignature("getCount()");
(bool succ, bytes memory data) =_getImplementation().delegatecall(callData);
if (!succ) revert("delegatecall fail");
return abi.decode(data, (uint256));
}
constructor(){}
function upgradeTo(address newImplementation) external {
require(newImplementation != address(0), "Invalid address");
bytes32 slot = bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1);
// 检查新实现合约是否符合要求
// 例如:检查合约是否支持特定接口
assembly {
sstore(slot, newImplementation)
}
emit Upgraded(newImplementation);
}
function _getImplementation() private view returns (address) {
bytes32 slot = bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1);
address impl;
assembly {
impl := sload(slot)
}
return impl;
}
}
contract CounterV2{
uint public count;
function addCount(uint256 i) public {
count+=i;
}
function getCount() public view returns (uint256){
return count;
}
}
直接代理把原有合约放到upgradeTo方法里边进行代理,然后在remix部署原有合约at address里边填写代理合约地址就直接可以代理; 升级合约先部署好然后放到代理合约upgradeTo方法里边进行代理,然后在remix部署原有合约at address里边填写代理合约地址就直接可以代理,在升级合约执行业务逻辑,代理合约里边的值也会随着改变
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.0;
contract CounterV1{
// address public impl;
uint public count;
function addCount(uint256 i) public {
count+=1;
}
function getCount() public view returns (uint256){
return count;
}
}
contract ProxyCounter{
uint public count;
// EIP-1967 实现合约存储插槽
bytes32 private constant _IMPLEMENTATION_SLOT =
bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1);
// constructor(address implementation) {
// // require(implementation.isContract(), "Proxy: implementation is not a contract");
// _setImplementation(implementation);
// }
function upgradeTo(address _newImplementation) public {
_setImplementation(_newImplementation);
}
function _setImplementation(address newImplementation) private {
bytes32 slot = _IMPLEMENTATION_SLOT;
assembly {
sstore(slot, newImplementation)
}
}
receive() external payable {
_delegate(_implementation());
}
fallback() external payable {
_delegate(_implementation());
}
function _implementation() internal view returns (address impl) {
bytes32 slot = _IMPLEMENTATION_SLOT;
assembly {
impl := sload(slot)
}
}
function _delegate(address implementation) internal {
assembly {
calldatacopy(0, 0, calldatasize())
let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
returndatacopy(0, 0, returndatasize())
switch result
case 0 { revert(0, returndatasize()) }
default { return(0, returndatasize()) }
}
}
}
contract CounterV2{
uint public count;
function addCount(uint256 i) public {
count+=i;
}
function getCount() public view returns (uint256){
return count;
}
}
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!