注册
关闭
区块链大帝

区块链大帝

发布于 3周前 阅读数 4919

在0.6.8版本的solidity中,使用delegatecall进行合约升级

在0.4.26版本的solidity中,delegatecall的返回值只有1个,表示delegatecall是否调用成功的布尔变量。

在0.6.8版本的solidity中,delegatecall的返回值有2个,一个是表示delegatecall是否调用成功的布尔变量,另一个则是被调用函数的返回值。

通过delegatecall调用逻辑合约来修改数据合约中的状态变量,从而实现数据和逻辑分离。后面可以通过升级逻辑合约来改变业务逻辑,但数据合约不能升级。

下面通过例子来说明在0.6.8版本的solidity中如何使用delegatecall进行合约升级。

合约代码:

pragma solidity ^0.6.8;

// 数据合约

contract DataContract {

uint256 public num1;

uint256 public num2;

uint256 public num3;

address public issuer;

 

event Log(string str, bool result);

event Log2(string str, uint256 result);

constructor() public {

issuer = msg.sender;

num1 = 1;

num2 = 2;

num3 = 3;

}

function callLogicContract(address logicContractAddr) public {

bool r;

bytes memory s;

// 通过delegatecall调用逻辑合约来修改数据合约中的状态变量,从而实现数据和逻辑分离。后面可以通过升级逻辑合约来改变业务逻辑,但数据合约不能升级

(r, s) = logicContractAddr.delegatecall(abi.encodeWithSignature(“test(address)”, this));

emit Log(“delegatecall return “, r); // r为true或false

uint256 result = bytesToUint(s);

emit Log2(“test() return “, result);

}

function bytesToUint(bytes memory b) public pure returns (uint256){

uint256 number;

for(uint i= 0; i<b.length; i++){

number = number + uint8(b[i])*(2**(8*(b.length-(i+1))));

}

return number;

}

function setNum1(uint256 s) public {

num1 = s;

}

function setNum2(uint256 s) public {

num2 = s;

}

function setNum3(uint256 s) public {

num3 = s;

}

function getNum1() public view returns(uint256){

return num1;

}

function getNum2() public view returns(uint256){

return num2;

}

function getNum3() public view returns(uint256){

return num3;

}

}

// 升级前的逻辑合约

contract LogicContract {

uint256 public num1;

uint256 public num2;

uint256 public num3; //num1, num2, num3声明的顺序和位置必须和DataContract中的一样,否则无法修改DataContract中的num3

address public caller;

address public dataContract;

event Log(string str, uint256 num);

event Log2(string str, address addr);

function test(address addr) public returns(uint256) {

dataContract = addr; // 数据合约DataContract地址

caller = msg.sender; // 运行数据合约DataContract的以太坊账号

num3 = num3*10; // DataContract通过delegatecall调用LogicContract的test函数,test函数里修改的是DataContract中的num3而不是LogicContract中的num3

emit Log(“after upgrading contract, num3=”, num3);

emit Log2(“dataContract=”, dataContract);

emit Log2(“caller=”, caller);

return num3;

}

}

// 升级后的逻辑合约

contract LogicContract2 {

uint256 public num1;

uint256 public num2;

uint256 public num3; //num1, num2, num3声明的顺序和位置必须和DataContract中的一样,否则无法修改DataContract中的num3

address public caller;

address public dataContract;

 

event Log(string str, uint256 num);

event Log2(string str, address addr);

function test(address addr) public returns(uint256) {

dataContract = addr; // 数据合约DataContract地址

caller = msg.sender; // 运行数据合约DataContract的以太坊账号

num3 = num3*300; // DataContract通过delegatecall调用LogicContract的test函数,test函数里修改的是DataContract中的num3而不是LogicContract2中的num3

emit Log(“after upgrading contract, num3=”, num3);

emit Log2(“dataContract=”, dataContract);

emit Log2(“caller=”, caller);

return num3;

}

}

地址列表:

运行数据合约DataContract的以太坊账号:0xC264358Ef94b48B62e7F94ce10795255f8b9EED7

数据合约DataContract地址: 0x4ABFb9D52f63834b2A30B42202Be4F43C8CC8b48

逻辑合约LogicContract地址: 0x565d6eE58b7D0d4BbdA5e2E337eaada2D634B40D

逻辑合约LogicContract2地址: 0x9c9f6158adC9B7E9FE5fF99cEE27eECE6433edCb

运行结果的输出日志:

升级合约前,调用合约LogicContract的test函数的日志输出

