CALL和CALLCODE的操作数相同(在执行堆栈中)。对于被推到堆栈顶部的异常标志:0表示异常,1表示成功执行。CALL很容易理解,但我无法理解CALL与CALLCODE之间的细微差别。黄纸上写着
CALLCODE:这意味着收件人实际上与目前的帐户相同,只是代码被覆盖了。
代码被覆盖是什么意思?这是否意味着我可以要求合同执行一些外部代码?如果有人能给我一个例子来区分这两种情况,那将是有帮助的。
编辑: DELEGATECALL是在“宅基地”中添加的,区别是什么?
发布于 2016-05-06 19:45:39
DELEGATECALL基本上说我是一份合同,我允许(委托)你对我的存储做任何你想做的事情。DELEGATECALL是发送合同的一种安全风险,它需要信任接收方能够很好地处理存储问题。
DELEGATECALL是一个新的操作码,它是CALLCODE的一个bug修复程序,它没有保存msg.sender和msg.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。
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.sender和msg.value。
你可以在中进行快速测试。
发布于 2018-11-24 15:00:05
显示调用、调用代码和委托代码之间的区别,我们可以考虑以下代码的示例:
合同可以通过三种方式相互作用
普拉格玛坚实度^0.4.0;
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);
}
}发布于 2020-07-10 16:34:14
对@eth的solidity v6示例的更新:
publickeccak256取代sha3abi.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);}}https://ethereum.stackexchange.com/questions/3667
复制相似问题