基于以太坊私鏈代幣發(fā)布

【傳智播客.黑馬程序員訓(xùn)練營成都中心】

一、前言

??

1.1 預(yù)備知識

(1) 以太坊相關(guān)概念 (2) 熟悉智能合約代碼編寫與部署 (3) 以太坊私鏈環(huán)境搭建 (4) Mist錢包的安裝與使用

1.2 環(huán)境介紹

(1) win10 (2) Mist錢包 (3) geth ---(version:1.7.2) ---搭建以太坊私鏈

二域那、以太坊代幣(Token)

??

2.1 介紹

如果不那么追求精確的定義播掷,代幣就是數(shù)字貨幣审编,比特幣、以太幣都可以定義代幣歧匈。而以太坊代幣是基于以太坊智能合約編寫出來并發(fā)行到以太坊虛擬機上的合約數(shù)字貨幣垒酬,代幣可以代表任何可以交易的東西,如:積分、財產(chǎn)勘究、證書等等矮湘。利用以太坊智能合約能夠非常輕松實現(xiàn)自己的代幣,因為以太坊提供了一個開發(fā)代幣的ERC20標準口糕。

2.2 標準代幣ERC20 Token

ERC20和代幣經(jīng)常一同出現(xiàn)缅阳, ERC20是以太坊定義的一個代幣標準。 要求我們在實現(xiàn)代幣的時必須要遵守的協(xié)議景描,如指定代幣名稱十办、總量、實現(xiàn)代幣交易函數(shù)等伏伯,只有支持了協(xié)議才能被以太坊錢包支持橘洞,這樣你的代幣才具有交易和流通的能力。目前ERC20存在一些無法解決的問題说搅,但是新的標準ERC223以及出世炸枣,但市面上大多數(shù)以太坊代幣都采用ERC20標準,所以本文也使用ERC20標準實現(xiàn)自己的代碼弄唧,最后會對ERC20存在的問題給大家稍作解釋适肠,那接下來我們就進入正題。

三候引、代幣合約

??

3.1 ERC20的標準接口

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" contenteditable="false" cid="n19" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; caret-color: rgb(51, 51, 51); color: rgb(51, 51, 51); font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-indent: 0px; text-transform: none; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none; background-position: inherit inherit; background-repeat: inherit inherit;">contract ERC20 {
function name() constant returns (string name)
function symbol() constant returns (string symbol)
function decimals() constant returns (uint8 decimals)
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);
}</pre>

接口代碼解釋: name() 返回ERC20代幣的名字侯养,例如”My test token”。 symbol() 返回代幣的簡稱澄干,例如:MTT逛揩,這個也是我們一般在代幣交易所看到的名字。 decimals() 返回token使用的小數(shù)點后幾位麸俘。比如如果設(shè)置為3辩稽,就是支持0.001表示。 totalSupply() 返回token的總供應(yīng)量 balanceOf() 返回某個地址(賬戶)的賬戶余額 transfer() 從代幣合約的調(diào)用者地址上轉(zhuǎn)移value的數(shù)量token到的地址to从媚,并且必須觸發(fā)Transfer事件逞泄。 transferFrom() transferFrom方法用于允許合同代理某人轉(zhuǎn)移token。前提是被代理人調(diào)用approve方法允許代理人設(shè)置操作自己多少token allowance() 被代理人設(shè)置代理人操作自己的多少token approve() 更改被代理人設(shè)置代理人操作自己的多少token拜效,并且必須觸發(fā)Approval事件 Transfer事件 代幣被轉(zhuǎn)移時觸發(fā)該事件喷众,記錄轉(zhuǎn)賬日志 Approval事件 調(diào)用approve方法時觸發(fā),記錄授權(quán)日志

注意:以上ERC20標準代幣接口方法只是標準紧憾,并不是所有方法都需要實現(xiàn)到千,當然我們還可以根據(jù)自己的業(yè)務(wù)增強自己的代幣,比如實現(xiàn)代幣管理稻励、代幣增發(fā)父阻、代幣兌換愈涩、資產(chǎn)凍結(jié)望抽、Gas自動補充等功能的高級代幣

3.2 代幣合約實現(xiàn)

