合约四种 call 区别

CALL|CALLCODE|DELEGATECALL|STATICCALL

四种调用的区别

CALL & STATICCALL

CALL 调用的上下文环境是被调用合约的环境,修改的是被调用合约的 state,调用者函数不能为 view。

CALL ContractB
CALL ContractB

STATICCALL 只能调用不修改 state 的函数(pure view 修饰的函数),调用者函数可以为 view。

STATICCALL ContractB
STATICCALL ContractB
// SPDX-License-Identifier: GPL-3.0

pragma solidity ^0.8.0;

// 调用者
contract ContractA {

    uint256 x;

    function add(uint256 _num) public {
        x = x + _num;
    }

    function getX() external view returns(uint256) {
        return x;
    }

}

// 被调用者
contract ContractB {

    function call(address _addr, uint256 _num) external {
        bytes memory data = abi.encodeWithSignature("add(uint256)", _num);
        (bool result, ) = _addr.call(data);
        require(result, "transaction failed");
    }

    function staticcall(address _addr) external view returns(uint256) {
        bytes memory data = abi.encodeWithSignature("getX()");
        (bool result, bytes memory returnNum) = _addr.staticcall(data);
        require(result, "transaction failed");
        return abi.decode(returnNum, (uint256));
    }

}

CALLCODE & DELEGATECALL

CALLCODE已被DELEGATECALL取代,区别就是 msg.sender不同。DELEGATECALL会一直使用原始调用者的地址,而CALLCODE不会。

post image

委托调用的上下文环境是调用者合约的环境,也就是说msg.sender是用户。通常用在可升级的代理合约中。