基于以太坊發(fā)布屬于自己的數(shù)字貨幣(代幣)完整版

基于以太坊發(fā)布屬于自己的數(shù)字貨幣(代幣)完整版

(參考資料來源于網(wǎng)絡(luò)以及各種摸索,其中各種坑)


本文單純從技術(shù)角度詳細(xì)介紹如何基于以太坊ERC20創(chuàng)建代幣的流程(此案例是部署的eth主網(wǎng),非測試案例)


寫在前面


本文所講的代幣是使用以太坊智能合約創(chuàng)建,閱讀本文前,你應(yīng)該對以太坊、智能合約有所了解,如果你還不了解,建議你先看以太坊是什么。

代幣Token

如果不那么追求精確的定義,代幣就是數(shù)字貨幣,比特幣、以太幣就是一個代幣。

利用以太坊的智能合約可以輕松編寫出屬于自己的代幣,代幣可以代表任何可以交易的東西,如:積分、財(cái)產(chǎn)、證書等等。

因此不管是出于商業(yè),還是學(xué)習(xí)很多人想創(chuàng)建一個自己的代幣,先貼一個圖看看創(chuàng)建的代幣是什么樣子。

以我自己發(fā)布的BliBli幣 Bcoin為例

訪問地址 : ?https://etherscan.io/token/0x73c8da697fe5e145f6269c4c852e59a7328f9371

?今天我們就來詳細(xì)講一講怎樣創(chuàng)建一個這樣的代幣。

ERC20 Token

ERC20和代幣一同出現(xiàn), ERC20是以太坊定義的一個代幣標(biāo)準(zhǔn)。是一種發(fā)行代幣合約必須要遵守的協(xié)議,該協(xié)議規(guī)定了幾個參數(shù)——發(fā)行貨幣的名稱,簡稱,發(fā)行量,要支持的函數(shù)等,只有支持了該協(xié)議才會被以太坊所認(rèn)同。

erc20標(biāo)準(zhǔn)代碼如下

// 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():該方法可以返回代幣的總數(shù)量

name:? 發(fā)行代幣的名稱? ? ? ? ? ? ? ? ? ? ? ?dicimals:? 發(fā)行代幣以后,代幣交易的最小單位

balanceOf(): 該方法返回的是輸入錢包地址后,該錢包的代幣余額

tansferFrom() :從一個地址向另一個地址發(fā)送余額

approve(): 允許_spender從你的賬戶轉(zhuǎn)出_value余額

allowance(): 允許_spender從你的賬戶轉(zhuǎn)出_value的余額,調(diào)用多次會覆蓋可用量。某些DEX功能需要此功能

event Transfer(): ?token轉(zhuǎn)移完成后出發(fā)

event Approval(): ?approve(address _spender, uint256 _value)調(diào)用后觸發(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數(shù)量

? ? uint256 public tokenRaised = 0;? ? ? ? // 總的售賣數(shù)量token

? ? uint256 public tokenMigrated = 0;? ? // 總的已經(jīng)交易的 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);

? ? // 轉(zhuǎn)換

? ? function formatDecimals(uint256 _value) internal returns (uint256 ) {

? ? ? ? return _value * 10 ** decimals;

? ? }

? ? // constructor

? ? function BliBliToken(

? ? ? ? address _ethFundDeposit,

? ? ? ? uint256 _currentSupply)

? ? {

? ? ? ? ethFundDeposit = _ethFundDeposit;

? ? ? ? isFunding = false;? ? ? ? ? ? ? ? ? ? ? ? ? //通過控制預(yù)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); _; }

? ? ///? 設(shè)置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;

? ? }

? ? ///? 關(guān)閉區(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;

? ? }

? ? /// 設(shè)置新的所有者地址

? ? function changeOwner(address _newFundDeposit) isOwner() external {

? ? ? ? if (_newFundDeposit == address(0x0)) throw;

? ? ? ? ethFundDeposit = _newFundDeposit;

? ? }

? ? ///轉(zhuǎn)移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

? ? }

? ? /// 轉(zhuǎn)賬ETH 到BILIBILI團(tuán)隊(duì)

? ? function transferETH() isOwner external {

? ? ? ? if (this.balance == 0) throw;

? ? ? ? if (!ethFundDeposit.send(this.balance)) throw;

? ? }

? ? ///? 將BILIBILI token分配到預(yù)處理地址。

? ? 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);? //記錄日志

? ? }

}

以上的代幣合約,是參考以太坊已經(jīng)ICO過,并且產(chǎn)生價值的代幣合約參考而來,完整比且功能強(qiáng)大,此合約創(chuàng)建的代幣,具有“交易”,“轉(zhuǎn)賬”,“異常檢測”,“更改代幣持有人”,“設(shè)置匯率”,“被盜處理”,“超發(fā)代幣”等功能。

(解釋下:在以太坊的世界中,硬通貨就是ETH-以太幣,相當(dāng)于現(xiàn)實(shí)世界中的黃金,我們發(fā)布的代幣,就相當(dāng)于各國發(fā)行的需要 與黃金掛鉤兌換比率的貨幣,國家對貨幣擁有控制權(quán),只要合約功能進(jìn)行擴(kuò)展,創(chuàng)造代幣的人也會對代幣擁有控制權(quán)。)