<pre spellcheck="false" class="md-fences md-end-block ty-contain-cm modeLoaded" lang="" contenteditable="false" cid="n24" mdtype="fences" style="box-sizing: border-box; overflow: visible; font-family: var(--monospace); font-size: 0.9em; display: block; break-inside: avoid; text-align: left; white-space: normal; background-image: inherit; background-size: inherit; background-attachment: inherit; background-origin: inherit; background-clip: inherit; background-color: rgb(248, 248, 248); position: relative !important; border: 1px solid rgb(231, 234, 237); border-top-left-radius: 3px; border-top-right-radius: 3px; border-bottom-right-radius: 3px; border-bottom-left-radius: 3px; padding: 8px 1em 6px; margin-bottom: 15px; margin-top: 15px; width: inherit; caret-color: rgb(51, 51, 51); color: rgb(51, 51, 51); font-style: normal; font-variant-caps: normal; font-weight: normal; letter-spacing: normal; orphans: auto; text-indent: 0px; text-transform: none; widows: auto; word-spacing: 0px; -webkit-text-size-adjust: auto; -webkit-text-stroke-width: 0px; text-decoration: none; background-position: inherit inherit; background-repeat: inherit inherit;">pragma solidity ^0.4.16;
?
interface tokenRecipient { function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData) public; }
?
contract TokenERC20 {
string public name; //token的名字
string public symbol;//token的簡稱
uint8 public decimals = 18; // decimals 可以有的小數(shù)點個數(shù)加矛,最小的代幣單位。18 是建議的默認值
uint256 public totalSupply;//token的總數(shù)
?
// 用mapping保存每個地址對應(yīng)的余額
mapping (address => uint256) public balanceOf;
// 存儲對賬號的控制
mapping (address => mapping (address => uint256)) public allowance;
?
// 事件煤篙,用來通知客戶端交易發(fā)生
event Transfer(address indexed from, address indexed to, uint256 value);
?
// 事件斟览,用來通知客戶端代幣被消費
event Burn(address indexed from, uint256 value);
?
/**

  • 初始化構(gòu)造
    /
    function TokenERC20(uint256 initialSupply, string tokenName, string tokenSymbol) public {
    totalSupply = initialSupply * 10 ** uint256(decimals); // 供應(yīng)的份額,份額跟最小的代幣單位有關(guān)辑奈,份額 = 幣數(shù) * 10 ** decimals苛茂。
    balanceOf[msg.sender] = totalSupply; // 創(chuàng)建者擁有所有的代幣
    name = tokenName; // 代幣名稱
    symbol = tokenSymbol; // 代幣符號
    }
    ?
    /
    *
  • 代幣交易轉(zhuǎn)移的內(nèi)部實現(xiàn)
    /
    function _transfer(address _from, address _to, uint _value) internal {
    // 確保目標地址不為0x0,因為0x0地址代表銷毀
    require(_to != 0x0);
    // 檢查發(fā)送者余額
    require(balanceOf[_from] >= _value);
    // 確保轉(zhuǎn)移為正數(shù)個
    require(balanceOf[_to] + _value > balanceOf[_to]);
    ?
    // 以下用來檢查交易鸠窗,
    uint previousBalances = balanceOf[_from] + balanceOf[_to];
    // Subtract from the sender
    balanceOf[_from] -= _value;
    // Add the same to the recipient
    balanceOf[_to] += _value;
    Transfer(_from, _to, _value);
    ?
    // 用assert來檢查代碼邏輯妓羊。
    assert(balanceOf[_from] + balanceOf[_to] == previousBalances);
    }
    ?
    /
    *
  • 代幣交易轉(zhuǎn)移
  • 從自己(創(chuàng)建交易者)賬號發(fā)送_value個代幣到 _to賬號
  • @param _to 接收者地址
  • @param _value 轉(zhuǎn)移數(shù)額
    /
    function transfer(address _to, uint256 _value) public {
    _transfer(msg.sender, _to, _value);
    }
    ?
    /
    *
  • 賬號之間代幣交易轉(zhuǎn)移
  • @param _from 發(fā)送者地址
  • @param _to 接收者地址
  • @param _value 轉(zhuǎn)移數(shù)額
    /
    function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
    require(_value <= allowance[_from][msg.sender]); // Check allowance
    allowance[_from][msg.sender] -= _value;
    _transfer(_from, _to, _value);
    return true;
    }
    ?
    /
    *
  • 設(shè)置某個地址(合約)可以創(chuàng)建交易者名義花費的代幣數(shù)。
  • 允許發(fā)送者_spender 花費不多于 _value 個代幣
  • @param _spender The address authorized to spend
  • @param _value the max amount they can spend
    /
    function approve(address _spender, uint256 _value) public
    returns (bool success) {
    allowance[msg.sender][_spender] = _value;
    return true;
    }
    ?
    /
    *
  • 設(shè)置允許一個地址(合約)以我(創(chuàng)建交易者)的名義可最多花費的代幣數(shù)稍计。
  • @param _spender 被授權(quán)的地址(合約)
  • @param _value 最大可花費代幣數(shù)
  • @param _extraData 發(fā)送給合約的附加數(shù)據(jù)
    /
    function approveAndCall(address _spender, uint256 _value, bytes _extraData)
    public
    returns (bool success) {
    tokenRecipient spender = tokenRecipient(_spender);
    if (approve(_spender, _value)) {
    // 通知合約
    spender.receiveApproval(msg.sender, _value, this, _extraData);
    return true;
    }
    }
    ?
    /
    *
  • 銷毀我(創(chuàng)建交易者)賬戶中指定個代幣
    /
    function burn(uint256 _value) public returns (bool success) {
    require(balanceOf[msg.sender] >= _value); // Check if the sender has enough
    balanceOf[msg.sender] -= _value; // Subtract from the sender
    totalSupply -= _value; // Updates totalSupply
    Burn(msg.sender, _value);
    return true;
    }
    ?
    /
    *
  • 銷毀用戶賬戶中指定個代幣
  • Remove _value tokens from the system irreversibly on behalf of _from.
  • @param _from the address of the sender
  • @param _value the amount of money to burn
    */
    function burnFrom(address _from, uint256 _value) public returns (bool success) {
    require(balanceOf[_from] >= _value); // Check if the targeted balance is enough
    require(_value <= allowance[_from][msg.sender]); // Check allowance
    balanceOf[_from] -= _value; // Subtract from the targeted balance
    allowance[_from][msg.sender] -= _value; // Subtract from the sender's allowance
    totalSupply -= _value; // Update totalSupply
    Burn(_from, _value);
    return true;
    }
    }</pre>