logs [

{

“from”: “0x4abfb9d52f63834b2a30b42202be4f43c8cc8b48”,

“topic”: “0xdd970dd9b5bfe707922155b058a407655cb18288b807e2216442bca8ad83d6b5”,

“event”: “Log”,

“args”: {

“0”: “after upgrading contract, num3=”,

“1”: “30”,

“str”: “after upgrading contract, num3=”,

“num”: “30”,

“length”: 2

}

},

{

“from”: “0x4abfb9d52f63834b2a30b42202be4f43c8cc8b48”,

“topic”: “0x953bb7c6c7f939308a523ff2ce38248d9a26e7e8212c5f982fd8dffaca3fc523”,

“event”: “Log2”,

“args”: {

“0”: “dataContract=”,

“1”: “0x4ABFb9D52f63834b2A30B42202Be4F43C8CC8b48”,

“str”: “dataContract=”,

“addr”: “0x4ABFb9D52f63834b2A30B42202Be4F43C8CC8b48”,

“length”: 2

}

},

{

“from”: “0x4abfb9d52f63834b2a30b42202be4f43c8cc8b48”,

“topic”: “0x953bb7c6c7f939308a523ff2ce38248d9a26e7e8212c5f982fd8dffaca3fc523”,

“event”: “Log2”,

“args”: {

“0”: “caller=”,

“1”: “0xC264358Ef94b48B62e7F94ce10795255f8b9EED7”,

“str”: “caller=”,

“addr”: “0xC264358Ef94b48B62e7F94ce10795255f8b9EED7”,

“length”: 2

}

},

{

“from”: “0x4abfb9d52f63834b2a30b42202be4f43c8cc8b48”,

“topic”: “0x52dd9d08c343f72c69027ade2a075f6242dba2eeca3a3c61bfd8d00d32f6bd20”,

“event”: “Log”,

“args”: {

“0”: “delegatecall return “,

“1”: true,

“str”: “delegatecall return “,

“result”: true,

“length”: 2

}

},

{

“from”: “0x4abfb9d52f63834b2a30b42202be4f43c8cc8b48”,

“topic”: “0x0c231cace93330e81aabd308eaecd9a98302e543efad0c88d0b99732e7c2ef5f”,

“event”: “Log2”,

“args”: {

“0”: “test() return “,

“1”: “30”,

“str”: “test() return “,

“result”: “30”,

“length”: 2

}

}

]

升级合约后,调用合约LogicContract2的test函数的日志输出

logs [

{

“from”: “0x4abfb9d52f63834b2a30b42202be4f43c8cc8b48”,

“topic”: “0xdd970dd9b5bfe707922155b058a407655cb18288b807e2216442bca8ad83d6b5”,

“event”: “Log”,

“args”: {

“0”: “after upgrading contract, num3=”,

“1”: “9000”,

“str”: “after upgrading contract, num3=”,

“num”: “9000”,

“length”: 2

}

},

{

“from”: “0x4abfb9d52f63834b2a30b42202be4f43c8cc8b48”,

“topic”: “0x953bb7c6c7f939308a523ff2ce38248d9a26e7e8212c5f982fd8dffaca3fc523”,

“event”: “Log2”,

“args”: {

“0”: “dataContract=”,

“1”: “0x4ABFb9D52f63834b2A30B42202Be4F43C8CC8b48”,

“str”: “dataContract=”,

“addr”: “0x4ABFb9D52f63834b2A30B42202Be4F43C8CC8b48”,

“length”: 2

}

},

{

“from”: “0x4abfb9d52f63834b2a30b42202be4f43c8cc8b48”,

“topic”: “0x953bb7c6c7f939308a523ff2ce38248d9a26e7e8212c5f982fd8dffaca3fc523”,

“event”: “Log2”,

“args”: {

“0”: “caller=”,

“1”: “0xC264358Ef94b48B62e7F94ce10795255f8b9EED7”,

“str”: “caller=”,

“addr”: “0xC264358Ef94b48B62e7F94ce10795255f8b9EED7”,

“length”: 2

}

},

{

“from”: “0x4abfb9d52f63834b2a30b42202be4f43c8cc8b48”,

“topic”: “0x52dd9d08c343f72c69027ade2a075f6242dba2eeca3a3c61bfd8d00d32f6bd20”,

“event”: “Log”,

“args”: {

“0”: “delegatecall return “,

“1”: true,

“str”: “delegatecall return “,

“result”: true,

“length”: 2

}

},

{

“from”: “0x4abfb9d52f63834b2a30b42202be4f43c8cc8b48”,

“topic”: “0x0c231cace93330e81aabd308eaecd9a98302e543efad0c88d0b99732e7c2ef5f”,

“event”: “Log2”,

“args”: {

“0”: “test() return “,

“1”: “9000”,

“str”: “test() return “,

“result”: “9000”,

“length”: 2

}

}

]

我的csdn:https://blog.csdn.net/powervip

我的腾讯微云网盘:https://share.weiyun.com/5qT0TvG

我的github: https://github.com/powervip

如果你觉得这篇文章写得还可以,请帮忙点个赞,谢谢!

你的鼓励,我的动力!

本文链接:https://www.8btc.com/media/613592
转载请注明文章出处

  • 0
区块链大帝
区块链大帝

0 条评论