何爲代幣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);
}