Mist

Ethereum Crowdsale 教程 - 無法在 Solo TestNet 中將 Ether 轉移到 Crowdsale - 合約不允許處理此交易

  • January 23, 2018

我相信這是一個非常簡單的問題,本網站上的一位天才天才應該能夠回答!我正在關注乙太坊網站https://www.ethereum.org上的 Crowdsale

教程要完成本教程,我首先使用此處的程式碼創建了一個自定義令牌: https ://www.ethereum.org/token

pragma solidity ^0.4.16;

               interface tokenRecipient { function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData) public; }

               contract DudeCoin {
                   // Public variables of the token
                   string public name;
                   string public symbol;
                   uint8 public decimals = 2;
                   // 18 decimals is the strongly suggested default, avoid changing it
                   uint256 public totalSupply;

                   // This creates an array with all balances
                   mapping (address => uint256) public balanceOf;
                   mapping (address => mapping (address => uint256)) public allowance;

                   // This generates a public event on the blockchain that will notify clients
                   event Transfer(address indexed from, address indexed to, uint256 value);

                   // This notifies clients about the amount burnt
                   event Burn(address indexed from, uint256 value);

                   /**
                    * Constrctor function
                    *
                    * Initializes contract with initial supply tokens to the creator of the contract
                    */
                   function DudeCoin(
                       uint256 initialSupply,
                       string tokenName,
                       string tokenSymbol
                   ) public {
                       totalSupply = initialSupply * 10 ** uint256(decimals);  // Update total supply with the decimal amount
                       balanceOf[msg.sender] = totalSupply;                // Give the creator all initial tokens
                       name = tokenName;                                   // Set the name for display purposes
                       symbol = tokenSymbol;                               // Set the symbol for display purposes
                   }

                   /**
                    * Internal transfer, only can be called by this contract
                    */
                   function _transfer(address _from, address _to, uint _value) internal {
                       // Prevent transfer to 0x0 address. Use burn() instead
                       require(_to != 0x0);
                       // Check if the sender has enough
                       require(balanceOf[_from] >= _value);
                       // Check for overflows
                       require(balanceOf[_to] + _value > balanceOf[_to]);
                       // Save this for an assertion in the future
                       uint previousBalances = balanceOf[_from] + balanceOf[_to];
                       // Subtract from the sender
                       balanceOf[_from] -= _value;
                       // Add the same to the recipient
                       balanceOf[_to] += _value;
                       Transfer(_from, _to, _value);
                       // Asserts are used to use static analysis to find bugs in your code. They should never fail
                       assert(balanceOf[_from] + balanceOf[_to] == previousBalances);
                   }

                   /**
                    * Transfer tokens
                    *
                    * Send `_value` tokens to `_to` from your account
                    *
                    * @param _to The address of the recipient
                    * @param _value the amount to send
                    */
                   function transfer(address _to, uint256 _value) public {
                       _transfer(msg.sender, _to, _value);
                   }

                   /**
                    * Transfer tokens from other address
                    *
                    * Send `_value` tokens to `_to` in behalf of `_from`
                    *
                    * @param _from The address of the sender
                    * @param _to The address of the recipient
                    * @param _value the amount to send
                    */
                   function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
                       require(_value <= allowance[_from][msg.sender]);     // Check allowance
                       allowance[_from][msg.sender] -= _value;
                       _transfer(_from, _to, _value);
                       return true;
                   }

                   /**
                    * Set allowance for other address
                    *
                    * Allows `_spender` to spend no more than `_value` tokens in your behalf
                    *
                    * @param _spender The address authorized to spend
                    * @param _value the max amount they can spend
                    */
                   function approve(address _spender, uint256 _value) public
                       returns (bool success) {
                       allowance[msg.sender][_spender] = _value;
                       return true;
                   }

                   /**
                    * Set allowance for other address and notify
                    *
                    * Allows `_spender` to spend no more than `_value` tokens in your behalf, and then ping the contract about it
                    *
                    * @param _spender The address authorized to spend
                    * @param _value the max amount they can spend
                    * @param _extraData some extra information to send to the approved contract
                    */
                   function approveAndCall(address _spender, uint256 _value, bytes _extraData)
                       public
                       returns (bool success) {
                       tokenRecipient spender = tokenRecipient(_spender);
                       if (approve(_spender, _value)) {
                           spender.receiveApproval(msg.sender, _value, this, _extraData);
                           return true;
                       }
                   }

                   /**
                    * Destroy tokens
                    *
                    * Remove `_value` tokens from the system irreversibly
                    *
                    * @param _value the amount of money to burn
                    */
                   function burn(uint256 _value) public returns (bool success) {
                       require(balanceOf[msg.sender] >= _value);   // Check if the sender has enough
                       balanceOf[msg.sender] -= _value;            // Subtract from the sender
                       totalSupply -= _value;                      // Updates totalSupply
                       Burn(msg.sender, _value);
                       return true;
                   }

                   /**
                    * Destroy tokens from other account
                    *
                    * Remove `_value` tokens from the system irreversibly on behalf of `_from`.
                    *
                    * @param _from the address of the sender
                    * @param _value the amount of money to burn
                    */
                   function burnFrom(address _from, uint256 _value) public returns (bool success) {
                       require(balanceOf[_from] >= _value);                // Check if the targeted balance is enough
                       require(_value <= allowance[_from][msg.sender]);    // Check allowance
                       balanceOf[_from] -= _value;                         // Subtract from the targeted balance
                       allowance[_from][msg.sender] -= _value;             // Subtract from the sender's allowance
                       totalSupply -= _value;                              // Update totalSupply
                       Burn(_from, _value);
                       return true;
                   }
               }

