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

本文首发于深刻浅出区块链社区 原文连接:如何经过以太坊智能合约来进行众筹(ICO)原文已更新,请读者前往原文阅读app

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

写在前面

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

众筹

先简单说下众筹的概念:通常是这样的,我一个很是好的想法,可是我没有钱来作这事,因而我把这个想法发给你们看,说:我作这件事须要5百万,你们有没有兴趣投些钱,若是你们在30天内投够了5百万我就开始作,到时你们都是原始股东,若是募资额不到5百万,你们投的钱就还给你们。区块链

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

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

代币

传统的众筹在参与以后一般不容易交易(参与以后没法转给其余人),而经过用代币来参与众筹,则很容易进行交易,众筹的参与人可随时进行买卖,待众筹项目实施完成的时候,彻底根据代币持有量进行回馈。blog

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

众筹智能合约代码

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

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

部署及说明

在部署这个合约以前,咱们须要先部署一个代币合约,请参考一步步教你建立本身的数字货币ip

  1. 建立众筹合约咱们须要提供一下几个参数: ifSuccessfulSendTo: 募资成功后的收款方(其实这里能够默认为合约建立者) fundingGoalInEthers: 募资额度, 为了方便咱们仅募3个ether durationInMinutes: 募资时间 finneyCostOfEachToken 每一个代币的价格, 这里为了方便使用了单位finney及值为:1 (1 ether = 1000 finney) addressOfTokenUsedAsReward: 代币合约地址。 如: 本文使用的参数为:
"0xc6f9ea59d424733e8e1902c7837ea75e20abfb49",3, 100, 1,"0xad8972e2b583f580fc52f737b98327eb65d08f8c"
  1. 参与人投资的时候实际购买众筹合约代币,因此须要先向合约预存代币,代币的数量为:募资额度 / 代币的价格 , 这里为:3 * 1000/1 = 3000 (当能也能够大于3000)。 向合约预存代币可使用myetherwallet钱包,或在remix中从新加载代币合约,执行代币合约tranfer()函数进行代币转帐,转帐的地址就是咱们建立合约的地址。如使用myetherwallet转帐如图:

  2. 投资人向众筹合约转帐(发送以太币)便是参与众筹行为,转帐时,会执行Fallback回退函数(即无名函数)向其帐户打回相应的代币。

  3. safeWithdrawl() 能够被参与人或收益人调用,若是融资不达标参与人可收回以前投资款,若是融资达标收益人能够拿到全部的融资款。

扩展

上面是一个很正规的募资合约。接下来说两个募资合约的扩展,如何实现无限募资合约及割韭菜合约。 这部份内容独家发布在个人小专栏区块链技术

若是你在学习中遇到问题,欢迎到个人**知识星球**提问,做为星球成员福利,成员可加入区块链技术付费交流群。

参考文档

深刻浅出区块链 - 系统学习区块链,打造最好的区块链技术博客。

☛ 个人知识星球为各位解答区块链技术问题,欢迎加入讨论。

☛ 关注公众号“深刻浅出区块链技术”第一时间获取区块链技术信息。

相关文章
相关标签/搜索