Solidity

顯示 Gas 限制錯誤的 CrowdSale 基本合約樣本

  • December 24, 2021

您好,我已經從官方網站https://ethereum.org/crowdsale複製了基本合約

我是 Solidity 和乙太坊開發的初學者

它已由 Remix 成功編譯,但是當我點擊“執行”選項卡下的“創建”時,它顯示錯誤

創建 Crowdsale 錯誤:所需的氣體超過限制:300000。重要的氣體估計也可能是契約程式碼中存在問題的跡象。請檢查循環並確保您沒有將值發送到非應付函式(這也是強氣體估計的原因)。

我不確定為什麼會顯示

這是我的程式碼

pragma solidity ^0.4.16;

interface token {
   function transfer(address receiver, uint amount) public;
}

contract Crowdsale {
   address public beneficiary;
   uint public fundingGoal;
   uint public amountRaised;
   uint public deadline;
   uint public price;
   token public tokenReward;
   mapping(address => uint256) public balanceOf;
   bool fundingGoalReached = false;
   bool crowdsaleClosed = false;

   event GoalReached(address recipient, uint totalAmountRaised);
   event FundTransfer(address backer, uint amount, bool isContribution);

   /**
    * Constrctor function
    *
    * Setup the owner
    */
   function Crowdsale(
       address ifSuccessfulSendTo,
       uint fundingGoalInEthers,
       uint durationInMinutes,
       uint etherCostOfEachToken,
       address addressOfTokenUsedAsReward
   ) public {
       beneficiary = ifSuccessfulSendTo;
       fundingGoal = fundingGoalInEthers * 1 ether;
       deadline = now + durationInMinutes * 1 minutes;
       price = etherCostOfEachToken * 1 ether;
       tokenReward = token(addressOfTokenUsedAsReward);
   }

   /**
    * Fallback function
    *
    * The function without name is the default function that is called whenever anyone sends funds to a contract
    */
   function () payable public{
       require(!crowdsaleClosed);
       uint amount = msg.value;
       balanceOf[msg.sender] += amount;
       amountRaised += amount;
       tokenReward.transfer(msg.sender, amount / price);
       FundTransfer(msg.sender, amount, true);
   }

   modifier afterDeadline() { if (now >= deadline) _; }

   /**
    * Check if goal was reached
    *
    * Checks if the goal or time limit has been reached and ends the campaign
    */
   function checkGoalReached() afterDeadline public {
       if (amountRaised >= fundingGoal){
           fundingGoalReached = true;
           GoalReached(beneficiary, amountRaised);
       }
       crowdsaleClosed = true;
   }


   /**
    * Withdraw the funds
    *
    * Checks to see if goal or time limit has been reached, and if so, and the funding goal was reached,
    * sends the entire amount to the beneficiary. If goal was not reached, each contributor can withdraw
    * the amount they contributed.
    */
   function safeWithdrawal() afterDeadline public {
       if (!fundingGoalReached) {
           uint amount = balanceOf[msg.sender];
           balanceOf[msg.sender] = 0;
           if (amount > 0) {
               if (msg.sender.send(amount)) {
                   FundTransfer(msg.sender, amount, false);
               } else {
                   balanceOf[msg.sender] = amount;
               }
           }
       }

       if (fundingGoalReached && beneficiary == msg.sender) {
           if (beneficiary.send(amountRaised)) {
               FundTransfer(beneficiary, amountRaised, false);
           } else {
               //If we fail to send the funds to beneficiary, unlock funders balance
               fundingGoalReached = false;
           }
       }
   }
}

在此處輸入圖像描述

所以請幫我找出確切的問題以及如何解決它。

事實證明,您正在嘗試部署價值為1 ether的合約。為此,您應該添加payable到您的建構子Crowdsale()

