您的位置:首页 > 其它

基于以太坊发布属于自己的数字货币(代币)完整版

2018-03-31 21:12 996 查看

基于以太坊发布属于自己的数字货币(代币)完整版

(参考资料来源于网络以及各种摸索,其中各种坑)

 

本文单纯从技术角度详细介绍如何基于以太坊ERC20创建代币的流程(此案例是部署的eth主网,非测试案例)
 
写在前面
 
本文所讲的代币是使用以太坊智能合约创建,阅读本文前,你应该对以太坊、智能合约有所了解,如果你还不了解,建议你先看以太坊是什么

代币Token

如果不那么追求精确的定义,代币就是数字货币,比特币、以太币就是一个代币。
利用以太坊的智能合约可以轻松编写出属于自己的代币,代币可以代表任何可以交易的东西,如:积分、财产、证书等等。

因此不管是出于商业,还是学习很多人想创建一个自己的代币,先贴一个图看看创建的代币是什么样子。
以我自己发布的BliBli币 Bcoin为例
访问地址 :  https://etherscan.io/token/0x73c8da697fe5e145f6269c4c852e59a7328f9371







 今天我们就来详细讲一讲怎样创建一个这样的代币。

ERC20 Token

ERC20和代币一同出现, ERC20是以太坊定义的一个代币标准。是一种发行代币合约必须要遵守的协议,该协议规定了几个参数——发行货币的名称,简称,发行量,要支持的函数等,只有支持了该协议才会被以太坊所认同。
erc20标准代码如下// https://github.com/ethereum/EIPs/issues/20 contract ERC20 {
function totalSupply() constant returns (uint totalSupply);
function balanceOf(address _owner) constant returns (uint balance);
function transfer(address _to, uint _value) returns (bool success);
function transferFrom(address _from, address _to, uint _value) returns (bool success);
function approve(address _spender, uint _value) returns (bool success);
function allowance(address _owner, address _spender) constant returns (uint remaining);
event Transfer(address indexed _from, address indexed _to, uint _value);
event Approval(address indexed _owner, address indexed _spender, uint _value);
}
totalSupply:  代表的是代币发行总量    totalSupply():该方法可以返回代币的总数量
name:  发行代币的名称                       dicimals:  发行代币以后,代币交易的最小单位
balanceOf(): 该方法返回的是输入钱包地址后,该钱包的代币余额
tansferFrom() :从一个地址向另一个地址发送余额
approve(): 允许_spender从你的账户转出_value余额

allowance(): 允许_spender从你的账户转出_value的余额,调用多次会覆盖可用量。某些DEX功能需要此功能
event Transfer():  token转移完成后出发
event Approval():  approve(address _spender, uint256 _value)调用后触发

编写代币合约:
pragma solidity ^0.4.12;

contract IMigrationContract {
function migrate(address addr, uint256 nas) returns (bool success);
}

/* 灵感来自于NAS coin*/
contract SafeMath {

function safeAdd(uint256 x, uint256 y) internal returns(uint256) {
u
4000
int256 z = x + y;
assert((z >= x) && (z >= y));
return z;
}

function safeSubtract(uint256 x, uint256 y) internal returns(uint256) {
assert(x >= y);
uint256 z = x - y;
return z;
}

function safeMult(uint256 x, uint256 y) internal returns(uint256) {
uint256 z = x * y;
assert((x == 0)||(z/x == y));
return z;
}

}

contract Token {
uint256 public totalSupply;
function balanceOf(address _owner) constant returns (uint256 balance);
function transfer(address _to, uint256 _value) returns (bool success);
function transferFrom(address _from, address _to, uint256 _value) returns (bool success);
function approve(address _spender, uint256 _value) returns (bool success);
function allowance(address _owner, address _spender) constant returns (uint256 remaining);
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}

/* ERC 20 token */
contract StandardToken is Token {

function transfer(address _to, uint256 _value) returns (bool success) {
if (balances[msg.sender] >= _value && _value > 0) {
balances[msg.sender] -= _value;
balances[_to] += _value;
Transfer(msg.sender, _to, _value);
return true;
} else {
return false;
}
}

function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {
if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && _value > 0) {
balances[_to] += _value;
balances[_from] -= _value;
allowed[_from][msg.sender] -= _value;
Transfer(_from, _to, _value);
return true;
} else {
return false;
}
}

function balanceOf(address _owner) constant returns (uint256 balance) {
return balances[_owner];
}

