以太坊合约调用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合约地址)

  • 3
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值