基于以太坊发行ERC20 Token(代币)

简介: 本文将介绍基于以太坊测试链,利用Remix与MetaMask两个工具发行Token(代币),以及基于ERC20标准规范编写代币合约,供初学者参考。 ERC20 Token也许你经常看到ERC20和代币一同出现, ERC20是以太坊定义的一个代币标准。

本文将介绍基于以太坊测试链,利用Remix与MetaMask两个工具发行Token(代币),以及基于ERC20标准规范编写代币合约,供初学者参考。

ERC20 Token
也许你经常看到ERC20和代币一同出现, ERC20是以太坊定义的一个代币标准。
要求我们在实现代币的时候必须要遵守的协议,如指定代币名称、总量、实现代币交易函数等,只有支持了协议才能被以太坊钱包支持。协议的github具体描述位于https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
一个标准的协议促使了代币可以在不同的应用中得到使用,如钱包和去中心化交易所。
接口定义如下:

pragma solidity ^0.4.19;

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);
}

代币合约
基于ERC20编写的合约代码如下:

pragma solidity ^0.4.19;

interface tokenRecipient { function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData) public; }

contract TokenERC20 {
    string public name;
    string public symbol;
    uint8 public decimals = 18;  // decimals 可以有的小数点个数,最小的代币单位。18 是建议的默认值
    uint256 public totalSupply;

    // 用mapping保存每个地址对应的余额
    mapping (address => uint256) public balanceOf;
    // 存储对账号的控制
    mapping (address => mapping (address => uint256)) public allowance;

    // 事件,用来通知客户端交易发生
    event Transfer(address indexed from, address indexed to, uint256 value);

    // 事件,用来通知客户端代币被消费
    event Burn(address indexed from, uint256 value);

    /**
     * 初始化构造
     */
    function TokenERC20(uint256 initialSupply, string tokenName, string tokenSymbol) public {
        totalSupply = initialSupply * 10 ** uint256(decimals);  // 供应的份额,份额跟最小的代币单位有关,份额 = 币数 * 10 ** decimals。
        balanceOf[msg.sender] = totalSupply;                // 创建者拥有所有的代币
        name = tokenName;                                   // 代币名称
        symbol = tokenSymbol;                               // 代币符号
    }

    /**
     * 代币交易转移的内部实现
     */
    function _transfer(address _from, address _to, uint _value) internal {
        // 确保目标地址不为0x0,因为0x0地址代表销毁
        require(_to != 0x0);
        // 检查发送者余额
        require(balanceOf[_from] >= _value);
        // 确保转移为正数个
        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);
    }

    /**
     *  代币交易转移
     * 从自己(创建交易者)账号发送`_value`个代币到 `_to`账号
     *
     * @param _to 接收者地址
     * @param _value 转移数额
     */
    function transfer(address _to, uint256 _value) public {
        _transfer(msg.sender, _to, _value);
    }

    /**
     * 账号之间代币交易转移
     * @param _from 发送者地址
     * @param _to 接收者地址
     * @param _value 转移数额
     */
    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;
    }

    /**
     * 设置某个地址(合约)可以创建交易者名义花费的代币数。
     *
     * 允许发送者`_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;
    }

    /**
     * 设置允许一个地址(合约)以我(创建交易者)的名义可最多花费的代币数。
     *
     * @param _spender 被授权的地址(合约)
     * @param _value 最大可花费代币数
     * @param _extraData 发送给合约的附加数据
     */
    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;
        }
    }

    /**
     * 销毁我(创建交易者)账户中指定个代币
     */
    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;
    }
}

部署合约
完成代币合约编写后,可以将合约发布到Etherscan的测试链上(公链需要购买ether,而且速度较慢,建议开发在测试上进行),合约部署方式如下:

我采用Remix在线浏览器IDE才进行合约的编译和部署的,打开Remix页面样子如下:

image

点击新建按钮,将上面编辑的合约复制到IDE中:

image


复制完成后,IDE的左边会自动校验你的合约的编写是否准确,有错误会提示,警告可以忽略。

image

中间插入MetaMask讲解

MetaMask使用
由于我们是在以太坊测试链上发行合约,还是需要ether的,只不过可以免费获得,为了发行合约,我们需要测试链账户,下面我们将插入使用MetaMaskchrome插件来链接创建账户:

image


安装好后,在浏览器右上角会出现图标,点击图标,一直点击到下图,填写你的密码,进入后就创建好了一个MetaMask钱包,MetaMask会为用户创建12个英文助记词, 一定要保存好这些助记词,一定要保存好这些助记词,一定要保存好这些助记词,在其他钱包导入这个新创建的账户的时候有可能需要这些助记词。具体细节可以参考 这篇文章

image

创建好后,会给你默认一个账号:

image


由于我们是要基于以太坊测试链发行代币,所以我们选择测试链:

