如何通過以太坊智慧合約來進行眾籌(ICO)

Tiny熊發表於2018-03-01

最新內容會更新在主站深入淺出區塊鏈社群
原文連結:如何通過以太坊智慧合約來進行眾籌(ICO)

前面我們有兩遍文章寫了如何發行代幣,今天我們講一下如何使用代幣來公開募資,即編寫一個募資合約。

寫在前面

本文所講的代幣是使用以太坊智慧合約建立,閱讀本文前,你應該對以太坊、智慧合約有所瞭解,如果你還不瞭解,建議你先看以太坊是什麼

眾籌

先簡單說下眾籌的概念:一般是這樣的,我一個非常好的想法,但是我沒有錢來做這事,於是我把這個想法發給大家看,說:我做這件事需要5百萬,大家有沒有興趣投些錢,如果大家在30天內投夠了5百萬我就開始做,到時大家都是原始股東,如果募資額不到5百萬,大家投的錢就還給大家。

現在ICO眾籌已經被各路大佬拿來割韭菜而被玩壞了(不管有無達標,都把錢捲走)。

其實區塊鏈技術本事非常適合解決眾籌的信任問題,藉助於智慧合約,可以實現當募資額完成時,募資款自動打到指定賬戶,當募資額未完成時,可退款。這個過程不需要看眾籌大佬的人品,不用依靠第三方平臺信用擔保。

代幣

傳統的眾籌在參與之後通常不容易交易(參與之後無法轉給其他人),而通過用代幣來參與眾籌,則很容易進行交易,眾籌的參與人可隨時進行買賣,待眾籌專案實施完成的時候,完全根據代幣持有量進行回饋。

舉個例子說明下,大家會更容易理解,有這一個眾籌:A有技術做一個能監測健康的指環,為此向公眾募資200百萬,募資時100塊對應一個代幣,約定在指環上市之後,代幣的持有人可以用一個代幣來兌換一個指環。而指環的研發週期是一年,因此在指環還未上市的一年裡,眾籌的參與人可以隨時交易所持有的代幣。

眾籌智慧合約程式碼

接下來就看看如何實現一個眾籌智慧合約。


pragma solidity ^0.4.16;

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

contract Crowdsale {
    address public beneficiary;  // 募資成功後的收款方
    uint public fundingGoal;   // 募資額度
    uint public amountRaised;   // 參與數量
    uint public deadline;      // 募資截止期

    uint public price;    //  token 與以太坊的匯率 , token賣多少錢
    token public tokenReward;   // 要賣的token

    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);

    /**
     * 建構函式, 設定相關屬性
     */
    function Crowdsale(
        address ifSuccessfulSendTo,
        uint fundingGoalInEthers,
        uint durationInMinutes,
        uint finneyCostOfEachToken,
        address addressOfTokenUsedAsReward) {
            beneficiary = ifSuccessfulSendTo;
            fundingGoal = fundingGoalInEthers * 1 ether;
            deadline = now + durationInMinutes * 1 minutes;
            price = finneyCostOfEachToken * 1 finney;
            tokenReward = token(addressOfTokenUsedAsReward);   // 傳入已釋出的 token 合約的地址來建立例項
    }

    /**
     * 無函式名的Fallback函式,
     * 在向合約轉賬時,這個函式會被呼叫
     */
    function () 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(作用和Python的裝飾器很相似)
    * 用於在函式執行前檢查某種前置條件(判斷通過之後才會繼續執行該方法)
    * _ 表示繼續執行之後的程式碼
    **/
    modifier afterDeadline() { if (now >= deadline) _; }

    /**
     * 判斷眾籌是否完成融資目標, 這個方法使用了afterDeadline函式修改器
     *
     */
    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;
            }
        }
    }
}

部署及說明

在部署這個合約之前,我們需要先部署一個代幣合約,請參考一步步教你建立自己的數字貨幣

  1. 建立眾籌合約我們需要提供一下幾個引數:
    ifSuccessfulSendTo: 募資成功後的收款方(其實這裡可以預設為合約建立者)
    fundingGoalInEthers: 募資額度, 為了方便我們僅募3個ether
    durationInMinutes: 募資時間
    finneyCostOfEachToken 每個代幣的價格, 這裡為了方便使用了單位finney及值為:1 (1 ether = 1000 finney)
    addressOfTokenUsedAsReward: 代幣合約地址。
    如:
    如何通過以太坊智慧合約來進行眾籌(ICO)
    本文使用的引數為:
"0xc6f9ea59d424733e8e1902c7837ea75e20abfb49",3, 100, 1,"0xad8972e2b583f580fc52f737b98327eb65d08f8c"
  1. 參與人投資的時候實際購買眾籌合約代幣,所有需要先向合約預存代幣,代幣的數量為:募資額度 / 代幣的價格 , 這裡為:3 * 1000/1 = 3000 (當能也可以大於3000)。
    向合約預存代幣可以使用myetherwallet錢包,或在remix中重新載入代幣合約,執行代幣合約tranfer()函式進行代幣轉賬。如使用myetherwallet轉賬如圖:
    如何通過以太坊智慧合約來進行眾籌(ICO)

  2. 參與人投資行為即是向買眾籌合約轉賬,轉賬時,會執行Fallback回退函式(即無名函式)向其賬戶打回相應的代幣。

  3. safeWithdrawl() 可以被參與人或收益人執行,如果融資不達標參與人可收回之前投資款,如果融資達標收益人可以拿到所有的融資款。

擴充套件

上面是一個很正規的募資合約。接下來講兩個募資合約的擴充套件,如何實現無限募資合約及割韭菜合約。
這部分內容獨家釋出在我的小專欄區塊鏈技術

如何建立代幣發行代幣,現在也錄製了對應的視訊教程:通過代幣學以太坊智慧合約開發,目前我們也在招募體驗師,可以點選連結瞭解。

如果你在學習中遇到問題,歡迎到我的知識星球提問,作為星球成員福利,成員可加入區塊鏈技術付費交流群。

參考文件

深入淺出區塊鏈 - 系統學習區塊鏈,打造最好的區塊鏈技術部落格。

相關文章