如何通过以太坊智能合约来进行众筹(ICO)
最新内容会更新在主站深入浅出区块链社区
原文链接:如何通过以太坊智能合约来进行众筹(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;
}
}
}
}
部署及说明
在部署这个合约之前,我们需要先部署一个代币合约,请参考一步步教你创建自己的数字货币。
- 创建众筹合约我们需要提供一下几个参数:
ifSuccessfulSendTo: 募资成功后的收款方(其实这里可以默认为合约创建者)
fundingGoalInEthers: 募资额度, 为了方便我们仅募3个ether
durationInMinutes: 募资时间
finneyCostOfEachToken 每个代币的价格, 这里为了方便使用了单位finney及值为:1 (1 ether = 1000 finney)
addressOfTokenUsedAsReward: 代币合约地址。
如:
本文使用的参数为:
"0xc6f9ea59d424733e8e1902c7837ea75e20abfb49",3, 100, 1,"0xad8972e2b583f580fc52f737b98327eb65d08f8c"
参与人投资的时候实际购买众筹合约代币,所有需要先向合约预存代币,代币的数量为:募资额度 / 代币的价格 , 这里为:3 * 1000/1 = 3000 (当能也可以大于3000)。
向合约预存代币可以使用myetherwallet钱包,或在remix中重新加载代币合约,执行代币合约tranfer()函数进行代币转账。如使用myetherwallet转账如图:
参与人投资行为即是向买众筹合约转账,转账时,会执行Fallback回退函数(即无名函数)向其账户打回相应的代币。
safeWithdrawl() 可以被参与人或收益人执行,如果融资不达标参与人可收回之前投资款,如果融资达标收益人可以拿到所有的融资款。
扩展
上面是一个很正规的募资合约。接下来讲两个募资合约的扩展,如何实现无限募资合约及割韭菜合约。
这部分内容独家发布在我的小专栏区块链技术
如何创建代币发行代币,现在也录制了对应的视频教程:通过代币学以太坊智能合约开发,目前我们也在招募体验师,可以点击链接了解。
如果你在学习中遇到问题,欢迎到我的知识星球提问,作为星球成员福利,成员可加入区块链技术付费交流群。
参考文档
深入浅出区块链 - 系统学习区块链,打造最好的区块链技术博客。
如何通过以太坊智能合约来进行众筹(ICO)的更多相关文章
- 以太坊智能合约Hello World示例程序
简介 以太坊(Ethereum)是一提供个智能合约(smart contract)功能的公共区块链(BlockChain)平台. 本文介绍了一个简单的以太坊智能合约的开发过程. 开发环境 在以太坊上开 ...
- 深入以太坊智能合约 ABI
开发 DApp 时要调用在区块链上的以太坊智能合约,就需要智能合约的 ABI.本文希望更多了解 ABI,如为什么需要 ABI?如何解读 Ethereum 的智能合约 ABI?以及如何取得合约的 ABI ...
- Go语言打造以太坊智能合约测试框架(level3)
传送门: 柏链项目学院 第三课 智能合约自动化测试 之前课程回顾 我们之前介绍了go语言调用exec处理命令行,介绍了toml配置文件的处理,以及awk处理文本文件获得ABI信息.我们的代码算是完成了 ...
- Go语言打造以太坊智能合约测试框架(level1)
传送门: 柏链项目学院 Go语言打造以太坊智能合约测试框架 前言 这是什么? 这是一个基于go语言编写的,自动化测试以太坊智能合约的开发框架,使用此框架,可以自动化的部署合约,自动测试合约内的功能函数 ...
- 以太坊智能合约 Solidity 的常用数据类型介绍
目录 目录 1.数组 1.1.对数组的增删改查操作. 2.String.Bytes.Mapping的使用 3.Enums 和 Structs 的简单应用 4.Ether 单位和 Time 单位 5.A ...
- rpc接口调用以太坊智能合约
rpc接口调用以太坊智能合约 传送门: 柏链项目学院 在以太坊摸爬滚打有些日子了,也遇到了各种各样的问题.这几天主要研究了一下如何通过rpc接口编译.部署和调用合约.也遇到了一些困难和问题,下面将 ...
- 使用web3.js监听以太坊智能合约event
传送门: 柏链项目学院 使用web3.js监听以太坊智能合约event 当我们在前端页面调用合约时发现有些数据不会立即返回,这时还需要再调用更新数据的函数.那么这样的方法使用起来非常不便,监听ev ...
- 以太坊智能合约开发,Web3.js API 中文文档 ethereum web3.js入门说明
以太坊智能合约开发,Web3.js API 中文文档 ethereum web3.js入门说明 为了让你的Ðapp运行上以太坊,一种选择是使用web3.js library提供的web3.对象.底层实 ...
- 以太坊智能合约介绍,Solidity介绍
以太坊智能合约介绍,Solidity介绍 一个简单的智能合约 先从一个非常基础的例子开始,不用担心你现在还一点都不了解,我们将逐步了解到更多的细节. Storage contract SimpleSt ...
随机推荐
- 策略模式--List排序
需求:根据姓名进行排序,升序或者降序,如果名字一样,就按照id升序排序,用策略模式 步骤一: 定义一个Person对象 public class Person { private Integer id ...
- [转]sysctl -P 报错解决办法
问题症状 修改 linux 内核文件 #vi /etc/sysctl.conf后执行sysctl -P 报错 error: "net.bridge.bridge-nf-call-ip6ta ...
- Python程序的执行方式
Python代码有两种执行方式: 一.文件执行 二.交互器执行(推荐) 一.文件执行 1.用 notepad++ 或 Sublime Text,甚至 写字本创建一个文件. 2.比如:print('He ...
- Asp.net core 2.0.1 Razor 的使用学习笔记(一)
环境:vs2017 版本:15.5.6 一.新建项目 1.文件>新建>项目>Visual c#>.NET Core>ASP.NET Core Web应用程序(“.NET ...
- String.Format 格式化货币的小问题
今天在开发过程中,遇到一件让我觉得比较纳闷的事情:用String.Format 格式化充值金额的时候,我这样处理: String.Format("{0:C2}", dr[" ...
- js—双等号引起的类型转换过程
一.首先看双等号前后有没有NaN,如果存在NaN一律返回false 二.再看双等号前后有没有布尔,有布尔就将布尔转换为数字.(false是0,true是1) 三.接着看双等号前后有没有字符串,有三种情 ...
- nginx加权轮询和ip_hash
nginx为后端web服务器(apache,nginx,tomcat,weblogic)等做反向代理 几台后端web服务器需要考虑文件共享,数据库共享,session共享问题.文件共享可以使用nfs, ...
- Redis和Memcached区别
本文参考 Redis与Memcached的区别. 如果简单地比较Redis与Memcached的区别,大多数都会得到以下观点: Redis不仅仅支持简单的k/v类型的数据,同时还提供list,set, ...
- python之在线平台与量化投资
0. 第一个量化策略 # 初始化函数,设定基准等等 def initialize(context): set_benchmark('000300.XSHG') g.security = get_ind ...
- JSP自定义标签就是如此简单
tags: JSP 为什么要用到简单标签? 上一篇博客中我已经讲解了传统标签,想要开发自定义标签,大多数情况下都要重写doStartTag(),doAfterBody()和doEndTag()方法,并 ...