Solidity

智能合約錯誤:所需氣體超過 300000000

  • December 19, 2017

我從本教程中獲得了以下程式碼:

https://medium.com/@merunasgrincalaitis/the-ultimate-end-to-end-tutorial-to-create-and-deploy-a-fully-descentralized-dapp-in-ethereum-18f0cf6d7e0e

pragma solidity ^0.4.11;

contract Casino {


   uint minimumBet;
   uint totalBet;
   uint numberOfBets;
   uint maximumAmountsOfBets = 100;
   address[] players;

   struct Player {

       uint amountBet;
       uint numberSelected;
   }


   mapping(address => Player) playerInfo;


   address owner; // Long string from metamask


   function Casino(uint _minimumBet) public{  // Constructor : has the same name as the contract , used to set up
       //contract owner

       owner = msg.sender;
       if(_minimumBet !=0) minimumBet = _minimumBet;

       }

       //To be for a number btw 1 & 10 both inclusive


   function bet(uint number) payable public {

       require(checkPlayerExists(msg.sender) );
       require(number >= 1 && number <= 10);
       require(msg.value >= minimumBet);


       playerInfo[msg.sender].amountBet = msg.value;
       playerInfo[msg.sender].numberSelected = number;
       numberOfBets += 1;
       players.push(msg.sender);
       totalBet += msg.value;

       if(numberOfBets >= maximumAmountsOfBets) generateNumberWinner();


       }



   function checkPlayerExists(address player) public view returns(bool) {

       for( uint i = 0 ; i < players.length; i++){
           if(players[i] == player) return true;
       }
       return false;
   }


   /* 
   Generate Winner : Generates a number between 1 & 10 
   */

   function generateNumberWinner() public{

       uint numberGenerated = block.number % 10 + 1; // This isnt secure

       distributePrizes(numberGenerated);
   }


   /*

   Distribute Prizes : Sends the correspondng ether to each winner
   depending on the total bets 
   */

   function distributePrizes(uint numberWinner) public {

       address[100] memory winners ; // We have to create a temporary in memory array with fixed size

       uint count = 0; // This is the count for the array of winners

       for(uint i = 0; i < players.length ; i++) {
           address playerAddress = players[i];
           if(playerInfo[playerAddress].numberSelected == numberWinner){
               winners[count] = playerAddress;
               count ++;
           }
           delete playerInfo[playerAddress]; // Delete all the players array


       }

       players.length = 0; //Delete all the players array

       uint winnerEtherAmount = totalBet / winners.length; // How much each player gets 

       for(uint j = 0; j < count; j++) {

           if(winners[j] !=address(0)) // Check the address in the fixed array is not empty
           winners[j].transfer(winnerEtherAmount);
       }


   }

   /*
   Annonymous Fallback function: In case someone sends ether to the 
   contract so it doesnt get lost
   */
   function() payable private{}

/*
Kill function: Used to destroy contract whenever we want. Only owner
has the ability to kill the contract
*/

   function kill() private{ 

       if(msg.sender == owner)
           selfdestruct(owner);
   }
}

它編譯得很好,但是當我嘗試bet它時,REMIX 會拋出以下錯誤:

向 Casino.bet 交易錯誤:所需氣體超出限制:3000000。重要的氣體估計也可能表明契約程式碼存在問題。請檢查循環並確保您沒有將值發送到不可支付的函式(這也是強氣體估計的原因)。

如果有人能指出我正確的方向,我將不勝感激。

我相信這條線:

require(checkPlayerExists(msg.sender));

實際上應該說相反:

require(!checkPlayerExists(msg.sender));

玩家第一次呼叫時不可能存在bet,因此require中止了事務。

假設您正在關注https://medium.com/@merunasgrincalaitis/the-ultimate-end-to-end-tutorial-to-create-and-deploy-a-fully-descentralized-dapp-in-ethereum-18f0cf6d7e0e,請注意,他們有這條線,這大致相當於我的建議。(但我認為require這裡比 . 更合適assert。)

assert(checkPlayerExists(msg.sender) == false);

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