在旧版本里面还有个callcode,现在是0.8.0版本,已经被废弃掉了
代码
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract a {
uint public x;
address public addr;
function func() public {
x = 100;
addr = msg.sender;
}
}
contract b {
uint public x;
address public addr;
function testCall(address _addr) public {
_addr.call(abi.encodeWithSignature("func()"));
}
function testDelegatecall(address _addr) public {
_addr.delegatecall(abi.encodeWithSignature("func()"));
}
}
然后使用remix部署
测试call方法

调用之后会发现,合约a中的数据会发生变化,其中a的x值会变为100,a的addr会变为合约b的地址

测试delegatecall方法

可以看到,调用完后变化的不是a的合约数据,而是b的合约数据,其实就相当于把a中的方法放到b中进行执行,而msg.sender并不是b的合约地址,而是调用b的那个地址,所以b的x为100,addr是调用b的testDelegatecall方法的外部地址。
需要注意的一个点就是,在合约a和b中,两个变量的位置顺序必须一致,如果在b合约中先定义addr,后定义x,刚好和合约a的顺序相反,在调用testDelegatecall方法虽然不会抛异常,但是x和addr的值都是错的。
总结
| 方法 | msg.sender | 作用域 |
|---|---|---|
| call | 调用者的地址 | 被调用者中 |
| delegatecall | 外部地址 | 调用者中 |