以太坊合约调用call、callcode和delegatecall的联系与区别

    在以太坊中,若需要合约与合约之间的调用,则可以使用call、callcode和delegatecall方法,它们之间的联系如下:

调用方式修改storage调用者的msg.sender被调用的msg.sender执行的上下文推荐
call修改被调用者的合约storage交易的发起者地址调用者地址被调用者
callcode修改调用者的合约storage调用者地址调用者地址在调用者里
delegatecall修改调用者的合约storage交易的发起者地址调用者地址在调用者里

    这里以合约EthAlice调用合约EthBob为例,进行说明,其执行流程如下:

图(1) 合约间的调用流程(Alice调用Bob)

1、调用者EthAlice

    //ehtAlice.sol

pragma solidity ^0.4.18;

contract EthAlice {
    uint    public num;
    address public addr;
    function callSetNum(address ads, uint value) public returns(uint) {
        require(ads.call(bytes4(keccak256("SetNum(uint256)")), value));
        return value;
    }

    function callcodeSetNum(address ads, uint value) public returns(uint) {
        require(ads.callcode(bytes4(keccak256("SetNum(uint256)")), value));
        return value;
    }

    function delegatecallSetNum(address ads, uint value) public returns(uint) {
        require(ads.delegatecall(bytes4(keccak256("SetNum(uint256)")), value));
        return value;
    }
}

2、被调用者EthBob

    //ethBob.sol

pragma solidity ^0.4.18;

contract EthBob {
    uint    public num;
    address public addr;

    event sendAddr(address);
    function SetNum(uint _num) public {
        num = _num;
        addr = msg.sender;
        emit sendAddr(msg.sender);
    }
}

3、部署合约

    在MetaMask里选择一个Rinkeby测试网账户,比如0x6026DfB9816D22F65F1011639B207B1c3A2C2e84
,然后在Remix上部署EthAlice和EthBob合约,得到如下:
    EthAlice合约地址:0xeb0282Dcd268afCFeAFA84ea2260edC2c7747381
    EthBob合约地址:0xe981880Ac36360A1bF4F8F2a369877dbE29Aa8d4

3.1 测试call()调用方式

    在Remix里的部署页面里,点开ETHALICE --> callSetNum 输入如下2个参数:
ads:0xe981880Ac36360A1bF4F8F2a369877dbE29Aa8d4
value:32
    如图(2) 所示:

图(2) call()调用方式

    Alice通过call()方式,修改的是Bob的num:0–>32,
而不是自身的num:0–>0;
    即call()方式,修改的是被调用者的storage
    Alice的msg.sender = 交易的发起者地址
    Bob的msg.sender = 调用者地址(Alice合约地址)

3.2 测试callcode()调用方式

    在Remix里的部署页面里,点开ETHALICE --> callcodeSetNum 输入如下2个参数:
ads:0xe981880Ac36360A1bF4F8F2a369877dbE29Aa8d4
value:34
    如图(3) 所示:

图(3) callcode()调用方式

    Alice通过callcode()方式,修改的是自身num:32–>34,
它不会修改Bob的num:32–>32;
    即callcode()方式,修改的是调用者自身的storage
    Alice的msg.sender = 调用者地址(Alice合约地址)
    Bob的msg.sender = 调用者地址(Alice合约地址)

3.3 测试delegatecall()调用方式

    在Remix里的部署页面里,点开ETHALICE --> delegatecallSetNum 输入如下2个参数:
ads:0xe981880Ac36360A1bF4F8F2a369877dbE29Aa8d4
value:36
    如图(4) 所示:

图(4) delegatecode()调用方式

    Alice通过delegatecall()方式,修改的是自身num:34–>36,
它不会修改Bob的num:32–>32;
    即delegatecall()方式,修改的是调用者自身的storage
    Alice的msg.sender = 交易的发起者地址
    Bob的msg.sender = 调用者地址(Alice合约地址)

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 深蓝海洋 设计师:CSDN官方博客 返回首页