Gas

為什麼 DELEGATECALL 在我的 Remix 合約中使用 94k gas?

  • August 5, 2017

我受到另一個問題的啟發,想了解更多關於堆棧深度攻擊的資訊。

當我嘗試attack(1023)在此契約上執行 Remix 時:

pragma solidity ^0.4.14;

contract Attacker {
   uint x;

   function attack(uint y) {
       if (y > x) {
           this.delegatecall(bytes4(sha3('attack(uint256)')), --y);
       }
       else {
           throw ; // doesn't matter, we never get here
       }
   }
}

使用 3M 氣體,我用完了氣體 228 呼叫深度。接近尾聲時,DELEGATECALL 指令似乎使用了大約 1.5k 的氣體。但是在第一個 DELEGATECALL 中,我看到了 94k。以下是我用來生成該數字的步驟:

  1. 使用 Javascript VM 在 Remix 中創建上述合約
  2. 稱呼attack(1023)
  3. 用完gas後點擊進入調試器
  4. 逐步打開“說明”欄,直到 DELEGATECALL 之前
  5. 在“步驟詳情”下注“剩餘氣體”5977987
  6. 點擊“步入前進”
  7. 在“步驟詳情”下注“剩餘氣體”5883892

**更新。**我將下面的答案留在原處,因為它有一些有趣的觀點,但我想我終於明白了這一點。

重點隱藏在Subtleties頁面中:

CALL 或 CREATE 最多可以消耗發出 CALL 時剩餘的 63/64 的 gas;如果 CALL 要求超過此規定的最大值,則內部呼叫將僅具有規定的最大 gas,無論要求多少 gas。

這在YP中解釋得很清楚,所以我不知道我是怎麼錯過的 :-) 在此處輸入圖像描述

因此,您的 CALL 並沒有消耗那麼多的氣體,而是您無法將所有想要傳遞的氣體傳遞給遞歸中的下一個 CALL。如果您的初始 gas 約為 640 萬,那麼您的第一個 CALLed 合約將收到比您想像的少約 100k 的 gas。我想這就是你所看到的。沒有傳遞給 CALL 的剩餘氣體在契約終止時仍然未使用,沒有用完。

所以 - 不是混音故障(抱歉,混音!)。如果有的話,看起來 testrpc 沒有執行此操作。


我認為這是 Remix 的報告問題。我已經針對 testrpc 執行了您的契約的一個小變體(即不是 Remix - 在我自己的環境中)並且看不到相同的內容。

pragma solidity ^0.4.13;

contract Attacker {
   uint256 x;

   function attack(uint256 y) payable returns(uint256) {
       if (y > 0) {
           this.delegatecall(bytes4(sha3('attack(uint256)')), --y);
       }
       else {
            // Save the remaining gas in storage so that we can access it later
            x = msg.gas;
            return;             
       }
   }
}

起始 y 是然後使用的次數delegatecall。它將剩餘的氣體量留在儲存中,可以使用eth_getStorageAt.

結果(y 是委託呼叫的數量,值是 gas 剩餘,diff 是這個和上一個之間的 gas 差異)。

  • y=0.2978464
  • y=1, 2977288, 差異 = 1176
  • y=2, 2976176, 差異 = 1112
  • y=3, 2975064, 差異 = 1112
  • y=4, 2973952, 差異 = 1112

在每種情況下,差異都是 1112 gas,包括零委託呼叫和一個委託呼叫之間的差異(除了額外的 64 gas,我認為這是由於 y=0 時初始呼叫數據中額外的零字節;這是按 4 gas 收費的而不是 68 用於非零字節)。

這基本上是我所期望的,這就是為什麼我認為 Remix 在這裡一定有點不穩定。

編輯:只是為了確認混音的古怪。使用相同的程序:從內部氣體測量(msg.gas放置在儲存中),Remix 報告每額外的時間輪委託呼叫進一步使用約 45000 氣體;但是,Remix 在合約選項卡上報告的合約執行成本每次委託呼叫僅增加 1339 gas。

請注意,gas 是在 of 之前計算sstorex,所以我們看不到這個的(大)成本。但沒關係,因為它是一次性的。

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