基于以太坊发布属于自己的数字货币(代币)完整版
https://blog.csdn.net/JAVA_HHHH/article/details/79771752
?
本文單純從技術角度詳細介紹如何基于以太坊ERC20創(chuàng)建代幣的流程(此案例是部署的eth主網,非測試案例)
?
寫在前面
?
本文所講的代幣是使用以太坊智能合約創(chuàng)建,閱讀本文前,你應該對以太坊、智能合約有所了解,如果你還不了解,建議你先看以太坊是什么。
代幣Token
如果不那么追求精確的定義,代幣就是數字貨幣,比特幣、以太幣就是一個代幣。
利用以太坊的智能合約可以輕松編寫出屬于自己的代幣,代幣可以代表任何可以交易的東西,如:積分、財產、證書等等。
因此不管是出于商業(yè),還是學習很多人想創(chuàng)建一個自己的代幣,先貼一個圖看看創(chuàng)建的代幣是什么樣子。
以我自己發(fā)布的BliBli幣 Bcoin為例
訪問地址 : ?https://etherscan.io/token/0x73c8da697fe5e145f6269c4c852e59a7328f9371
?
?
?
?今天我們就來詳細講一講怎樣創(chuàng)建一個這樣的代幣。
ERC20 Token
ERC20和代幣一同出現, ERC20是以太坊定義的一個代幣標準。是一種發(fā)行代幣合約必須要遵守的協(xié)議,該協(xié)議規(guī)定了幾個參數——發(fā)行貨幣的名稱,簡稱,發(fā)行量,要支持的函數等,只有支持了該協(xié)議才會被以太坊所認同。
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:? 代表的是代幣發(fā)行總量? ? totalSupply():該方法可以返回代幣的總數量
name:? 發(fā)行代幣的名稱? ? ? ? ? ? ? ? ? ? ? ?dicimals:? 發(fā)行代幣以后,代幣交易的最小單位
balanceOf(): 該方法返回的是輸入錢包地址后,該錢包的代幣余額
tansferFrom() :從一個地址向另一個地址發(fā)送余額
approve(): 允許_spender從你的賬戶轉出_value余額
allowance(): 允許_spender從你的賬戶轉出_value的余額,調用多次會覆蓋可用量。某些DEX功能需要此功能
event Transfer(): ?token轉移完成后出發(fā)
event Approval(): ?approve(address _spender, uint256 _value)調用后觸發(fā)
?
編寫代幣合約:
?
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; // 狀態(tài)切換到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); // 公開發(fā)行售賣的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狀態(tài)
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 超發(fā)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);
}
/// 啟動區(qū)塊檢測 異常的處理
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;
}
/// 關閉區(qū)塊異常處理
function stopFunding() isOwner external {
if (!isFunding) throw;
isFunding = false;
}
/// 開發(fā)了一個新的合同來接收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過,并且產生價值的代幣合約參考而來,完整比且功能強大,此合約創(chuàng)建的代幣,具有“交易”,“轉賬”,“異常檢測”,“更改代幣持有人”,“設置匯率”,“被盜處理”,“超發(fā)代幣”等功能。
(解釋下:在以太坊的世界中,硬通貨就是ETH-以太幣,相當于現實世界中的黃金,我們發(fā)布的代幣,就相當于各國發(fā)行的需要 與黃金掛鉤兌換比率的貨幣,國家對貨幣擁有控制權,只要合約功能進行擴展,創(chuàng)造代幣的人也會對代幣擁有控制權。)
(對于挖礦的誤解:不少小哥哥小姐姐認為挖礦就是挖幣,其實挖礦是挖區(qū)塊,區(qū)塊是干嘛的,是用來打包交易的,是存儲數據的,代幣是不用挖的,當你挖到了區(qū)塊,代幣是給你的獎勵,在發(fā)行量一定的情況下,代幣會越來越少,所以挖到區(qū)塊的獎勵會變少。那獎勵少了為什么還要挖礦呢,因為你的任何一筆交易都需要記錄,一個區(qū)塊的大小也就幾M,存儲不了那么多交易信息,所以要持續(xù)挖區(qū)塊來記錄你的交易,同時交易的手續(xù)費,會獎勵給挖出區(qū)塊的人。)
?
部署合約:
? ??
部署合約有多種方式? ? ? 1 geth 編譯代碼 ---部署合約
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?2 用ethereum wallet錢包部署合約
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 3 最簡單直觀的部署合約方式:??MetaMask和Remix Solidity IDE?部署合約
? ?我們按照?MetaMask和Remix Solidity IDE?來進行部署合約。
?1:?創(chuàng)建錢包帳號。MetaMask是錢包的一種,在chrome瀏覽器中,安裝MetaMask插件即可,安裝完成后,右上角會出現一個“狐貍頭”的標志,點擊該標志,打開錢包,第一步,創(chuàng)建賬戶,(創(chuàng)建賬戶只需要輸入面密碼即可,名稱創(chuàng)建后可以隨便改,該賬戶就是一個hash值,如何給自己創(chuàng)建的賬戶沖以太幣,可以上https://otcbtc.com/sign_up網站,按照操作買以太幣,然后轉賬到自己創(chuàng)建的賬戶)創(chuàng)建成功后,記住密碼還有產生的幾個隨機單詞(一定要記錄下來)。如下:
?
???2:打開?Remix Solidity IDE?訪問地址:?http://remix.ethereum.org/#optimize=false&version=soljson-v0.4.21+commit.dfe3193c.js? ?界面如下?
?
?
?
3:? 拷貝“編寫代幣合約”后邊的代碼到Remix Solidity IDE中按照如下編譯
?
4: create 發(fā)布? 如下
?
?
5 create后,產生hash值,拷貝hash值,在錢包中添加token
?
?
?
?
?
OK,如上所示,第一個屬于你的真正意義上的去中心化數字貨幣就誕生了。正式網絡和測試網絡部署方法一樣,不需要買eth就是了。
如果是測試網絡,如何獲得ETH?? ?進入 https://gitter.im/kovan-testnet/faucet? 下方直接發(fā)送你的賬戶地址(hash值)即可,一般五分鐘到賬,會得到五個測試網絡用的ETH幣。
?
?
6(如果部署的是eth主網,非測試網,執(zhí)行該步驟,測試網絡可以不理會)
發(fā)布了代幣以后,如果以后進行ico,那么需要發(fā)布源碼公開。步驟如下
? ?①? 拷貝部署成功的合約地址(hash),到? https://etherscan.io/? ?右上角搜索hash
? ?②? 按照如下圖進行verify AND publish
? ? ? ? ? ?打開如下頁面第一步
?
?
? ? ? ? ?打開如下頁面第二部
?
?
?
?
? ? ? ? ? 打開如下頁面第三部
?
?
?
?
?
?
?
? ok? 現在的代幣就比較完整了,差ico了
?
?
代幣轉賬:
? ?1? metamask錢包轉賬:? 如下
?
? ?輸入地址和代幣數量
?
?
?
?
2? 網頁錢包轉賬:? 如下??https://www.myetherwallet.com/#send-transaction
? ? 登錄賬戶:
?
?
? 轉賬交易
?
---------------------
作者:JAVA_HHHH
來源:CSDN
原文:https://blog.csdn.net/JAVA_HHHH/article/details/79771752
版權聲明:本文為博主原創(chuàng)文章,轉載請附上博文鏈接!
轉載于:https://www.cnblogs.com/zhangbojiangfeng/p/10158628.html
總結
以上是生活随笔為你收集整理的基于以太坊发布属于自己的数字货币(代币)完整版的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 时间模块和时间工具
- 下一篇: 梦到前任老公预示着什么