Contract-Design

CALL、CALLCODE 和 DELEGATECALL 的區別

  • July 18, 2021

CALL 和 CALLCODE 採用相同數量的操作數(在執行堆棧中)。對於被壓入棧頂的異常標誌:0表示異常,1表示執行成功。CALL 很容易理解,但我無法理解 CALL 和 CALLCODE 之間的細微差別。黃皮書中指出,對於

CALLCODE:這意味著收件人實際上與目前的帳戶相同,只是程式碼被覆蓋了。

程式碼被覆蓋是什麼意思?這是否意味著我可以要求合約執行一些外部程式碼?如果有人可以為我提供一個範例來區分兩者,那將會很有幫助。

編輯:在 Homestead 中添加了 DELEGATECALL 有什麼區別?

DELEGATECALL基本上說我是一個契約,我允許(委託)我的儲存做任何你想做的事情。 DELEGATECALL對於發送合約來說是一個安全風險,它需要相信接收合約會很好地處理儲存。

DELEGATECALL是一個新的操作碼,它是一個錯誤修復,CALLCODE它沒有保留msg.sendermsg.value. 如果愛麗絲呼叫DELEGATECALL對查理做的鮑勃,則msg.senderinDELEGATECALL是 Alice(而如果CALLCODE被使用,msg.sender則將是 Bob)。

細節

當 D 對 E 執行 CALL 時,程式碼在 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 時,在 Emsg.sender內部是 D,如上面程式碼中所述。

當帳戶 C 呼叫 D,並且**D對 E 執行DELEGATECALLmsg.sender**時,**E****內部是 C。**也就是說,E與D具有相同的msg.sender和。msg.value

您可以在 Solidity Browser 中快速測試以上內容

引用自:https://ethereum.stackexchange.com/questions/3667