首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >CALL、CALLCODE和DELEGATECALL的区别

CALL、CALLCODE和DELEGATECALL的区别
EN

Ethereum用户
提问于 2016-05-06 16:21:20
回答 6查看 48.4K关注 0票数 109

CALL和CALLCODE的操作数相同(在执行堆栈中)。对于被推到堆栈顶部的异常标志:0表示异常,1表示成功执行。CALL很容易理解,但我无法理解CALL与CALLCODE之间的细微差别。黄纸上写着

CALLCODE:这意味着收件人实际上与目前的帐户相同,只是代码被覆盖了。

代码被覆盖是什么意思?这是否意味着我可以要求合同执行一些外部代码?如果有人能给我一个例子来区分这两种情况,那将是有帮助的。

编辑: DELEGATECALL是在“宅基地”中添加的,区别是什么?

EN

回答 6

Ethereum用户

回答已采纳

发布于 2016-05-06 19:45:39

DELEGATECALL基本上说我是一份合同,我允许(委托)你对我的存储做任何你想做的事情。DELEGATECALL是发送合同的一种安全风险,它需要信任接收方能够很好地处理存储问题。

DELEGATECALL是一个新的操作码,它是CALLCODE的一个bug修复程序,它没有保存msg.sendermsg.value。如果Alice调用对Charlie执行DELEGATECALL的Bob,则DELEGATECALL中的msg.sender是Alice (而如果使用CALLCODE,则msg.sender将是Bob)。

详细信息

当D调用E时,代码在E的上下文中运行:使用E的存储。

当D在E上执行CALLCODE时,代码在D的上下文中运行。因此,假设E的代码在D中,只要代码写入存储,它就写入帐户D的存储,而不是E。

代码语言:javascript
复制
contract D {
  uint public n;
  address public sender;

  function callSetN(address _e, uint _n) {
    _e.call(bytes4(sha3("setN(uint256)")), _n); // E's storage is set, D is not modified 
  }

  function callcodeSetN(address _e, uint _n) {
    _e.callcode(bytes4(sha3("setN(uint256)")), _n); // D's storage is set, E is not modified 
  }

  function delegatecallSetN(address _e, uint _n) {
    _e.delegatecall(bytes4(sha3("setN(uint256)")), _n); // D's storage is set, E is not modified 
  }
}

contract E {
  uint public n;
  address public sender;

  function setN(uint _n) {
    n = _n;
    sender = msg.sender;
    // msg.sender is D if invoked by D's callcodeSetN. None of E's storage is updated
    // msg.sender is C if invoked by C.foo(). None of E's storage is updated

    // the value of "this" is D, when invoked by either D's callcodeSetN or C.foo()
  }
}

contract C {
    function foo(D _d, E _e, uint _n) {
        _d.delegatecallSetN(_e, _n);
    }
}

当D在E上做CALLCODE时,E中的msg.sender是D,如上面代码中的注释所示。

当帐户C调用D,D对E执行副局长时,E内的msg.sender为C,即E与D具有相同的msg.sendermsg.value

你可以在中进行快速测试

票数 131
EN

Ethereum用户

发布于 2018-11-24 15:00:05

显示调用、调用代码和委托代码之间的区别,我们可以考虑以下代码的示例:

合同可以通过三种方式相互作用

  1. 调用:通过一个函数直接从合同中调用,该函数不会设置调用者的值,而是设置被调用者的值。而其中的发送方将仅是调用方。
  2. CallCode :当通过CallCode调用时,调用者调用被调用者的函数并表示自己的值(或者用被调用的参数来更改自己的值),但是没有变化反映到被调用者的存储中。这里,发送者也是呼叫者本身。
  3. DelegateCall :当第三个契约代表调用方调用被调用方对被调用方中的某个函数的委托调用时,对调用方的值进行存储更改,而在被调用方的存储中没有任何反映。在这里,发件人不再是呼叫者,而是第三个契约呼叫助手。

普拉格玛坚实度^0.4.0;

代码语言:javascript
复制
contract Caller {
uint public value;
address public sender;

function callSetValue(address _callee, uint _value) {
    _callee.call(bytes4(sha3("setValue(uint256)")), _value); // Callee's storage is set as given , Caller's is not modified 
}

function callcodeSetValue(address _callee, uint _value) {
    _callee.callcode(bytes4(sha3("setValue(uint256)")), _value); // Caller's storage is set, Calee is not modified 
}

function delegatecallSetValue(address _callee, uint _value) {
    _callee.delegatecall(bytes4(sha3("setValue(uint256)")), _value); // Caller's storage is set, Callee is not modified 
}
}

contract Callee {
uint public value;
address public sender;

function setValue(uint _value) {
    value = _value;
    sender = msg.sender;
    // msg.sender is Caller if invoked by Caller's callcodeSetValue. None of Callee's storage is updated
    // msg.sender is OnlyCaller if invoked by onlyCaller.justCall(). None of Callee's storage is updated

    // the value of "this" is Caller, when invoked by either Caller's callcodeSetValue or CallHelper.justCall()
}
}

contract CallHelper {
    function justCall(Caller _caller, Callee _callee, uint _value) {
        _caller.delegatecallSetValue(_callee, _value);
    }
}
票数 7
EN

Ethereum用户

发布于 2020-07-10 16:34:14

对@eth的solidity v6示例的更新:

  • 函数定义必须是public
  • keccak256取代sha3
  • 调用参数使用abi.encode()
  • 得到契约地址的address()实体^0.6.0;契约D( uint public n;address public发件人;callSetN(address _e,uint _n) public (_e _n));// E的存储设置,D不修改} /*调用代码是折旧函数callcodeSetN(address _e,uint _n) public {_e_n);// D的存储被设置,E不修改} */函数delegatecallSetN(地址_e,uint _n)公共的{ _n);// D的存储被设置,E不修改}收缩E{ uint公共n;地址公共发送方;函数setN(uint _n) public {n= _n;发送者= msg.sender;// msg.sender是D的callcodeSetN调用的D。如果由msg.sender ()调用,E的存储没有更新// C.foo是C的。没有一个E的存储被更新/ "this“的值是D,如果由D的callcodeSetN或C.foo() }{ function (D _d,E _e,uint _n)调用,则为public {_d.delegatecallSetN(地址(_e),_n);}}
票数 6
EN
页面原文内容由Ethereum提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://ethereum.stackexchange.com/questions/3667

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档