使用Remix与MetaMask发行以太坊ERC20 Token

ERC20是以太坊网络上发行代币(Token)的一个标准协议接口,协议的github具体描述位于https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md。一个标准的协议促使了代币可以在不同的应用中得到使用,如钱包和去中心化交易所。目前有很多实现该标准协议的Token Examples,我们将使用https://github.com/ConsenSys/Tokens提供的例子进行演示操作。我们先来看下这个实现库中的主要合约文件:

ERC20 Token协议实现

  1. Token.sol ERC 20协议的抽象定义
//Abstract contract for the full ERC 20 Token standard
// https://github.com/ethereum/EIPs/issues/20

pragma solidity ^0.4.8;
contract Token {
    /// token总量,默认会为public变量生成一个getter函数接口,名称为totalSupply().
    uint256 public totalSupply;

    /// 获取账户_owner拥有token的数量
    function balanceOf(address _owner) constant returns (uint256 balance);

    //从消息发送者账户中往_to账户转数量为_value的token
    function transfer(address _to, uint256 _value) returns (bool success);

    //从账户_from中往账户_to转数量为_value的token,与approve方法配合使用
    function transferFrom(address _from, address _to, uint256 _value) returns  (bool success);

    //消息发送账户设置账户_spender能从发送账户中转出数量为_value的token
    function approve(address _spender, uint256 _value) returns (bool success);

    //获取账户_spender可以从账户_owner中转出token的数量
    function allowance(address _owner, address _spender) constant returns  (uint256 remaining);

    //发生转账时必须要触发的事件 
    event Transfer(address indexed _from, address indexed _to, uint256 _value);

    //当函数approve(address _spender, uint256 _value)成功执行时必须触发的事件
    event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}
  1. StandardToken.sol ERC20协议的标准实现
You should inherit from StandardToken or, for a token like you would want to
deploy in something like Mist, see HumanStandardToken.sol.
(This implements ONLY the standard functions and NOTHING else.
If you deploy this, you won't have anything useful.)
Implements ERC 20 Token standard: https://github.com/ethereum/EIPs/issues/20.*/

pragma solidity ^0.4.8;
import "./Token.sol";
contract StandardToken is Token {
    function transfer(address _to, uint256 _value) returns (bool success) {
        //默认totalSupply 不会超过最大值 (2^256 - 1).
        //如果随着时间的推移将会有新的token生成,则可以用下面这句避免溢出的异常
        //require(balances[msg.sender] >= _value && balances[_to] + _value >balances[_to]);
        require(balances[msg.sender] >= _value);
        balances[msg.sender] -= _value;//从消息发送者账户中减去token数量_value
        balances[_to] += _value;//往接收账户增加token数量_value
        Transfer(msg.sender, _to, _value);//触发转币交易事件
        return true;
    }
    function transferFrom(address _from, address _to, uint256 _value) returns (bool success) {
        //require(balances[_from] >= _value && allowed[_from][msg.sender] >= _value && balances[_to] + _value > balances[_to]);
        require(balances[_from] >= _value && allowed[_from][msg.sender] >=  _value);
        balances[_to] += _value;//接收账户增加token数量_value
        balances[_from] -= _value; ;//支出账户_from减去token数量_value
        allowed[_from][msg.sender] -= _value;//消息发送者可以从账户_from中转出的数量减少_value
        Transfer(_from, _to, _value);//触发转币交易事件
        return true;
    }
    //查询余额
    function balanceOf(address _owner) constant returns (uint256 balance) {
        return balances[_owner];
    }
    //授权账户_spender可以从消息发送者账户转出数量为_value的token
    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];//允许_spender从_owner中转出的token数
    }

    mapping (address => uint256) balances;
    mapping (address => mapping (address => uint256)) allowed;
}
  1. HumanStandardToken.sol 具体的token实现
This Token Contract implements the standard token functionality (https://github.com/ethereum/EIPs/issues/20) as well as the following OPTIONAL extras intended for use by humans.
In other words. This is intended for deployment in something like a Token Factory or Mist wallet, and then used by humans.
Imagine coins, currencies, shares, voting weight, etc.
Machine-based, rapid creation of many tokens would not necessarily need these extra features or will be minted in other manners.
1) Initial Finite Supply (upon creation one specifies how much is minted).
2) In the absence of a token registry: Optional Decimal, Symbol & Name.
3) Optional approveAndCall() functionality to notify a contract if an approval() has occurred.
.*/

import "./StandardToken.sol";
pragma solidity ^0.4.8;
contract HumanStandardToken is StandardToken {
    /* Public variables of the token */
    string public name;                   //名称: eg Simon Bucks
    uint8 public decimals;                //最多的小数位数How many decimals to show. ie. There could 1000 base units with 3 decimals. Meaning 0.980 SBX = 980 base units. It's like comparing 1 wei to 1 ether.
    string public symbol;                 //token简称: eg SBX
    string public version = 'H0.1';       //版本

    function HumanStandardToken(uint256 _initialAmount, string _tokenName, uint8 _decimalUnits, string _tokenSymbol) {
        balances[msg.sender] = _initialAmount; // 初始token数量给予消息发送者
        totalSupply = _initialAmount;         // 设置初始总量
        name = _tokenName;                   // token名称
        decimals = _decimalUnits;           // 小数位数
        symbol = _tokenSymbol;             // token简称
    }
    /* 同意转出并调用接收合约(根据自己需求实现) */
    function approveAndCall(address _spender, uint256 _value, bytes _extraData) returns (bool success) {
        allowed[msg.sender][_spender] = _value;
        Approval(msg.sender, _spender, _value);
        //call the receiveApproval function on the contract you want to be notified. This crafts the function signature manually so one doesn't have to include a contract in here just for this.
        //receiveApproval(address _from, uint256 _value, address _tokenContract, bytes _extraData)
        //it is assumed that when does this that the call *should* succeed, otherwise one would use vanilla approve instead.
        
        require(_spender.call(bytes4(bytes32(sha3("receiveApproval(address,uint256,address,bytes)"))), msg.sender, _value, this, _extraData));
        return true;
    }
}

