实例验证 - call delegatecall
实例验证下call,delegatecall,两种方式下msg.sender和数据storage存储位置的区别
合约A
pragma solidity ^0.8.19;
contract A {
address public temp1;
uint256 public temp2;
function three_call(address addr) public {
(bool success, bytes memory result) = addr.call(
abi.encodeWithSignature("test()")
); // 1
require(success, "The call to B contract failed");
}
function three_delegatecall(address addr) public {
(bool success, bytes memory result) = addr.delegatecall(
abi.encodeWithSignature("test()")
); // 2
require(success, "The delegatecall to B contract failed");
}
}
合约B
pragma solidity ^0.8.19;
contract B {
address public temp1;
uint256 public temp2;
function test() public {
temp1 = msg.sender;
temp2 = 100;
}
}
call 测试
B合约地址:0x086866663330344C7D1C51Bf19FF981AF3cB5782
A合约地址:0x05715D87C062B9685DD877d307b584bAbec964Ed
交易发起地址:0x6BC0E9C6a939f8f6d3413091738665aD1D7d2776
执行前数据
A | B | |
---|---|---|
temp1 | 0x0000000000000000000000000000000000000000 | 0x0000000000000000000000000000000000000000 |
temp2 | 0 | 0 |
A合约执行three_call
,参数为B合约地址
执行后数据
A | B | |
---|---|---|
temp1 | 0x0000000000000000000000000000000000000000 | 0x05715D87C062B9685DD877d307b584bAbec964Ed |
temp2 | 0 | 100 |
delegatecall 测试
B合约地址:0x27153EDA2E085534811b040f6062f6528D6B80a1
A合约地址:0xd3C23F354Ca2160E6dC168564AB8954146cF35C9
交易发起地址:0x6BC0E9C6a939f8f6d3413091738665aD1D7d2776
执行前数据
A | B | |
---|---|---|
temp1 | 0x0000000000000000000000000000000000000000 | 0x0000000000000000000000000000000000000000 |
temp2 | 0 | 0 |
A合约执行three_delegatecall
,参数为B合约地址
执行后数据
A | B | |
---|---|---|
temp1 | address: 0x6BC0E9C6a939f8f6d3413091738665aD1D7d2776 | 0x0000000000000000000000000000000000000000 |
temp2 | 100 | 0 |
总结
- A发起地址->B合约call->C合约
msg.sender为B合约地址,非原始A发起地址,数据保存在C合约中 - A地址->B合约delegatecall->C合约
msg.sender为A发起地址,数据保存在B合约中
注意
callcode 已经在solidity 0.5+废弃,被delegatecall取代,故不做分析测试
TypeError: "callcode" has been deprecated in favour of "delegatecall".