Solidity

備份功能使用過多的氣體?

  • October 30, 2017

我寫了這份契約,但 Remix 抱怨它使用了太多的氣體。我究竟做錯了什麼?

“合約瀏覽器的備份功能/SplitBalance.sol:SplitBalance 需要的gas太多(40612)。如果備份功能需要超過2300的gas,則合約無法接收乙太幣。”

pragma solidity ^0.4.10;

contract SplitBalance{

   address a1;
   address a2;
   uint account1;
   uint account2;

   function SplitBalance(address _a1, address _a2) public{
       a1 = _a1;
       a2 = _a2;
   }

   function withdraw(address _addr) public {
       if (_addr == a1)   
       {
           account1 = 0;
           a1.transfer(account1);
       }
       else if (_addr == a2)   
       {
           account2 = 0;
           a2.transfer(account2);
       }
   }

   function updateAddress1(address newAddress) public {
       if(msg.sender != a1)
          revert();
       a1 = newAddress;
   }

   function updateAddress2(address newAddress) public {
       if(msg.sender != a2)
          revert();
       a2 = newAddress;
   }

   function() payable public { 
       uint amount = msg.value/2;
       account1 = account1 + amount;
       account2 = account2 + amount;
   }
}

Solidity 中的備份(預設/未命名)函式預設只有 2300 個 gas 的 gas 限額——這足以創建一個事件日誌:

如果合約收到 Ether(沒有呼叫函式),則執行回退函式。…在執行回退功能期間,合約只能依靠當時可用的“gas stipend”(2300 gas)。這筆津貼不足以以任何方式訪問儲存。

源可靠文件

因此,除非呼叫者明確提供更多氣體,否則在該函式中添加諸如更新乙太坊儲存變數之類的邏輯將不起作用;正如文件指出的那樣,您不能依賴在執行期間可用的額外氣體。

一種解決方案是將你的邏輯轉移到一個新的支付函式中——當使用者想要將乙太幣發送到合約時呼叫該函式;這將取代在回退函式中包含邏輯(如果乙太被錯誤地發送到合約,您可以讓回退函式拋出)。

好吧,當您更改合約的狀態時,例如在狀態變數中儲存新值,那麼這比在記憶體中儲存值更昂貴。例如,您寫 account1 = account1 + amount。但這不是什麼大問題,你只需要在向合約發送 ETH 時增加你的 gas 限制,否則交易可能會失敗。

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