/**
* Constrctor function
*
* Setup the owner
*/
function Crowdsale(
   address ifSuccessfulSendTo,
   uint fundingGoalInEthers,
   uint durationInMinutes,
   uint etherCostOfEachToken,
   address addressOfTokenUsedAsReward
) public payable {
   beneficiary = ifSuccessfulSendTo;
   fundingGoal = fundingGoalInEthers * 1 ether;
   deadline = now + durationInMinutes * 1 minutes;
   price = etherCostOfEachToken * 1 ether;
   tokenReward = token(addressOfTokenUsedAsReward);
}

價值 1 乙太沒有證明然後這段程式碼執行:

pragma solidity ^0.4.16;

interface token {
   function transfer(address receiver, uint amount) public;
}

contract Crowdsale {
   address public beneficiary;
   uint public fundingGoal;
   uint public amountRaised;
   uint public deadline;
   uint public price;
   token public tokenReward;
   mapping(address => uint256) public balanceOf;
   bool fundingGoalReached = false;
   bool crowdsaleClosed = false;

   event GoalReached(address recipient, uint totalAmountRaised);
   event FundTransfer(address backer, uint amount, bool isContribution);

   /**
    * Constrctor function
    *
    * Setup the owner
    */
   function Crowdsale(
       address ifSuccessfulSendTo,
       uint fundingGoalInEthers,
       uint durationInMinutes,
       uint etherCostOfEachToken,
       address addressOfTokenUsedAsReward
   ) public {
       beneficiary = ifSuccessfulSendTo;
       fundingGoal = fundingGoalInEthers * 1 ether;
       deadline = now + durationInMinutes * 1 minutes;
       price = etherCostOfEachToken * 1 ether;
       tokenReward = token(addressOfTokenUsedAsReward);
   }

   /**
    * Fallback function
    *
    * The function without name is the default function that is called whenever anyone sends funds to a contract
    */
   function () payable public{
       require(!crowdsaleClosed);
       uint amount = msg.value;
       balanceOf[msg.sender] += amount;
       amountRaised += amount;
       tokenReward.transfer(msg.sender, amount / price);
       FundTransfer(msg.sender, amount, true);
   }

   modifier afterDeadline() { if (now >= deadline) _; }

   /**
    * Check if goal was reached
    *
    * Checks if the goal or time limit has been reached and ends the campaign
    */
   function checkGoalReached() afterDeadline public {
       if (amountRaised >= fundingGoal){
           fundingGoalReached = true;
           GoalReached(beneficiary, amountRaised);
       }
       crowdsaleClosed = true;
   }


   /**
    * Withdraw the funds
    *
    * Checks to see if goal or time limit has been reached, and if so, and the funding goal was reached,
    * sends the entire amount to the beneficiary. If goal was not reached, each contributor can withdraw
    * the amount they contributed.
    */
   function safeWithdrawal() afterDeadline public {
       if (!fundingGoalReached) {
           uint amount = balanceOf[msg.sender];
           balanceOf[msg.sender] = 0;
           if (amount > 0) {
               if (msg.sender.send(amount)) {
                   FundTransfer(msg.sender, amount, false);
               } else {
                   balanceOf[msg.sender] = amount;
               }
           }
       }

       if (fundingGoalReached && beneficiary == msg.sender) {
           if (beneficiary.send(amountRaised)) {
               FundTransfer(beneficiary, amountRaised, false);
           } else {
               //If we fail to send the funds to beneficiary, unlock funders balance
               fundingGoalReached = false;
           }
       }
   }
}

除非礦工增加區塊氣體限制,否則您唯一的選擇是將合約拆分為多個合約

所以每個合約都有自己的地址,你可以在它們之間進行呼叫。例如,ICO 眾籌可以分為:

1 Crowdsale:管理眾籌,代幣如何分配,獎勵,開啟,關閉 2 Token:實現 ERC20,可以創建代幣,批准轉賬 3 Wallet:管理眾籌期間收到的資金

由於每個契約的範圍有限,因此拆分也有助於安全審計。

謝謝試試

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