最新内容会更新在主站深入浅出区块链社区

原文链接:如何通过以太坊智能合约来进行众筹(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: 代币合约地址。

    如:



    本文使用的参数为:
"0xc6f9ea59d424733e8e1902c7837ea75e20abfb49",3, 100, 1,"0xad8972e2b583f580fc52f737b98327eb65d08f8c"
  1. 参与人投资的时候实际购买众筹合约代币,所有需要先向合约预存代币,代币的数量为:募资额度 / 代币的价格 , 这里为:3 * 1000/1 = 3000 (当能也可以大于3000)。

    向合约预存代币可以使用myetherwallet钱包,或在remix中重新加载代币合约,执行代币合约tranfer()函数进行代币转账。如使用myetherwallet转账如图:

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

  3. safeWithdrawl() 可以被参与人或收益人执行,如果融资不达标参与人可收回之前投资款,如果融资达标收益人可以拿到所有的融资款。

扩展

上面是一个很正规的募资合约。接下来讲两个募资合约的扩展,如何实现无限募资合约及割韭菜合约。

这部分内容独家发布在我的小专栏区块链技术

如何创建代币发行代币,现在也录制了对应的视频教程:通过代币学以太坊智能合约开发,目前我们也在招募体验师,可以点击链接了解。

如果你在学习中遇到问题,欢迎到我的知识星球提问,作为星球成员福利,成员可加入区块链技术付费交流群。

参考文档

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

如何通过以太坊智能合约来进行众筹(ICO)的更多相关文章

  1. 以太坊智能合约Hello World示例程序

    简介 以太坊(Ethereum)是一提供个智能合约(smart contract)功能的公共区块链(BlockChain)平台. 本文介绍了一个简单的以太坊智能合约的开发过程. 开发环境 在以太坊上开 ...

  2. 深入以太坊智能合约 ABI

    开发 DApp 时要调用在区块链上的以太坊智能合约,就需要智能合约的 ABI.本文希望更多了解 ABI,如为什么需要 ABI?如何解读 Ethereum 的智能合约 ABI?以及如何取得合约的 ABI ...

  3. Go语言打造以太坊智能合约测试框架(level3)

    传送门: 柏链项目学院 第三课 智能合约自动化测试 之前课程回顾 我们之前介绍了go语言调用exec处理命令行,介绍了toml配置文件的处理,以及awk处理文本文件获得ABI信息.我们的代码算是完成了 ...

  4. Go语言打造以太坊智能合约测试框架(level1)

    传送门: 柏链项目学院 Go语言打造以太坊智能合约测试框架 前言 这是什么? 这是一个基于go语言编写的,自动化测试以太坊智能合约的开发框架,使用此框架,可以自动化的部署合约,自动测试合约内的功能函数 ...

  5. 以太坊智能合约 Solidity 的常用数据类型介绍

    目录 目录 1.数组 1.1.对数组的增删改查操作. 2.String.Bytes.Mapping的使用 3.Enums 和 Structs 的简单应用 4.Ether 单位和 Time 单位 5.A ...

  6. rpc接口调用以太坊智能合约

    rpc接口调用以太坊智能合约 传送门: 柏链项目学院   在以太坊摸爬滚打有些日子了,也遇到了各种各样的问题.这几天主要研究了一下如何通过rpc接口编译.部署和调用合约.也遇到了一些困难和问题,下面将 ...

  7. 使用web3.js监听以太坊智能合约event

    传送门: 柏链项目学院 使用web3.js监听以太坊智能合约event   当我们在前端页面调用合约时发现有些数据不会立即返回,这时还需要再调用更新数据的函数.那么这样的方法使用起来非常不便,监听ev ...

  8. 以太坊智能合约开发,Web3.js API 中文文档 ethereum web3.js入门说明

    以太坊智能合约开发,Web3.js API 中文文档 ethereum web3.js入门说明 为了让你的Ðapp运行上以太坊,一种选择是使用web3.js library提供的web3.对象.底层实 ...

  9. 以太坊智能合约介绍,Solidity介绍

    以太坊智能合约介绍,Solidity介绍 一个简单的智能合约 先从一个非常基础的例子开始,不用担心你现在还一点都不了解,我们将逐步了解到更多的细节. Storage contract SimpleSt ...

随机推荐

  1. Select、Poll、Epoll、 异步IO 介绍

    一.概念相关介绍 同步IO和异步IO,阻塞IO和非阻塞IO分别是什么,到底有什么区别?不同的人在不同的上下文下给出的答案是不同的.所以先限定一下本文的上下文. 本文讨论的背景是Linux环境下的net ...

  2. PHP获取中英文字符串的首字母

    使用场景:在对地区进行筛选时,我们经常会看到按照英文字母进行筛选定位,起初想着是数据表里存储上地区与首字母关联关系,但是觉得太麻烦,然后就想着根据地区名称来获取首字母,然后对地区进行分组,由此便用到了 ...

  3. Activity内切换fragment实现底部菜单切换遇到的坑

    1.一般说来,app底部导航都会设计为5个菜单,可以使用textView,也可使用radioButton,这里我选择用radioButton,给radioButton直接设置selector就可以实现 ...

  4. sql 时间转换问题 from_unixtime() UNIX_TIMESTAMP()

    http://blog.csdn.net/test_soy/article/details/50328367 from_unixtime()是MySQL里的时间函数 date为需要处理的参数(该参数是 ...

  5. python操作mysql,增,删,改,查

    import MySQLdb conn = MySQLdb.connect(host='192.168.1.21',user='yangqw',passwd='1',db='free')cur = c ...

  6. oracle 配置 自启动 和 关闭

    今天在看oracle自启动脚本,突然有点时间,总结一下!!! 第一次写博客,大家随便看看就好,有错误麻烦提醒下,不喜欢别喷,主要是锻炼自己,形成写博客的好习惯. 刚毕业,现在还没转正,在干运维和自学d ...

  7. 如何去掉ul标签的多余空白或多余大距离?

    在css中写入 ul{ margin:; padding:; list-style: none; } 让其内边距和外边距为0,列表样式为空

  8. JS与ajax遍历list

    示例: <script> <c:forEach var="yanan" items="${yananList}">            ...

  9. TCP/IP详解 卷1 第二十章 TCP的成块数据流

    先补充一个知识: 1.停止等待协议:是tcp保证传输可靠的重要途径,"停止等待"就是指发送完一个分组就停止发送,等待对方确认之后,才能继续发送下一个分组 停止等待协议的优点是简单, ...

  10. 【Java框架型项目从入门到装逼】第十四节 查询用户列表展现到页面

    这一节,我们来实现一下用户列表搜索,最终的效果如下: 这边我们要使用easyUI给我们提供的datagrid组件. HTML结构如下 <!-- 数据列表 --> <table id= ...