CALL、CALLCODE 和 DELEGATECALL 的區別
CALL 和 CALLCODE 採用相同數量的操作數(在執行堆棧中)。對於被壓入棧頂的異常標誌:0表示異常,1表示執行成功。CALL 很容易理解,但我無法理解 CALL 和 CALLCODE 之間的細微差別。黃皮書中指出,對於
CALLCODE:這意味著收件人實際上與目前的帳戶相同,只是程式碼被覆蓋了。
程式碼被覆蓋是什麼意思?這是否意味著我可以要求合約執行一些外部程式碼?如果有人可以為我提供一個範例來區分兩者,那將會很有幫助。
編輯:在 Homestead 中添加了 DELEGATECALL 有什麼區別?
DELEGATECALL
基本上說我是一個契約,我允許(委託)你對我的儲存做任何你想做的事情。DELEGATECALL
對於發送合約來說是一個安全風險,它需要相信接收合約會很好地處理儲存。
DELEGATECALL
是一個新的操作碼,它是一個錯誤修復,CALLCODE
它沒有保留msg.sender
和msg.value
. 如果愛麗絲呼叫DELEGATECALL
對查理做的鮑勃,則msg.sender
inDELEGATECALL
是 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 時,在 E
msg.sender
內部是 D,如上面程式碼中所述。當帳戶 C 呼叫 D,並且**D對 E 執行DELEGATECALL
msg.sender
**時,**E****內部是 C。**也就是說,E與D具有相同的msg.sender
和。msg.value