四躁绸、部署

??

采用以太坊錢包mist+geth私有環(huán)境部署

以太坊私鏈的搭建和mist錢包的安裝與使用請自行學習

4.1 啟動私鏈

image

4.2 新建賬號

image

4.3 挖礦

挖礦:挖礦可以獲得私有鏈的以太幣,因為我們需要部署我們上面寫的代幣合約就需要消費gas臣嚣,gas就是相應(yīng)的以太幣净刮。挖礦默認采用第一個賬號進行,如下所示

在控制臺輸入:miner.start() 即可開始挖礦
image

查看余額

image

4.4 打開Mist錢包并連接到私鏈

image
界面介紹
image

4.5 合約部署

點擊【CONTRACTS】進入合約部署界面
image

點擊【DEPLOY NEW CONTRACT】開始部署新的合約
image

點擊最下面的【DEPLOY】彈出如下窗口(一定要在geth控制臺執(zhí)行miner.start(1)開啟挖礦)
image

點擊【W(wǎng)ALLETS】進入回到主界面
image

五硅则、測試Token

??

點擊【Main account】進入該賬號界面

image

點擊【Transfer Ether & Tokens】進入轉(zhuǎn)賬界面

image

在最下面點擊【send】并在彈出框輸入密碼,待挖礦成功之后如下界面

image

image

當然你還可以在token合約主頁面進行相關(guān)方法的測試淹父,方法的測試有讀者自行完成!

六、ERC20標準代幣的問題

