主页 > imtoken冷钱包官网 > 基于以太坊私链的代币发行

基于以太坊私链的代币发行

imtoken冷钱包官网 2023-10-12 05:07:12

【传智播客。 黑马程序员训练营成都中心】

一、简介

​​​​

1.1 预备知识

(1)以太坊相关概念(2)熟悉智能合约代码编写与部署(3)以太坊私链环境搭建(4)Mist钱包安装与使用

1.2 环境介绍

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

2. 以太坊代币(Token)

​​​​

2.1 简介

如果不追求精确的定义以太坊靠谱吗,代币就是数字货币,比特币和以太坊都可以定义代币。 以太坊代币是基于以太坊智能合约编写并发行给以太坊虚拟机的合约数字货币。 代币可以代表任何可以交易的东西,比如积分、财产、证书等。使用以太坊智能合约很容易实现自己的代币,因为以太坊提供了开发代币的ERC20标准。

2.2 标准代币 ERC20 代币

ERC20 和代币经常一起出现。 ERC20 是以太坊定义的代币标准。 实现代币需要我们遵守的协议以太坊靠谱吗,比如指定代币名称、总量、实现代币交易功能等,只有协议支持,以太坊钱包才能支持,这样你的代币才能交易和流通能力。 目前ERC20还有一些无法解决的问题,但是新标准ERC223已经诞生,但是市面上的以太坊代币大多采用ERC20标准,所以本文也使用ERC20标准来实现自己的代码,最后将对ERC20存在的问题进行说明,下面稍微说明一下,然后进入正题。

3.代币合约

​​​​

3.1 ERC20标准接口

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

接口代码说明: name() 返回ERC20 token的名称,如“My test token”。 symbol() 返回代币的缩写,例如:MTT,这也是我们通常在代币交易所看到的名称。 decimals() 返回令牌使用的小数位数。 例如设置为3,则支持0.001表示。 totalSupply() 返回token总供应量 balanceOf() 返回一个地址(account)的账户余额 transfer() 将价值token从token合约的调用地址转入to地址,必须触发Transfer事件。 transferFrom() transferFrom方法用于让合约委托某人转账token。前提是被授权人调用approve方法让代理人设置自己操作多少token。 Allowance() 授权人设置代理人自己操作多少代币。 Event 转账事件 代币转账时触发该事件,并记录转账日志。 调用approve方法时会触发Approval事件,并记录授权日志。

注:以上ERC20标准代币接口方法只是标准,并非所有方法都需要实现。 当然我们也可以根据自己的业务对自己的代币进行增强,比如实现代币管理、代币发行、代币兑换、资产冻结、Gas自动补给等高级代币

3.2 代币合约实现

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 可以有的小数点个数,最小的代币单位。18 是建议的默认值
uint256 public totalSupply;//token的总数

// 用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;
    }
    }

4.部署

​​​​

部署在以太坊钱包mist+geth的私有环境中

以太坊私链的搭建和mist钱包的安装使用请自行学习

4.1 启动私有链

以太坊靠谱吗_以太创服靠谱吗_以太坊贸易靠谱吗

图片

4.2 创建一个新帐户

以太坊靠谱吗_以太创服靠谱吗_以太坊贸易靠谱吗

图片

4.3 挖矿

挖矿:挖矿可以获得私链的以太坊,因为需要部署我们上面写的token合约来消耗gas,gas就是对应的以太坊。默认使用第一个账户进行挖矿,如下图

在控制台输入:miner.start()开始挖矿

以太坊靠谱吗_以太创服靠谱吗_以太坊贸易靠谱吗

图片

查看余额

以太坊靠谱吗_以太创服靠谱吗_以太坊贸易靠谱吗

图片

4.4 打开Mist钱包并连接私链

以太坊靠谱吗_以太创服靠谱吗_以太坊贸易靠谱吗

图片

界面介绍

以太坊靠谱吗_以太创服靠谱吗_以太坊贸易靠谱吗

图片

4.5 合约部署 点击【CONTRACTS】进入合约部署界面

以太坊靠谱吗_以太创服靠谱吗_以太坊贸易靠谱吗

图片

点击【DEPLOY NEW CONTRACT】开始部署新合约

以太坊靠谱吗_以太创服靠谱吗_以太坊贸易靠谱吗

图片

点击下方【DEPLOY】弹出如下窗口(一定要在geth控制台执行miner.start(1)开始挖矿)

以太坊靠谱吗_以太创服靠谱吗_以太坊贸易靠谱吗

图片

点击【WALLETS】进入并返回主界面

以太坊靠谱吗_以太创服靠谱吗_以太坊贸易靠谱吗

图片

5. 测试令牌

​​​​

点击【主账户】进入账户界面

以太坊靠谱吗_以太创服靠谱吗_以太坊贸易靠谱吗

图片

点击【Transfer Ether & Tokens】进入转账界面

以太坊靠谱吗_以太创服靠谱吗_以太坊贸易靠谱吗

图片

点击下方【发送】,在弹出框中输入密码。 挖矿成功后界面如下

以太坊靠谱吗_以太创服靠谱吗_以太坊贸易靠谱吗

图片

以太坊靠谱吗_以太创服靠谱吗_以太坊贸易靠谱吗

图片

当然你也可以在代币合约主页面测试相关方法。 方法的测试由读者完成!

6. ERC20标准代币的问题

ERC20有两种转账方式,一种是接收方是合约,这种情况下用户必须使用approve+transferFrom函数来转账; 另一种是接收方是合约外的账户(比如钱包地址),用户需要通过转账功能将代币转出。 如果用户使用转账方式向合约地址转账,代币将会丢失。 据了解,以太坊生态中的Golem代币仍有93644.51美元的代币因投资者的无心操作而丢失至合约地址。 硬币永久丢失。 因此,ERC223诞生了。 请读者自行研究相关介绍!

七、结束

本文介绍了基于以太坊私有链的ERC20标准代币合约的开发,以及使用Mist钱包的部署,以及简单的转账测试。 区块链技术目前非常流行。 区块链技术还不成熟,但相信未来区块链在互联网中的地位不可低估。 希望本文能对读者有所帮助。相互学习,相互讨论,不断研究