solidity中call和delegatecall的区别

415 阅读1分钟

在旧版本里面还有个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方法

testCall

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

contractA

测试delegatecall方法

testDelegatecall

可以看到,调用完后变化的不是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外部地址调用者中