ERC20有兩種轉(zhuǎn)賬方式怎虫,一種是收件方為一份合同暑认,這種情況下用戶必須使用approve+transferFrom的功能來進行代幣轉(zhuǎn)移;而另一種則是收件方為合同外賬戶(例如大审,錢包地址)的情況蘸际,用戶需將代幣通過transfer功能轉(zhuǎn)出 。如果用戶使用transfer給合同地址轉(zhuǎn)賬將導(dǎo)致代幣丟失饥努,據(jù)了解捡鱼,以太坊生態(tài)中的Golem代幣,至今仍有93644.51美元的代幣因投資者的無意操作而流失到合同地址內(nèi)酷愧,造成這些代幣的永久性丟失驾诈。因此ERC223就此誕生,相關(guān)介紹請讀者自行學習溶浴!

七乍迄、結(jié)尾

本文介紹了基于以太坊私鏈開發(fā)ERC20標準代幣合約,并且使用Mist錢包部署士败,以及簡單的轉(zhuǎn)賬測試闯两。 區(qū)塊鏈技術(shù)是目前非常熱門的褥伴,區(qū)塊鏈技術(shù)暫時還不成熟,但是相信未來區(qū)塊鏈在互聯(lián)網(wǎng)的地位一定不可小覷漾狼,希望本文能夠?qū)ψx者有幫助重慢。相互學習相互探討不斷專研

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市逊躁,隨后出現(xiàn)的幾起案子似踱,更是在濱河造成了極大的恐慌,老刑警劉巖稽煤,帶你破解...
    沈念sama閱讀 216,470評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件核芽,死亡現(xiàn)場離奇詭異,居然都是意外死亡酵熙,警方通過查閱死者的電腦和手機轧简,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,393評論 3 392
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來匾二,“玉大人哮独,你說我怎么就攤上這事〖傥穑” “怎么了借嗽?”我有些...
    開封第一講書人閱讀 162,577評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長转培。 經(jīng)常有香客問我恶导,道長,這世上最難降的妖魔是什么浸须? 我笑而不...
    開封第一講書人閱讀 58,176評論 1 292
  • 正文 為了忘掉前任惨寿,我火速辦了婚禮,結(jié)果婚禮上删窒,老公的妹妹穿的比我還像新娘裂垦。我一直安慰自己,他們只是感情好肌索,可當我...
    茶點故事閱讀 67,189評論 6 388
  • 文/花漫 我一把揭開白布蕉拢。 她就那樣靜靜地躺著,像睡著了一般诚亚。 火紅的嫁衣襯著肌膚如雪晕换。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,155評論 1 299
  • 那天站宗,我揣著相機與錄音闸准,去河邊找鬼。 笑死梢灭,一個胖子當著我的面吹牛夷家,可吹牛的內(nèi)容都是我干的蒸其。 我是一名探鬼主播,決...
    沈念sama閱讀 40,041評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼库快,長吁一口氣:“原來是場噩夢啊……” “哼摸袁!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起缺谴,我...
    開封第一講書人閱讀 38,903評論 0 274
  • 序言:老撾萬榮一對情侶失蹤但惶,失蹤者是張志新(化名)和其女友劉穎耳鸯,沒想到半個月后湿蛔,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,319評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡县爬,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,539評論 2 332
  • 正文 我和宋清朗相戀三年阳啥,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片财喳。...
    茶點故事閱讀 39,703評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡察迟,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出耳高,到底是詐尸還是另有隱情扎瓶,我是刑警寧澤,帶...
    沈念sama閱讀 35,417評論 5 343
  • 正文 年R本政府宣布泌枪,位于F島的核電站概荷,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏碌燕。R本人自食惡果不足惜误证,卻給世界環(huán)境...
    茶點故事閱讀 41,013評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望修壕。 院中可真熱鬧愈捅,春花似錦、人聲如沸慈鸠。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,664評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至碧囊,卻和暖如春嫉父,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背缕题。 一陣腳步聲響...
    開封第一講書人閱讀 32,818評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留胖腾,地道東北人烟零。 一個月前我還...
    沈念sama閱讀 47,711評論 2 368
  • 正文 我出身青樓瘪松,卻偏偏與公主長得像,于是被迫代替她去往敵國和親锨阿。 傳聞我的和親對象是個殘疾皇子宵睦,可洞房花燭夜當晚...
    茶點故事閱讀 44,601評論 2 353

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