然後我使用此處教程中的程式碼創建了一個“關聯”: https ://www.ethereum.org/dao

pragma solidity ^0.4.16;

contract owned {
   address public owner;

   function owned() public{
       owner = msg.sender;
   }

   modifier onlyOwner {
       require(msg.sender == owner);
       _;
   }

   function transferOwnership(address newOwner) public {
       owner = newOwner;
   }
}

contract tokenRecipient {
   event receivedEther(address sender, uint amount);
   event receivedTokens(address _from, uint256 _value, address _token, bytes _extraData);

   function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData)public{
       Token t = Token(_token);
       require(t.transferFrom(_from, this, _value));
       receivedTokens(_from, _value, _token, _extraData);
   }

   function () public payable {
       receivedEther(msg.sender, msg.value);
   }
}

contract Token {
   mapping (address => uint256) public balanceOf;
   function transferFrom(address _from, address _to, uint256 _value) public returns (bool success);
}

/**
* The shareholder association contract itself
*/
contract Association is owned, tokenRecipient {

   uint public minimumQuorum;
   uint public debatingPeriodInMinutes;
   Proposal[] public proposals;
   uint public numProposals;
   Token public sharesTokenAddress;

   event ProposalAdded(uint proposalID, address recipient, uint amount, string description);
   event Voted(uint proposalID, bool position, address voter);
   event ProposalTallied(uint proposalID, uint result, uint quorum, bool active);
   event ChangeOfRules(uint newMinimumQuorum, uint newDebatingPeriodInMinutes, address newSharesTokenAddress);

   struct Proposal {
       address recipient;
       uint amount;
       string description;
       uint votingDeadline;
       bool executed;
       bool proposalPassed;
       uint numberOfVotes;
       bytes32 proposalHash;
       Vote[] votes;
       mapping (address => bool) voted;
   }

   struct Vote {
       bool inSupport;
       address voter;
   }

   // Modifier that allows only shareholders to vote and create new proposals
   modifier onlyShareholders {
       require(sharesTokenAddress.balanceOf(msg.sender) > 0);
       _;
   }

   /**
    * Constructor function
    *
    * First time setup
    */
   function Association(Token sharesAddress, uint minimumSharesToPassAVote, uint minutesForDebate) public payable {
       changeVotingRules(sharesAddress, minimumSharesToPassAVote, minutesForDebate);
   }

   /**
    * Change voting rules
    *
    * Make so that proposals need to be discussed for at least `minutesForDebate/60` hours
    * and all voters combined must own more than `minimumSharesToPassAVote` shares of token `sharesAddress` to be executed
    *
    * @param sharesAddress token address
    * @param minimumSharesToPassAVote proposal can vote only if the sum of shares held by all voters exceed this number
    * @param minutesForDebate the minimum amount of delay between when a proposal is made and when it can be executed
    */
   function changeVotingRules(Token sharesAddress, uint minimumSharesToPassAVote, uint minutesForDebate) public onlyOwner {
       sharesTokenAddress = Token(sharesAddress);
       if (minimumSharesToPassAVote == 0 ) minimumSharesToPassAVote = 1;
       minimumQuorum = minimumSharesToPassAVote;
       debatingPeriodInMinutes = minutesForDebate;
       ChangeOfRules(minimumQuorum, debatingPeriodInMinutes, sharesTokenAddress);
   }

   /**
    * Add Proposal
    *
    * Propose to send `weiAmount / 1e18` ether to `beneficiary` for `jobDescription`. `transactionBytecode ? Contains : Does not contain` code.
    *
    * @param beneficiary who to send the ether to
    * @param weiAmount amount of ether to send, in wei
    * @param jobDescription Description of job
    * @param transactionBytecode bytecode of transaction
    */
   function newProposal(
       address beneficiary,
       uint weiAmount,
       string jobDescription,
       bytes transactionBytecode
   )   public
       onlyShareholders
       returns (uint proposalID)
   {
       proposalID = proposals.length++;
       Proposal storage p = proposals[proposalID];
       p.recipient = beneficiary;
       p.amount = weiAmount;
       p.description = jobDescription;
       p.proposalHash = keccak256(beneficiary, weiAmount, transactionBytecode);
       p.votingDeadline = now + debatingPeriodInMinutes * 1 minutes;
       p.executed = false;
       p.proposalPassed = false;
       p.numberOfVotes = 0;
       ProposalAdded(proposalID, beneficiary, weiAmount, jobDescription);
       numProposals = proposalID+1;

       return proposalID;
   }

   /**
    * Add proposal in Ether
    *
    * Propose to send `etherAmount` ether to `beneficiary` for `jobDescription`. `transactionBytecode ? Contains : Does not contain` code.
    * This is a convenience function to use if the amount to be given is in round number of ether units.
    *
    * @param beneficiary who to send the ether to
    * @param etherAmount amount of ether to send
    * @param jobDescription Description of job
    * @param transactionBytecode bytecode of transaction
    */
   function newProposalInEther(
       address beneficiary,
       uint etherAmount,
       string jobDescription,
       bytes transactionBytecode
   )   public                  
       onlyShareholders
       returns (uint proposalID)
   {
       return newProposal(beneficiary, etherAmount * 1 ether, jobDescription, transactionBytecode);
   }

   /**
    * Check if a proposal code matches
    *
    * @param proposalNumber ID number of the proposal to query
    * @param beneficiary who to send the ether to
    * @param weiAmount amount of ether to send
    * @param transactionBytecode bytecode of transaction
    */
   function checkProposalCode(
       uint proposalNumber,
       address beneficiary,
       uint weiAmount,
       bytes transactionBytecode
   )   public
       constant
       returns (bool codeChecksOut)
   {
       Proposal storage p = proposals[proposalNumber];
       return p.proposalHash == keccak256(beneficiary, weiAmount, transactionBytecode);
   }

   /**
    * Log a vote for a proposal
    *
    * Vote `supportsProposal? in support of : against` proposal #`proposalNumber`
    *
    * @param proposalNumber number of proposal
    * @param supportsProposal either in favor or against it
    */
   function vote(
       uint proposalNumber,
       bool supportsProposal
   )   public
       onlyShareholders
       returns (uint voteID)
   {
       Proposal storage p = proposals[proposalNumber];
       require(p.voted[msg.sender] != true);

       voteID = p.votes.length++;
       p.votes[voteID] = Vote({inSupport: supportsProposal, voter: msg.sender});
       p.voted[msg.sender] = true;
       p.numberOfVotes = voteID +1;
       Voted(proposalNumber,  supportsProposal, msg.sender);
       return voteID;
   }

   /**
    * Finish vote
    *
    * Count the votes proposal #`proposalNumber` and execute it if approved
    *
    * @param proposalNumber proposal number
    * @param transactionBytecode optional: if the transaction contained a bytecode, you need to send it
    */
   function executeProposal(uint proposalNumber, bytes transactionBytecode) public {
       Proposal storage p = proposals[proposalNumber];

       require(now > p.votingDeadline                                             // If it is past the voting deadline
           && !p.executed                                                          // and it has not already been executed
           && p.proposalHash == keccak256(p.recipient, p.amount, transactionBytecode)); // and the supplied code matches the proposal...


       // ...then tally the results
       uint quorum = 0;
       uint yea = 0;
       uint nay = 0;

       for (uint i = 0; i <  p.votes.length; ++i) {
           Vote storage v = p.votes[i];
           uint voteWeight = sharesTokenAddress.balanceOf(v.voter);
           quorum += voteWeight;
           if (v.inSupport) {
               yea += voteWeight;
           } else {
               nay += voteWeight;
           }
       }

       require(quorum >= minimumQuorum); // Check if a minimum quorum has been reached

       if (yea > nay ) {
           // Proposal passed; execute the transaction

           p.executed = true;
           require(p.recipient.call.value(p.amount)(transactionBytecode));

           p.proposalPassed = true;
       } else {
           // Proposal failed
           p.proposalPassed = false;
       }

       // Fire Events
       ProposalTallied(proposalNumber, yea - nay, quorum, p.proposalPassed);
   }
}

然後,我使用此處教程中的程式碼創建了“crowdsale”: https ://www.ethereum.org/crowdsale

pragma solidity ^0.4.16;

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

contract Crowdsale7 {
   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 Crowdsale7(
       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 () public payable {
       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() public afterDeadline {
       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() public afterDeadline {
       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;
           }
       }
   }
}

但是,當我執行眾籌時,我無法成功將資金轉入眾籌賬戶,並且出現以下錯誤

乙太坊霧錯誤

這變得有些令人沮喪,因為我已按照教程中的說明進行操作,但無法使這個(相對)簡單的範例正常工作。我需要做的就是為購買“DudeCoins”創建一個基本的眾籌。如果這個網站上一位傑出的天才能指出我正確的方向,那將不勝感激!謝謝

事實證明,交易無法處理,因為我忘記使用名為“DudeCoins”的自定義代幣為眾籌提供資金。在用“DudeCoins”資助我的眾籌後,眾籌能夠正常接受乙太幣作為代幣。

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