(對于挖礦的誤解:不少小哥哥小姐姐認(rèn)為挖礦就是挖幣,其實(shí)挖礦是挖區(qū)塊,區(qū)塊是干嘛的,是用來打包交易的,是存儲數(shù)據(jù)的,代幣是不用挖的,當(dāng)你挖到了區(qū)塊,代幣是給你的獎勵,在發(fā)行量一定的情況下,代幣會越來越少,所以挖到區(qū)塊的獎勵會變少。那獎勵少了為什么還要挖礦呢,因?yàn)槟愕娜魏我还P交易都需要記錄,一個區(qū)塊的大小也就幾M,存儲不了那么多交易信息,所以要持續(xù)挖區(qū)塊來記錄你的交易,同時交易的手續(xù)費(fèi),會獎勵給挖出區(qū)塊的人。)

部署合約:


部署合約有多種方式? ? ? 1 geth 編譯代碼 ---部署合約

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?2 用ethereum wallet錢包部署合約

? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 3 最簡單直觀的部署合約方式:??MetaMask和Remix Solidity IDE?部署合約

? ?我們按照?MetaMask和Remix Solidity IDE?來進(jìn)行部署合約。

?1:?創(chuàng)建錢包帳號。MetaMask是錢包的一種,在chrome瀏覽器中,安裝MetaMask插件即可,安裝完成后,右上角會出現(xiàn)一個“狐貍頭”的標(biāo)志,點(diǎn)擊該標(biāo)志,打開錢包,第一步,創(chuàng)建賬戶,(創(chuàng)建賬戶只需要輸入面密碼即可,名稱創(chuàng)建后可以隨便改,該賬戶就是一個hash值,如何給自己創(chuàng)建的賬戶沖以太幣,可以上https://otcbtc.com/sign_up網(wǎng)站,按照操作買以太幣,然后轉(zhuǎn)賬到自己創(chuàng)建的賬戶)創(chuàng)建成功后,記住密碼還有產(chǎn)生的幾個隨機(jī)單詞(一定要記錄下來)。如下:

???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后,產(chǎn)生hash值,拷貝hash值,在錢包中添加token

OK,如上所示,第一個屬于你的真正意義上的去中心化數(shù)字貨幣就誕生了。正式網(wǎng)絡(luò)和測試網(wǎng)絡(luò)部署方法一樣,不需要買eth就是了。

如果是測試網(wǎng)絡(luò),如何獲得ETH?? ?進(jìn)入 https://gitter.im/kovan-testnet/faucet? 下方直接發(fā)送你的賬戶地址(hash值)即可,一般五分鐘到賬,會得到五個測試網(wǎng)絡(luò)用的ETH幣。

6(如果部署的是eth主網(wǎng),非測試網(wǎng),執(zhí)行該步驟,測試網(wǎng)絡(luò)可以不理會)

發(fā)布了代幣以后,如果以后進(jìn)行ico,那么需要發(fā)布源碼公開。步驟如下

? ?①? 拷貝部署成功的合約地址(hash),到? https://etherscan.io/? ?右上角搜索hash

? ?②? 按照如下圖進(jìn)行verify AND publish

? ? ? ? ? ?打開如下頁面第一步

? ? ? ? ?打開如下頁面第二部


? ? ? ? ? 打開如下頁面第三部




? ok? 現(xiàn)在的代幣就比較完整了,差ico了

代幣轉(zhuǎn)賬:

? ?1? metamask錢包轉(zhuǎn)賬:? 如下

? ?輸入地址和代幣數(shù)量

2? 網(wǎng)頁錢包轉(zhuǎn)賬:? 如下??https://www.myetherwallet.com/#send-transaction

? ? 登錄賬戶:

? 轉(zhuǎn)賬交易

---------------------

作者:JAVA_HHHH

來源:CSDN

原文:https://blog.csdn.net/JAVA_HHHH/article/details/79771752

版權(quán)聲明:本文為博主原創(chuàng)文章,轉(zhuǎn)載請附上博文鏈接!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 1、流程圖 2、ERC20代碼詳解 1)、基本合約提供總發(fā)行量,余額,交易轉(zhuǎn)賬函數(shù)以及轉(zhuǎn)賬事件 2)、Safe...
    08f1b6c52d2a閱讀 6,626評論 0 6
  • (注:本文是在原文的基礎(chǔ)上,根據(jù)個人的理解,修改部分內(nèi)容并添加了一些注釋) 買賣部分代碼未調(diào)試通過 基礎(chǔ)版的代幣合...
    中v中閱讀 2,976評論 0 2
  • 1、ERC20Basic 安全考慮定義抽象函數(shù)和發(fā)送事件,個人認(rèn)為隔離設(shè)計(jì)更安全 function totalS...
    08f1b6c52d2a閱讀 3,692評論 0 2
  • 媽媽:兒子,你躺在地上干嘛呢!臟! 弟弟:我在戰(zhàn)壕里!不怕苦不怕臟! 爸爸:咋不穿迷彩服?玩的逼真點(diǎn),沖鋒槍呢? ...
    五箴閱讀 201評論 0 0
  • 問: 裝修環(huán)保誤區(qū)-“掩蓋味道就能根除污染?” ??答: ?裝修后,很多人會用芳香劑、柚子皮、茶葉、醋等弄弄就行了。...
    史密斯空凈閱讀 192評論 0 1