call 会切换到被调合约中去执行方法,会切换上下文。msg.sender是主调合约地址。
delegatecall 则是将被调合约中的方法调到本合约中执行,也就是不会切换上下文。msg.sender是发起者本人。
另外,还有staticcall是 call 的只读版本,适用于调用不会修改状态的函数。在调用期间,合约的状态无法被改变。
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract SetNum {
uint256 public n = 20;
address public sender;
function setN(uint256 _n) public {
n = _n;
sender = msg.sender;
}
}
contract CallSet {
uint256 public n = 15;
address public sender;
function CallTest(address _addr, uint256 _n) public {
_addr.call(abi.encodeWithSignature("setN(uint256)", _n)); //改变SetNum中的n值
sender = msg.sender; //是调用者本人,同时会改变SetNum的sender地址
//(bool success, bytes memory returnData) = _addr.staticcall(data);
}
function delegatecallTest(address _addr, uint256 _n) public {
_addr.delegatecall(abi.encodeWithSignature("setN(uint256)", _n)); //改变自身的n值
//(bool success, bytes memory data) = _contract.delegatecall(
// abi.encodeWithSignature("setVars(uint256)", _num)
// );
sender = msg.sender; //是调用者本人,不会改变SetNum的sender地址
}
}
// 注意: delegatecall是相当于将被调合约的函数引入自身中执行,所以,这两个合约中的状态变量要一致!否则容易出错。
// 传入的参数(address _addr)是合约地址。
RE: Solidity开发指南