Solidity

分析氣體使用和契約設計

  • September 23, 2021

假設我有以下合約程式碼:

pragma solidity ^0.4.23;

contract pensCollection{

   struct Pen{
       uint productCode;
       address ownerAddress;
   }

   address public owner;

   // history of a pen.
   mapping(uint => address[]) public __history;

   // One account can hold many pens.
   mapping(address => Pen[]) public __inventary;

   constructor () public{
       owner = msg.sender;
   }


   function addPen(uint _productCode, address _ownerAddress) public returns (address) {


       Pen memory _pen = Pen({
           productCode : _productCode,
           ownerAddress : _ownerAddress
           });
       __inventary[_ownerAddress].push(_pen);

       // Add history entry for this new pen.
       __history[_productCode].push(_ownerAddress);

       return msg.sender;
   }

   function exchangePen(address _buyer, uint _productCode) public returns (bool) {

      // Search for pen in the inventary.
       for (uint i = 0; i < (__inventary[msg.sender].length); i++) {

           // If I find it then change its owner address.
           if (__inventary[msg.sender][i].productCode == _productCode) {

               Pen memory _pen = Pen(
                   {
                   productCode : _productCode,
                   ownerAddress : _buyer
                   });
               __inventary[_buyer].push(_pen);
               __history[_productCode].push(_buyer);

               delete __inventary[msg.sender][i];
               return true;
           }
       }

       return false;
   }

   function getHistoryForPen(uint _productCode) public view returns (address[]) {
       return __history[_productCode];
   }
}

該合約應允許使用者將一系列筆註冊到智能合約中。有一個映射,對於每個所有者地址,我都有一個PenPen 是結構的數組。我可以使用方法將筆添加到集合(__inventary變數)中addPen(...)exchangePen(...)我還可以使用將給定筆轉移到買家地址並從舊所有者那裡移除的功能來交換筆。還有一個數組,稱為__history,其中註冊了所有運動(銷售/購買),使用者可以通過呼叫適當的方法獲取此數組。當我線上使用 remix 編譯此程式碼時,我會收到有關 gas 使用情況的警告,因為如果我是正確的,將數據儲存在合約狀態是一種不好的做法,它會消耗大量 gas,並且可能導致執行時異常耗盡氣體。

我的一個問題是:我怎樣才能導致這個異常?在得到 gasLimit 異常之前我應該插入多少支筆?

另一個問題是:我是否應該部署一個只代表一支筆的合約,具有傳輸和歷史的方法?我的意思是下面的契約比之前的更好嗎?

pragma solidity ^0.4.23;

contract PenContract{

   struct Pen{
       uint productCode;
       address ownerAddress;
   }

   address public owner;
   Pen public _pen;

   // history of a pen.
   address[] public __history;


   constructor (uint _productCode, address _ownerAddress) public{
       owner = msg.sender;
       _pen.productCode = _productCode;
       _pen.ownerAddress = _ownerAddress;

       // Add history entry for this new pen.
       __history.push(_ownerAddress);
   }


   function exchangePen(address _buyer) public returns (bool) {
       _pen.ownerAddress = _buyer;
       __history.push(_buyer);
       return true;            
   }

   function getHistoryForPen() public view returns (address[]) {
       return __history;
   }
}

換句話說,考慮到部署智能合約需要花費 32k gas(此處),是擁有一個管理所有筆的合約並讓您添加其他合約(可能導致 gas 限制問題)更好還是更好為每支筆部署一個契約(這也會導致問題嗎?)?

提前致謝。

可能重複:使用結構創建多個契約或單個契約

進一步的動態數組類型可以增長到 2^256-1 個元素。

我希望它有所幫助:我總是將數據儲存在映射而不是數組中。正如您所說,數組可能會變得非常昂貴。因此,您可以將您的筆儲存在映射中,然後使用無需任何成本的視圖函式對其進行迭代。只是一個註釋不是完整的答案😉

祝你契約順利

納爾珀

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