function approve(address _spender, uint256 _value) returns (bool success) {
allowed[msg.sender][_spender] = _value;
Approval(msg.sender, _spender, _value);
return true;
}

function allowance(address _owner, address _spender) constant returns (uint256 remaining) {
return allowed[_owner][_spender];
}

mapping (address => uint256) balances;
mapping (address => mapping (address => uint256)) allowed;
}

contract BliBliToken is StandardToken, SafeMath {

// metadata
string public constant name = "BliBli";
string public constant symbol = "BCoin";
uint256 public constant decimals = 18;
string public version = "1.0";

// contracts
address public ethFundDeposit; // ETH存放地址
address public newContractAddr; // token更新地址

// crowdsale parameters
bool public isFunding; // 状态切换到true
uint256 public fundingStartBlock;
uint256 public fundingStopBlock;

uint256 public currentSupply; // 正在售卖中的tokens数量
uint256 public tokenRaised = 0; // 总的售卖数量token
uint256 public tokenMigrated = 0; // 总的已经交易的 token
uint256 public tokenExchangeRate = 625; // 625 BILIBILI 兑换 1 ETH

// events
event AllocateToken(address indexed _to, uint256 _value); // 分配的私有交易token;
event IssueToken(address indexed _to, uint256 _value); // 公开发行售卖的token;
event IncreaseSupply(uint256 _value);
event DecreaseSupply(uint256 _value);
event Migrate(address indexed _to, uint256 _value);

// 转换
function formatDecimals(uint256 _value) internal returns (uint256 ) {
return _value * 10 ** decimals;
}

// constructor
function BliBliToken(
address _ethFundDeposit,
uint256 _currentSupply)
{
ethFundDeposit = _ethFundDeposit;

isFunding = false; //通过控制预CrowdS ale状态
fundingStartBlock = 0;
fundingStopBlock = 0;

currentSupply = formatDecimals(_currentSupply);
totalSupply = formatDecimals(10000000);
balances[msg.sender] = totalSupply;
if(currentSupply > totalSupply) throw;
}

modifier isOwner() { require(msg.sender == ethFundDeposit); _; }

/// 设置token汇率
function setTokenExchangeRate(uint256 _tokenExchangeRate) isOwner external {
if (_tokenExchangeRate == 0) throw;
if (_tokenExchangeRate == tokenExchangeRate) throw;

tokenExchangeRate = _tokenExchangeRate;
}

/// @dev 超发token处理
function increaseSupply (uint256 _value) isOwner external {
uint256 value = formatDecimals(_value);
if (value + currentSupply > totalSupply) throw;
currentSupply = safeAdd(currentSupply, value);
IncreaseSupply(value);
}

/// @dev 被盗token处理
function decreaseSupply (uint256 _value) isOwner external {
uint256 value = formatDecimals(_value);
if (value + tokenRaised > currentSupply) throw;

currentSupply = safeSubtract(currentSupply, value);
DecreaseSupply(value);
}

/// 启动区块检测 异常的处理
function startFunding (uint256 _fundingStartBlock, uint256 _fundingStopBlock) isOwner external {
if (isFunding) throw;
if (_fundingStartBlock >= _fundingStopBlock) throw;
if (block.number >= _fundingStartBlock) throw;

fundingStartBlock = _fundingStartBlock;
fundingStopBlock = _fundingStopBlock;
isFunding = true;
}

/// 关闭区块异常处理
function stopFunding() isOwner external {
if (!isFunding) throw;
isFunding = false;
}

/// 开发了一个新的合同来接收token(或者更新token)
function setMigrateContract(address _newContractAddr) isOwner external {
if (_newContractAddr == newContractAddr) throw;
newContractAddr = _newContractAddr;
}

/// 设置新的所有者地址
function changeOwner(address _newFundDeposit) isOwner() external {
if (_newFundDeposit == address(0x0)) throw;
ethFundDeposit = _newFundDeposit;
}

///转移token到新的合约
function migrate() external {
if(isFunding) throw;
if(newContractAddr == address(0x0)) throw;

uint256 tokens = balances[msg.sender];
if (tokens == 0) throw;

balances[msg.sender] = 0;
tokenMigrated = safeAdd(tokenMigrated, tokens);

IMigrationContract newContract = IMigrationContract(newContractAddr);
if (!newContract.migrate(msg.sender, tokens)) throw;

Migrate(msg.sender, tokens); // log it
}

/// 转账ETH 到BILIBILI团队
function transferETH() isOwner external {
if (this.balance == 0) throw;
if (!ethFundDeposit.send(this.balance)) throw;
}

/// 将BILIBILI token分配到预处理地址。
function allocateToken (address _addr, uint256 _eth) isOwner external {
if (_eth == 0) throw;
if (_addr == address(0x0)) throw;

uint256 tokens = safeMult(formatDecimals(_eth), tokenExchangeRate);
if (tokens + tokenRaised > currentSupply) throw;

tokenRaised = safeAdd(tokenRaised, tokens);
balances[_addr] += tokens;

AllocateToken(_addr, tokens); // 记录token日志
}

/// 购买token
function () payable {
if (!isFunding) throw;
if (msg.value == 0) throw;

if (block.number < fundingStartBlock) throw;
if (block.number > fundingStopBlock) throw;

uint256 tokens = safeMult(msg.value, tokenExchangeRate);
if (tokens + tokenRaised > currentSupply) throw;

tokenRaised = safeAdd(tokenRaised, tokens);
balances[msg.sender] += tokens;

IssueToken(msg.sender, tokens); //记录日志
}
}以上的代币合约,是参考以太坊已经ICO过,并且产生价值的代币合约参考而来,完整比且功能强大,此合约创建的代币,具有“交易”,“转账”,“异常检测”,“更改代币持有人”,“设置汇率”,“被盗处理”,“超发代币”等功能。(解释下:在以太坊的世界中,硬通货就是ETH-以太币,相当于现实世界中的黄金,我们发布的代币,就相当于各国发行的需要 与黄金挂钩兑换比率的货币,国家对货币拥有控制权,只要合约功能进行扩展,创造代币的人也会对代币拥有控制权。)(对于挖矿的误解:不少小哥哥小姐姐认为挖矿就是挖币,其实挖矿是挖区块,区块是干嘛的,是用来打包交易的,是存储数据的,代币是不用挖的,当你挖到了区块,代币是给你的奖励,在发行量一定的情况下,代币会越来越少,所以挖到区块的奖励会变少。那奖励少了为什么还要挖矿呢,因为你的任何一笔交易都需要记录,一个区块的大小也就几M,存储不了那么多交易信息,所以要持续挖区块来记录你的交易,同时交易的手续费,会奖励给挖出区块的人。)
部署合约:    部署合约有多种方式      1 geth 编译代码 ---部署合约                                     2 用ethereum wallet钱包部署合约                                    3 最简单直观的部署合约方式:  MetaMaskRemix Solidity IDE 部署合约   我们按照 MetaMaskRemix Solidity IDE 来进行部署合约。
 1: 创建钱包帐号。MetaMask是钱包的一种,在chrome浏览器中,安装MetaMask插件即可,安装完成后,右上角会出现一个“狐狸头”的标志,点击该标志,打开钱包,第一步,创建账户,(创建账户只需要输入面密码即可,名称创建后可以随便改,该账户就是一个hash值,如何给自己创建的账户冲以太币,可以上https://otcbtc.com/sign_up网站,按照操作买以太币,然后转账到自己创建的账户)创建成功后,记住密码还有产生的几个随机单词(一定要记录下来)。如下:


   2:打开 Remix Solidity IDE 访问地址: http://remix.ethereum.org/#optimize=false&version=soljson-v0.4.21+commit.dfe3193c.js   界面如下 



3:  拷贝“编写代币合约”后边的代码到Remix Solidity IDE中按照如下编译



4: create 发布  如下 

 5 create后,产生hash值,拷贝hash值,在钱包中添加token








OK,如上所示,第一个属于你的真正意义上的去中心化数字货币就诞生了。正式网络和测试网络部署方法一样,不需要买eth就是了。

如果是测试网络,如何获得ETH?   进入 https://gitter.im/kovan-testnet/faucet  下方直接发送你的账户地址(hash值)即可,一般五分钟到账,会得到五个测试网络用的ETH币。

6(如果部署的是eth主网,非测试网,执行该步骤,测试网络可以不理会)

发布了代币以后,如果以后进行ico,那么需要发布源码公开。步骤如下

   ①  拷贝部署成功的合约地址(hash),到  https://etherscan.io/   右上角搜索hash
   ②  按照如下图进行verify AND publish
           打开如下页面第一步



         打开如下页面第二部






 
          打开如下页面第三部



 
 



 

  ok  现在的代币就比较完整了,差ico了

代币转账:

   1  metamask钱包转账:  如下



   输入地址和代币数量



网页钱包转账:  如下  https://www.myetherwallet.com/#send-transaction
    登录账户:



  转账交易



     qq群交流
 


 
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息