image


此时,我们发现我们的账户中没有ether,依次按照如下步骤获取,

image

image


这时候会打开网页,点击图标(建议点一两次就ok,每次会给你的账户放1个ether,部署合约1个就已经搓搓有余。)。

image


一会你就会发现你们账户有金额;

image

准备工作终于做完了,现在我们开始部署代币合约,这时候点击IDE右侧横栏中的run,按照1到3确认信息,并在4中编写你要发行的代币的信息,依次是100000000,"GaoTeB","GTB"(发行总量,发行币全称,发行币简称),4步确认不误后点击create按钮发布代币合约带测试链中。

image


点击后,会弹出对话框:

image


点击submit后,如果不报错,此时,会出现你的合约信息:

image

点击合约会打开页面,你可以看到正在创建中:

image

过一会,你就会看到:

image

那么你就基本已经发行成功你的代币了!

怎么在我们的账户下看呢?

下面我们使用MetaMask工具查看,依次点击:

image


将刚才打开的页面中的信息填入MetaMask中,

image


这时候,我们就能看到啦:

image

哎,终于大功告成,下面我们来转账一回试试:

代币交易
MetaMask插件没有提供代币交易功能,同时考虑到很多人并没有以太坊钱包或是被以太坊钱包网络同步问题折磨,今天我用网页钱包来讲解代币交易。
初次进入会有一些列的确认信息,一顿点击,来到这个页面,选择与MetaMask同一个网络链(以太坊测试链):

image


然后按下图点击:

image


点击链接后,这个页面就会和你的MetaMask链接上,你会发现你的账户信息就会出现在页面上。
此时,你的Token信息并没有出现在这里,需要你认为添加:

image


点击添加,将你的Token信息填入这里:

image


此时,你会发现:

image

然后开始代币交易,我们尝试转账给别的账户,填写好信息后依次点击:

image


此时,你将会发现,你的账户的Token已经减少了。

如果你觉得这边文章对你有些帮助,请wx给作者点辛苦费吧,谢谢!

image

目录
相关文章
|
5月前
|
供应链 安全 区块链
区块链钱包合约代币质押系统开发(模式详情)
一组条件在时间的推移中不可能一直正确的,而智能合约是不可变的,更新当前的预编程条件几乎是不可能的
|
7月前
|
JavaScript 前端开发 API
如何通过合约获取所有ERC20转账
通过使用正确的API,可以轻松获取与合约地址相关的ERC20代币的所有转账记录。通过创建账户、编写使用API的脚本并使用getTokenTransfers函数,您可以访问和分析有关ERC20代币的有价值的转账数据。
164 0
|
7月前
|
JavaScript 前端开发 IDE
如何获取某个地址拥有的所有ERC20代币
本文将介绍如何设置Chainbase帐户、编写使用Chainbase API的脚本以及获取ERC20令牌余额的过程。
165 0
|
8月前
|
区块链
如何发行数字货币代币?[数字货币代币的发行和操作流程]
如何发行数字货币代币?[数字货币代币的发行和操作流程]
|
8月前
|
存储 JavaScript 前端开发
区块链代币支付钱包(trx/trc20代币/usdt)对接开发
区块链代币支付钱包(trx/trc20代币/usdt)对接开发
|
9月前
|
存储 安全 区块链
DAPP|去中心化交易系统开发(合约代币发行)
区块链是一种特殊的分布式系统 etherStore.withdraw
|
9月前
|
人工智能 区块链 安全
区块链BSC币安链DAPP发行代币合约项目系统开发正式版丨DAPP币安链BSC代币发行合约系统开发(源码详情)
 本质上来说,智能合约是一段程序,它以计算机指令的方式实现了传统合约的自动化处理。智能合约程序不只是一个可以自动执行的计算机程序,它本身就是一个系统参与者,对接收到的信息进行回应,可以接收和储存价值,也可以向外发送信息和价值。
|
9月前
|
前端开发 安全 JavaScript
  ERC20 Token智能合约DApp开发
ERC20 Token智能合约DApp开发是指基于以太坊区块链平台和ERC20 Token标准开发的去中心化应用程序,用于数字货币、代币、积分等的发行、交易和管理。
|
存储 人工智能 安全
区块链合约交易所源码新币币交易所USDT秒合约杠杆C2C法币交易
迄今为止,已经有相当多的服务提供加密货币兑换服务。虚拟货币的流行度只增不减,交易平台的需求量也越来越大。 并非所有知名交易所都是可靠和诚实的,因此利基市场仍然对新的和改进的公司开放。
区块链合约交易所源码新币币交易所USDT秒合约杠杆C2C法币交易
|
安全 测试技术 区块链
非同质化代币的过去、现在和未来
非同质化代币的过去、现在和未来
109 0
非同质化代币的过去、现在和未来