何为代币ICO
ICO是英文Initial Coin Offering,意思是代币首次发行,其概念源自于股票市场的IPO :Initial Coin Offering,首次公开募资。在以太坊网络中,以太币Eth是最原始的代币,也是除了比特币之后公众最为认可、以太坊网络价值最高的代币。代币ICO实际上就是项目方以一定的实际项目为基础,向公众募集以太币资金,并把自己项目代币作为奖励。(本质上就是代币跟以太币的比例兑换)
通俗来讲,就如龙泉剑商家在平台上发起众筹,募集指定目标资金如40万,完成之后为每个参与者铸剑作为奖励的过程。
代币ICO的核心三要素:
众筹时间
众筹价格
众筹受益人
代币ICO的实现流程:
一:设定众筹时间、目标、价格、受益人
二:实现以太币与代币之间的交换
三:实现受益人提款(众筹成功)、投资者退款(众筹失败)
pragma solidity ^0.4.24;
contract SafeMath {//用来安全计算的合约,防止加乘溢出
function safeMul(uint256 a, uint256 b) internal returns (uint256) {
uint256 c = a * b;
assert(a == 0 || c / a == b);
return c;
}
function safeDiv(uint256 a, uint256 b) internal returns (uint256) {
assert(b > 0);
uint256 c = a / b;
assert(a == b * c + a % b);
return c;
}
function safeSub(uint256 a, uint256 b) internal returns (uint256) {
assert(b <= a);
return a - b;
}
function safeAdd(uint256 a, uint256 b) internal returns (uint256) {
uint256 c = a + b;
assert(c>=a && c>=b);
return c;
}
function assert(bool assertion) internal {
if (!assertion) {
throw;
}
}
}
interface token{//这里是提供调用ERC20代币的接口
function transfer(address _to, uint256 _value) external;
}
contract ICO{
uint public goal;//发行目标,也就是募集以太币的数量
uint public price;//发行价格
uint public duration;//截至时间
address public beneficial;//受益人(提款人)
token public tokenReword;//用来调用的ERC20合约
//构造函数
constructor( uint _goal,uint _price, uint _duration, address _token) public {
goal=_goal;
price=_price * 1 ether;//指定价格为一个单位以太币,10的18次方WEI
duration=now + _duration * 60 days;//截至时间为现在+60天。
tokenReword=token(_token);//把合约地址转为token对象
beneficial=msg.sender;//指定受益人为智能合约发布者
}
}
这里要说明一下 interface token,在众筹之前首先是把ERC20代币部署到以太坊主网中,然后我们在部署众筹合约。两个合约之间可以互相调用函数,这称之为消息调用。在众筹项目中,我们是要把自己项目代币作为奖励返回给投资者的,也就是说调用transfer函数把代币打入到投资者账户,而我们的账户则是用来接收以太币的。
第二步:实现以太币与代币之间的交换
mapping (address => uint) refund;//用来记录投资者投资了多少个以太币
function () public payable{//这里是一个fallback函数,当投资者调用这个函数,打入以太币时自动执行
require(now <duration);
uint amount =msg.value /price;//计算以太币与代币兑换比例,这里为简单计算,采用1:1兑换
safeAdd(refund[msg.sender],amount);
tokenReword.transfer(msg.sender,amount);
emit FundingTransfer(msg.sender,amount);
}
//记录向投资者转入多少个代币事件
event FundingTransfer(address _to,uint amount);
第三步实现提款、退款
uint realmount;//用来记录投资者打入的eth总和
function () public payable{
require(now <duration);
uint amount =msg.value /price;
refund[msg.sender]=safeAdd(refund[msg.sender],amount);
realamount=safeAdd(realamount,amount);//增加投资者打入的eth总和
tokenReword.transfer(msg.sender,amount);
emit FundingTransfer(msg.sender,amount);
}
function withdrawl() public {//提款、退款函数
require(now >=duration);判断当前时间要大于截止时间
if(realamount>=goal){//投资者打入的eth总和要大于目标数量
require(beneficial==msg.sender);
beneficial.transfer(realamount);//受益人提款
}else{
msg.sender.transfer(refund[msg.sender]);//投资者退款
refund[msg.sender]=0;
}
}
//判断是否实现众筹函数
function checkIsReachGoal() public{
require(now >=duration);
if(realamount>=goal){
emit ReachGoal(true);
}
}
//判断是否实现众筹事件
event ReachGoal(bool);
最后代码如下:
pragma solidity ^0.4.24;
interface token{
function transfer(address _to, uint256 _value) external;
}
contract SafeMath {
function safeMul(uint256 a, uint256 b) internal returns (uint256) {
uint256 c = a * b;
assert(a == 0 || c / a == b);
return c;
}
function safeDiv(uint256 a, uint256 b) internal returns (uint256) {
assert(b > 0);
uint256 c = a / b;
assert(a == b * c + a % b);
return c;
}
function safeSub(uint256 a, uint256 b) internal returns (uint256) {
assert(b <= a);
return a - b;
}
function safeAdd(uint256 a, uint256 b) internal returns (uint256) {
uint256 c = a + b;
assert(c>=a && c>=b);
return c;
}
function assert(bool assertion) internal {
if (!assertion) {
throw;
}
}
}
contract ICO is SafeMath{
uint public goal;
uint public realamount;
uint public price;
uint public duration;
address public beneficial;
token public tokenReword;
mapping (address => uint) refund;
constructor( uint _goal,uint _price, uint _duration, address _token) public {
goal=_goal;
price=_price * 1 ether;
duration= now + _duration * 60 days;
tokenReword=token(_token);
beneficial=msg.sender;
}
function () public payable{
require(now <duration);
uint amount =msg.value /price;
refund[msg.sender]=safeAdd(refund[msg.sender],amount);
realamount=safeAdd(realamount,amount);
tokenReword.transfer(msg.sender,amount);
emit FundingTransfer(msg.sender,amount);
}
event FundingTransfer(address _to,uint amount);
function withdrawl() public {
require(now >=duration);
if(realamount>=goal){
require(beneficial==msg.sender);
beneficial.transfer(realamount);
}else{
msg.sender.transfer(refund[msg.sender]);
refund[msg.sender]=0;
}
}
function checkIsReachGoal() public{
require(now >=duration);
if(realamount>=goal){
emit ReachGoal(true);
}
}
event ReachGoal(bool);
}