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

https://blog.csdn.net/JAVA_HHHH/article/details/79771752git

 

本文单纯从技术角度详细介绍如何基于以太坊ERC20建立代币的流程(此案例是部署的eth主网,非测试案例)github

 

写在前面chrome

 

本文所讲的代币是使用以太坊智能合约建立,阅读本文前,你应该对以太坊、智能合约有所了解,若是你还不了解,建议你先看以太坊是什么。json

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

所以不论是出于商业,仍是学习不少人想建立一个本身的代币,先贴一个图看看建立的代币是什么样子。网络

以我本身发布的BliBli币 Bcoin为例app

访问地址 :  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) {
uint256 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 最简单直观的部署合约方式:  MetaMask和Remix Solidity IDE 部署合约

   咱们按照 MetaMask和Remix 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钱包转帐:  以下

 

   输入地址和代币数量

 

 

 

 

2  网页钱包转帐:  以下  https://www.myetherwallet.com/#send-transaction

    登陆帐户:

 

 

  转帐交易

相关文章
相关标签/搜索