Solidity

眾籌後如何將 ETH 從合約轉移到外部地址?

  • October 4, 2017

我正在嘗試學習創建智能合約。作為實踐,我按照 ethereum.org 上的範例創建了代幣和眾籌合約並進行了部署。代幣分配按預期進行,但當合約期限到期(資金目標也達到)時,合約賬戶中的資金不會轉移到受益人賬戶。

這是程式碼:

pragma solidity ^0.4.11;
contract token { function transfer(address, uint){  } }

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;
   event GoalReached(address beneficiary, uint amountRaised);
   event FundTransfer(address backer, uint amount, bool isContribution);
   bool crowdsaleClosed = false;

   /* data structure to hold information about campaign contributors */

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

   /* The function without name is the default function that is called whenever anyone sends funds to a contract */
   function () payable {
       if (crowdsaleClosed) revert();
       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) _; }

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


   function safeWithdrawal() 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;
           }
       }
   }
}

我錯過了什麼嗎?

您可能提供的資訊太少,無法真正提供幫助。

您可以發布契約的地址和用於創建它的參數嗎?

address ifSuccessfulSendTo       =
uint fundingGoalInEthers         =
uint durationInMinutes           =
uint etherCostOfEachToken        =
token addressOfTokenUsedAsReward =

無論如何,您可以嘗試幾件事:

  1. 確保您safeWithdrawal()從用於創建契約的同一地址撥打電話。如果此事務失敗,則fundingGoalReached返回到false,這意味著您必須在再次呼叫之前呼叫checkGoalReached()將其設置回。true``safeWithdrawal()
  2. 當呼叫合約的方法時,嘗試發送大量的氣體,例如200,000,為了安全起見*(未使用的氣體總是會被退回給你)*。

餘額

$$ msg.sender $$=數量;

此外,這似乎有問題,因為它每次都設置存款人的餘額值並且不會增加它,例如。進行多次存款時。

募集金額 += 金額;

最後,通常不建議這樣做,因為它會引發溢出問題。最好使用zeppelin-solidity 的SafeMath.sol 之類的東西。

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