如何通过以太坊智能合约来进行众筹(ICO)

前面我们有两遍文章写了如何发行代币,今天我们讲一下如何使用代币来公开募资,即编写一个募资合约。

写在前面

本文所讲的代币是使用以太坊智能合约创建,阅读本文前,你应该对以太坊、智能合约有所了解,如果你还不了解,建议你先看以太坊是什么

众筹

先简单说下众筹的概念:一般是这样的,我一个非常好的想法,但是我没有钱来做这事,于是我把这个想法发给大家看,说:我做这件事需要5百万,大家有没有兴趣投些钱,如果大家在30天内投够了5百万我就开始做,到时大家都是原始股东,如果募资额不到5百万,大家投的钱就还给大家。

现在ICO众筹已经被各路大佬拿来割韭菜而被玩坏了(不管有无达标,都把钱卷走)。

其实区块链技术本事非常适合解决众筹的信任问题,借助于智能合约,可以实现当募资额完成时,募资款自动打到指定账户,当募资额未完成时,可退款。这个过程不需要看众筹大佬的人品,不用依靠第三方平台信用担保。

代币

传统的众筹在参与之后通常不容易交易(参与之后无法转给其他人),而通过用代币来参与众筹,则很容易进行交易,众筹的参与人可随时进行买卖,待众筹项目实施完成的时候,完全根据代币持有量进行回馈。

举个例子说明下,大家会更容易理解,有这一个众筹:A有技术做一个能监测健康的指环,为此向公众募资200百万,募资时100块对应一个代币,约定在指环上市之后,代币的持有人可以用一个代币来兑换一个指环。而指环的研发周期是一年,因此在指环还未上市的一年里,众筹的参与人可以随时交易所持有的代币。

众筹智能合约代码

接下来就看看如何实现一个众筹智能合约。

```js

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;
}
top Created with Sketch.