Token合约发布

我们将使用MetaMask( chrome插件安装链接https://chrome.google.com/webstore/detail/metamask/nkbihfbeogaeaoehlefnkodbefgpgknn?authuser=2)和Remix(https://ethereum.github.io/browser-solidity)并选择在Ropsten测试网络(获取免费ETH: http://www.jianshu.com/p/41580c29656f)进行Token合约发布。

  1. 切换MetaMask至Ropsten网络
image.png

2.将所有相关代码copy至Remix

image.png

在右侧上方红框标记处Environment选择Injected Web3, 下方的Account列表将会列出MetaMask中的账户信息。然后在右侧下方红框中依次填入初始化HumanStandardToken需要的参数,初始token数量(100000000)、token的名称描述(My Test Token)、decimal数(8)、token简称(MTT)。

  1. Token合约发布

点击合约HumanStandardToken处的create按钮,将弹出如下画面:

image.png

点击SUBMIT将该交易请求发布至Rosten网络中,交易变成功打包后。可以查询到本次操作的交易id为0x9fb4144f5a28ac46d43c689994de3cfa29cdb538582bde1ea1d646efcb7dcfa, 合约地址为0x06750c263b1a344b9b01b32888e93bc3c28a950d,交易截图如下:

image.png

值得一提的是, 本次交易刚好赶上Ropsten在区块1700000后进行BYZANTIUM( 拜占庭)分叉,遗憾的是交易最后被打包到了区块1700017,没有打包到1700001区块中。

image.png

4.合约源代码上传

接下来我们看下如何在https://ropsten.etherscan.io上传合约的源代码,首先打开合约0x06750c263b1a344b9b01b32888e93bc3c28a950d的详情页,并切换至Contrant Code标签中,如下图。

image.png

在Contract code 标签页中点击“Verify And Publish”链接,然后填入下图红框各项内容。

image.png
  • Contract address为上面创建的合约地址;
  • Contract name为在Remix中选择创建的合约名称HumanStandardToken;
  • Compiler版本需选择在Remix进行合约创建时选择的编译器版本一致;
  • 是否优化Optimization也需要与Remix发布合约时保持一致;
  • 在“Enter the Solidity Contract Code below”中填入之前在Remix中的solidity合约代码;
  • 在“Constructor Arguments ABI-encoded”中填入构造函数参数(100000000,“My Test Token”,8,“MTT”)的ABI编码,这个编码可以在创建合约的transaction的Input data中找出,如下图蓝色选中的部分即是构造函数参数的ABI编码(b0029之后所有的数据)。
image.png

填好上述数据后,点击Verify and Publish,如果验证通过了就会出现如下页面:

image.png

最后我们切换到合约的详情页,点击Contract Source标签,就能看到上传的合约源代码了,如下图:

image.png

如果遇到错误"Unable to Verify Contract at this point time",请确认在提交合约源代码时,选择的编译器版本与是否优化选项,与你在Remix中的选择是否一致。

  1. 添加发布的Token到钱包

我们可以在MetaMask中添加上面生成的Token至MetaMask钱包中,如下图。

image.png

点击Add后可以在Tokens标签页中看到上面发布的Token MTT. (因为我们在创建HumanStandardToken时,输入的初始量为100000000,而decimal值为8,这个初始量值的单位是token的最低单位,故总量为1MTT,大家可以根据自己的情况作出相应调整。)

image.png

接下来就可以在Ropsten测试网络上进行Token的转账以及相关的测试操作了,如果测试没问题就按照同样的流程把合约部署至以太坊主网络中发行真实的token了。

Good Luck!!!

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,080评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,422评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,630评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,554评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,662评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,856评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,014评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,752评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,212评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,541评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,687评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,347评论 4 331
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,973评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,777评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,006评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,406评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,576评论 2 349

推荐阅读更多精彩内容

  • 前言: 周一听了oldlee《如何发行基于以太坊的数字货币》的精彩演讲,才发现发行以太坊ERC20 Token很简...
    钟晓宏阅读 19,195评论 34 40
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,633评论 18 139
  • 本文是对以太坊文档 Ethereum Frontier Guide 和 Ethereum Homestead 的整...
    趁风卷阅读 9,499评论 0 16
  • 新丰酒,新丰酒,题柱面将酡。待到时乘风破浪,再挥毫指点南柯,填一阕渔歌。 「新丰酒,新丰酒,题柱面将酡」 「新丰酒...
    肇英阅读 537评论 0 1
  • 通过昨天的论证,都知道,假如你中了1000元,同时股票又涨了1000元,最聪明的做法是分开告诉爱人,让ta嘚瑟两次...
    草酰盛阅读 283评论 0 0