在ETH网络上发布代币智能合约(在以太坊发行自己的币种)

在ETH网络上发布代币智能合约(在以太坊发行自己的币种)

以太坊官方开发文档:https://ethereum.org/zh/
以太坊小游戏代码学习:https://cryptozombies.io/

本文介绍了以下内容,文章比较长,涉及内容较多,如果对你有帮助,麻烦点赞、收藏,感谢支持

  • 如何搭建本地区块链智能合约开发环境
  • 如何编写代币合约、及代币合约的自定义方法
  • 智能合约测试、部署到开发网络、测试网络
  • 发布后调用合约
  • 相关代码会放到GitHub,链接在文章末尾

文章目录

  • 在ETH网络上发布代币智能合约(在以太坊发行自己的币种)
  • 本文使用环境
  • 一、环境搭建
    • 1.安装Node.js
    • 2.安装HardHat
  • 二、智能合约开发
  • 三、智能合约编译
  • 四、智能合约测试
  • 五、智能合约部署(本地开发网络)
  • 六、智能合约部署(私有、公开区块链[主、测试]网络)

本文使用环境

  • Windows 10 x64
  • Node v12.14.0
  • Hardhat v2.6.6(npm安装依赖会自动安装最新,版本不影响使用)
  • MetaMask 浏览器插件(Google插件需要VPN,可以使用Edge,安装插件不要一样使用)
  • (非必须)使用Besu搭建的ETH私链(搭建方法参考我的另一篇文章:使用For Java的Hyperledger Besu部署以太坊的私有链),不搭建私链也可以,文章最后是在以太坊测试链练习发布,免去搭建私链的时间

一、环境搭建

以太坊开发环境(之一Hardhat):https://hardhat.org/
以太坊合约调用(之一Web3.js也可以编译、部署合约):https://web3js.readthedocs.io/

1.安装Node.js

Hardhat是依赖Node环境的,先安装Node.js
在ETH网络上发布代币智能合约(在以太坊发行自己的币种)_第1张图片
下载长期维护版,并进行安装即可(各系统的安装流程,环境变量配置此处不做介绍,非本文核心内容),安装完成后打开终端(cmd、PowerShell),如下测试node环境有效性,正常输出版本信息即可

node -v
v12.14.0

2.安装HardHat

(Windows版node环境)Hardhat环境搭建:

  1. 建立空文件夹,运行npm init,初始化一个npm项目,按照提示依次输入项目信息
npm init
  1. 初始化完成后,运行npm install --save-dev hardhat,稍后使用的时候使用npx hardhat的方式调用
npm install --save-dev hardhat
  1. 安装hardhat-waffle、hardhat-truffle5、hardhat-ethers、web3,这使得 Hardhat 与使用 Waffle 构建的测试兼容,并支持远程调用智能合约
npm install --save-dev @nomiclabs/hardhat-waffle ethereum-waffle chai @nomiclabs/hardhat-ethers ethers @nomiclabs/hardhat-truffle5 @nomiclabs/hardhat-web3 web3
  1. 初始化一个hardhat项目
npx hardhat 

在ETH网络上发布代币智能合约(在以太坊发行自己的币种)_第2张图片

  1. 选择第一个创建简单的项目,这里会包含一些示例代码
  2. 创建完毕之后,再次运行npx hardhat即可获得帮助
    在ETH网络上发布代币智能合约(在以太坊发行自己的币种)_第3张图片
  3. 开启挖抗模式,否则后面添加合约后,不会有新的块产出,就看不到效果,修改目录下hardhat.config.js文件的networks如下,其他配置可参考:HardHat网络参考
module.exports = {
  defaultNetwork: "hardhat",
  networks: {
    hardhat: {
	  // 在这种情况下,将在 3 到 6 秒的随机延迟后挖掘一个新块。
	  // 例如,第一个区块可以在 4 秒后开采,第二个区块在 5.5 秒后开采,依此类推。
      mining: {
        auto: false,
        interval: [3000, 6000]
      }
    }
  },
  solidity: "0.8.4",
};
  1. 启动本地开发网络
npx hardhat node

看到输出Account #1、Private Key等信息,说明本地网络启动成功,该网络每次启动都是新的,但创世用户都是固定的,仅用于开发使用,并非真正意义上的区块链网络,本地开发测试发布都需要依赖这个网络环境

  1. Hardhat Network将公开一个JSON-RPC接口。要使用它,请将您的钱包或应用程序连接到http://localhost:8545
  • 新建或导入MetaMask钱包账户,此文不介绍该内容,钱包信息注意妥善保管

  • 点击浏览器插件MetaMask,三个点,点击展开视图便于操作
    在ETH网络上发布代币智能合约(在以太坊发行自己的币种)_第4张图片

  • 点击头像,选择设置
    在ETH网络上发布代币智能合约(在以太坊发行自己的币种)_第5张图片

  • 添加本地开发网络
    在ETH网络上发布代币智能合约(在以太坊发行自己的币种)_第6张图片

  • 保存后,头像旁就变为本地网络了,说明连接成功
    在这里插入图片描述

  • 注意:这时的用户还是创建钱包的默认用户,并不是所连接网络上的用户,选择钱包的导入账户
    在ETH网络上发布代币智能合约(在以太坊发行自己的币种)_第7张图片

  • 私钥,填写本地HardHat启动时,输出的任何一个Account下面的Private Key,点击导入后如图,才可以使用该账户进行后续操作,如果是私链,则使用私链中的用户,就是一定要使用对应网络中的用户,本地HardHat环境查看创世用户可以使用命令npm hardhat account
    在ETH网络上发布代币智能合约(在以太坊发行自己的币种)_第8张图片

二、智能合约开发

所涉及的代码都需要有,因为ERC20是代币本身的规范,但是对代币合约的操作以及其他方法都是需要自己开发的,我这里增加了给用户发币等一些方法,为了良好的体验建议跟着往下走

EIPs/eip-20.md
点击链接查看以太坊官方发布的ERC20标准说明

ERC代表“Etuereum Request for Comment”。
ERC20标准定义了一些函数接口,规定了各个代币的基本功能,它可以快速发币,而且使用又方便,因此空投币和大部分基于以太坊合约的代币基本上就是利用ERC-20标准开发的。
如果简单理解的话就是,ERC20是以太坊的一种标准,所有符合这个标准的数字货币都可以成为ERC20代币,自然也就能存入支持以太币的钱包中了,但是这些货币的交易本质上还是在消耗以太坊的资源,所以交易费都还是以太币。
这里的标准其实就是一种智能合约模版,只要满足这个模版的代币都称之为ERC20代币。你可以理解为电脑主板上的内存插条,只要符合一定的尺寸和接线标准的内存品牌都可以使用。这就等于说以太坊订立了一个标准,其他代币就不需要另起炉灶,全部从头到尾再搞一遍,只要满足这个标准就可以在以太坊公链上运行了,极大降低了开发难度。很多代币就是只关注自己的业务逻辑,底层全部依赖以太坊。
 
转自:https://xw.qq.com/cmsid/20210512A03DDN00

  1. 先添加SafeMath.sol计算方法
    在contracts目录同级创建library目录,在library目录中创建文件SafeMath.sol,内容如下
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.4;

library SafeMath {
    function mul(uint256 a, uint256 b) internal pure returns (uint256){
        uint256 c = a * b;
        assert(a == 0 || c / a == b);
        return c;
    }
 
    function div(uint256 a, uint256 b) internal pure returns (uint256){
        assert(b > 0);
        uint256 c = a / b;
        return c;
    }
 
    function sub(uint256 a, uint256 b) internal pure returns (uint256){
        assert(b <= a);
        return a - b;
    }
 
    function add(uint256 a, uint256 b) internal pure returns (uint256){
        uint256 c = a + b;
        assert(c >= a);
        return c;
    }
}
  1. 添加ERC20.sol代币标准接口
    在contracts目录同级创建library目录,在library目录中创建文件ERC20.sol,内容如下
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.4;

interface ERC20 {
    function totalSupply() external view returns (uint256);
    
    function balanceOf(address _owner) external view returns (uint256 balance);

    function transfer(address _to, uint256 _value)  external returns (bool success);

    function transferFrom(address _from, address _to, uint256 _value) external returns (bool success);

    function approve(address _spender  , uint256 _value) external returns (bool success);

    function allowance(address _owner, address _spender) external view returns (uint256 remaining);

    event Transfer(address indexed _from, address indexed _to, uint256 _value);
    event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}
  1. 添加Roles.sol合约权限管理,授权用户列表添加、移出等
    在contracts目录同级创建library目录,在library目录中创建文件Roles.sol,内容如下
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.4;

/**
 * @title Roles
 * @dev Library for managing addresses assigned to a Role.
 */
library Roles {
  struct Role {
    mapping (address => bool) bearer;
  }

  /**
   * @dev give an account access to this role
   */
  function add(Role storage role, address account) internal {
    require(account != address(0));
    role.bearer[account] = true;
  }

  /**
   * @dev remove an account's access to this role
   */
  function remove(Role storage role, address account) internal {
    require(account != address(0));
    role.bearer[account] = false;
  }

  /**
   * @dev check if an account has this role
   * @return bool
   */
  function has(Role storage role, address account)
    internal
    view
    returns (bool)
  {
    require(account != address(0));
    return role.bearer[account];
  }
}
  1. 添加Ownable.sol代币所有者权限管理合约,针对业务,管理业务的授权用户列表,判断是否有权限,业务授权方法等
    在contracts目录同级创建library目录,在library目录中创建文件Ownable.sol,内容如下
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.4;

import "./Roles.sol";

contract Ownable {
  using Roles for Roles.Role;

  event MinterAdded(address indexed account);
  event MinterRemoved(address indexed account);

  Roles.Role private minters;

  constructor() {
    minters.add(msg.sender);
  }

  modifier onlyMinter() {
    require(isMinter(msg.sender));
    _;
  }

  function isMinter(address account) public view returns (bool) {
    return minters.has(account);
  }

  function addMinter(address account) public onlyMinter {
    minters.add(account);
    emit MinterAdded(account);
  }

  function renounceMinter() public {
    minters.remove(msg.sender);
  }

  function _removeMinter(address account) internal {
    minters.remove(account);
    emit MinterRemoved(account);
  }
}
  1. 查看contracts目录,您应该能够找到 Greeter.sol,这是hardhat默认的示例,不修改可以直接进行下一步编译进行测试;本文需要自己写一个代币的合约,依赖于上方创建的内容,如下是我自己根据ERC20规范写的代币合约,代币名称PET,文件名TokenPET.sol,实现ERC20,放在contracts目录下

需要注意的是,发行的数量需要相对token小数点来设置。
例如如果token的小数点是0位,你要发行1000个token,那么发行数量_totalSupply的值是1000。
但是如果token的小数点是18位,你要发行1000个token,那么发行数量_totalSupply的值是1000000000000000000000(1000后面加上18个0)。

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.4;
import { SafeMath } from "../library/SafeMath.sol";
import { ERC20 } from "../library/ERC20.sol";

/// @title PET 私有区块链代币合约
/// @author Aubrey
/// @notice Explain to an end user what this does
/// @dev Explain to a developer any extra details
contract TokenPET is ERC20 {

  // 变量
  string private _name = 'PETurrency';
  string private _symbol = 'PET';
  // 8表示将令牌数量除以100000000得到其用户表示。
  uint8 private _decimals = 8;
  uint256 private _totalSupply;
  uint256 constant private MAX_UINT256 = 2**256 - 1;
  uint256 private maxMintBlock = 0;

  // 使用 SafeMath 函数库
  using SafeMath for uint256;
  // 类比二维数组
  mapping (address => mapping (address => uint256)) private allowed;
  // 类比一维数组
  mapping (address => uint256) private balances;

  // 令牌的名称
  function name() public view returns (string memory) {
    return _name;
  }
  // 令牌的符号
  function symbol() public view returns (string memory) {
    return _symbol;
  }
  // 令牌使用的小数位数 - 例如8,表示将令牌数量除以100000000得到其用户表示。 
  function decimals() public view returns (uint8) {
    return _decimals;
  }
  // 返回总代币供应量
  function totalSupply() public override view returns (uint256) {
    return _totalSupply;
  }
  // 获取账户余额
  function balanceOf(address _owner) public override view returns (uint256 balance) {
    return balances[_owner];
  }
  // 给账户转账
  function transfer(address _to, uint256 _value) public override returns (bool success) {
    assert(0 < _value);
    require(balances[msg.sender] >= _value);
    require(_to != address(0));
    balances[msg.sender] = balances[msg.sender].sub(_value);
    balances[_to] = balances[_to].add(_value);
    emit Transfer(msg.sender, _to, _value);
    return true;
  }
  // 从账户转账到账户 
  function transferFrom(address _from, address _to, uint256 _value) public override returns (bool success) {
    uint256 _allowance = allowed[_from][msg.sender];
    assert (balances[_from] >= _value);
    assert (_allowance >= _value);
    assert (_value > 0);
    require(_to != address(0));
    balances[_from] = balances[_from].sub(_value);
    balances[_to] = balances[_to].add(_value);
    allowed[_from][msg.sender] = _allowance.sub(_value);
    emit Transfer(_from, _to, _value);
    return true;
  }
  // 允许 _spender 多次取回您的帐户,最高达 _value 金额; 如果再次调用此函数,它将用 _value 的当前值覆盖的 allowance 值。
  function approve(address _spender, uint256 _value) public override returns (bool success) {
    require(_spender != address(0));
    require((_value == 0) || (allowed[msg.sender][_spender] == 0));
    allowed[msg.sender][_spender] = _value;
    emit Approval(msg.sender, _spender, _value);
    return true;
  }
  //  返回 _spender 仍然被允许从 _owner 提取的金额。
  function allowance(address _owner, address _spender) public override view returns (uint256 remaining) {
    return allowed[_owner][_spender];
  }

  // 内部方法 给地址 _to 初始化数量 _amount 数量的 tokens,注意 onlyOwner 修饰,只有合约创建者才有权限分配 分配会增加可发行总代币量,如果代币总量为0也可以增量发行
  function _mint(address _to, uint256 _amount) internal {
      require(_to != address(0));
      _totalSupply = _totalSupply.add(_amount);
      balances[_to] = balances[_to].add(_amount);
      emit Transfer(address(0), _to, _amount);
  }
  // 内部方法 销毁一定数量的令牌
  function _burn(address account, uint256 amount) internal {
    require(account != address(0));
    require(amount <= balances[account]);

    _totalSupply = _totalSupply.sub(amount);
    balances[account] = balances[account].sub(amount);
    emit Transfer(account, address(0), amount);
  }
  // 内部方法 从津贴中销毁一定数量的令牌
  function _burnFrom(address account, uint256 amount) internal {
    require(amount <= allowed[account][msg.sender]);

    // Should https://github.com/OpenZeppelin/zeppelin-solidity/issues/707 be accepted,
    // this function needs to emit an event with the updated approval.
    allowed[account][msg.sender] = allowed[account][msg.sender].sub(amount);
    _burn(account, amount);
  }

}

上方代码有三个内部方法,因为方法的操作内容比较敏感,所以控制为内部方法,然后使用权限控制调用是否允许,下面编写内部方法的对外调用接口

  1. 在contracts目录创建TokenPETMintable.sol代币合约文件,用来向外提供内部方法mint的鉴权调用,需要继承TokenPET、Ownable,根据Ownable的判断是否有权限调用内部方法或其他逻辑,之后的测试、部署都是基于该文件
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.4;
import { TokenPET } from "../contracts/TokenPET.sol";
import { Ownable } from "../library/Ownable.sol";

contract TokenPETMintable is TokenPET, Ownable {
event MintingFinished();

  bool private _mintingFinished = false;

  modifier onlyBeforeMintingFinished() {
    require(!_mintingFinished);
    _;
  }

  /**
   * @return true if the minting is finished.
   */
  function mintingFinished() public view returns(bool) {
    return _mintingFinished;
  }

  /**
   * @dev Function to mint tokens
   * @param to The address that will receive the minted tokens.
   * @param amount The amount of tokens to mint.
   * @return A boolean that indicates if the operation was successful.
   */
  function mint(
    address to,
    uint256 amount
  )
    public
    onlyMinter
    onlyBeforeMintingFinished
    returns (bool)
  {
    _mint(to, amount);
    return true;
  }

  /**
   * @dev Function to stop minting new tokens.
   * @return True if the operation was successful.
   */
  function finishMinting()
    public
    onlyMinter
    onlyBeforeMintingFinished
    returns (bool)
  {
    _mintingFinished = true;
    emit MintingFinished();
    return true;
  }

}

三、智能合约编译

  1. 运行npx hardhat compile编译合同
npx hardhat compile
---------------------
# 编译成功最后输出如下
> Compilation finished successfully

四、智能合约测试

  1. 测试合约,在test目录下,能够找到sample-test.js,如下图所示,这是默认的测试代码示例;可以按照该格式写测试代码,调用合同中的方法并输出log进行测试合同是否正常

在ETH网络上发布代币智能合约(在以太坊发行自己的币种)_第9张图片

  1. PET代币合约测试代码如下
const { expect } = require("chai");

// 这里的PET是测试实例名
describe("PET", function() {
  // 测试描述
  it("Should return the new PET once it's changed", async function() {
    // 获取编译的智能合约TokenPET,这个名是sol合约文件的类名,就是contracts后面的名字,不是文件名
    const TokenPET = await ethers.getContractFactory("TokenPET");
    const pet = await TokenPET.deploy();
    await pet.deployed();

    // 断言判断
    expect(await pet.name()).to.equal("PETurrency");
    expect(await pet.symbol()).to.equal("PET");
  });
});

  1. 编写好测试脚本之后,运行npx hardhat test即可看到输出
npx hardhat test
-------------------------
# 输出如下说明成功
  PET
    √ Should return the new PET once it's changed (166ms)


  1 passing (901ms)

五、智能合约部署(本地开发网络)

  1. 测试通过之后,进行合同的部署,在scripts目录里面你会发现sample-script.js,这是发布合约的示例,如图所示;可以按照该格式进行部署脚本的编写

在ETH网络上发布代币智能合约(在以太坊发行自己的币种)_第10张图片

  1. 如下是,我针对自己添加的智能合约的部署脚本pet-deploy-script.js,hre.ethers.getContractFactory的参数是合同名,就是智能合约代码中contracts后的名,不是合约文件名
const hre = require("hardhat");

async function main() {
  const TokenPET = await hre.ethers.getContractFactory("TokenPETMintable");
  const pet = await TokenPET.deploy();

  await pet.deployed();

  console.log("TokenPET symbol is:", await pet.symbol());
  console.log("TokenPET deployed to:", pet.address);
}

main()
  .then(() => process.exit(0))
  .catch(error => {
    console.error(error);
    process.exit(1);
  });

  1. 上文已经启动hardhat本地网络,现在发布合同到本地网络
# scripts/pet-deploy-script.js 为写好的部署合同脚本,想运行哪个执行哪个
# --network localhost 指发布到本地网络,之后讲发布到测试链或私链
npx hardhat run scripts/pet-deploy-script.js --network localhost
  1. 运行以上内容,输出如下,说明发布成功,这是本地发布,说明合约没有问题,才可以往线上的链发布
TokenPET symbol is: PET
TokenPET deployed to: 0x9fE46736679d2D9a65F0992F2……
  1. 到MetaMask中使用刚刚发布的代币,右上角选择本地网络然后点击下方“添加代币”使用合约
    在ETH网络上发布代币智能合约(在以太坊发行自己的币种)_第11张图片
  2. 填写代币信息,代币合约地址就是第4步TokenPET deployed to的地址,代币信息会自动显示,如果网络连接错误或地址填写错误是找不到合约地址的,也就不会自动显示下方的代币信息
    在ETH网络上发布代币智能合约(在以太坊发行自己的币种)_第12张图片
  3. 点击下一步,添加代币
    在ETH网络上发布代币智能合约(在以太坊发行自己的币种)_第13张图片
  4. 钱包中就可以使用该代币了
    在ETH网络上发布代币智能合约(在以太坊发行自己的币种)_第14张图片
  5. 调用合约中的mint方法,传入目标用户地址、代币数量,就可以给指定用户发币了(同时代币总量也会增加,相当于增量发行代币)pet-using.js
//初始化过程
var Web3 = require('web3');
var Contract = require('web3-eth-contract');

// 编译后的文件 自行定位文件修改路径
var TokenPETMintable = require("../artifacts/contracts/TokenPETMintable.sol/TokenPETMintable.json");
var abi = TokenPETMintable.abi;
// 发布后合约的地址
var address = '0xa85233C63b9Ee964Add6F2cffe00……';

// 合约发布的链网络
web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));

// 创建合同对象
var contract = new web3.eth.Contract(abi, address);

// 方法调用
contract.methods.totalSupply().call().then(function(totalSupply){
  console.log('totalSupply result', totalSupply) 
});

// 查询发币之前的账户余额 钱包中所选的创世用户也可以
contract.methods.balanceOf('0xf39Fd6e51aad88F6F4ce6aB88272……').call().then(function(balanceOf){
  console.log('Before balanceOf result', balanceOf) 
});

// 调用mint方法向账户发行代币
var mint = contract.methods.mint('0xf39Fd6e51aad88F6F4ce6aB88272……', 999);
// from需要是所有者,因为发布的时候没有选择用户,默认是创世用户第一个,才可以向想合约申请给用户发币
mint.send({from: '0xf39Fd6e51aad88F6F4ce6aB88272……'}).then(function(receipt){
// var result = mint.call().then(function(receipt) {
  console.log('call result', receipt) 
  // 查询发币之后的账户余额 钱包中所选的创世用户也可以
  contract.methods.balanceOf('0xf39Fd6e51aad88F6F4ce6aB88272……').call().then(function(balanceOf){
	console.log('After balanceOf result', balanceOf) 
  });
}).catch((error, receipt) => {
  console.error('error === ', error);
  process.exit(1);
});
  1. 执行合约调用
npx hardhat run .\scripts\pet-using.js
# Before balanceOf result 0
# call result中status: true则为交易成功
# After balanceOf result 999

到钱包中查看对应账户就有余额了
在ETH网络上发布代币智能合约(在以太坊发行自己的币种)_第15张图片

到此,您已经在本地创建了一个项目,运行了一个HardHat任务,开发、编译了一个智能合约,编写并运行了一个测试,并部署了一个合同,远程调用了已部署合约的方法,对合约及账户进行了操作。

下面说将该代币发布到私有、公开区块链网络。

六、智能合约部署(私有、公开区块链[主、测试]网络)

以下发布流程需要是本地测试、部署没有问题再进行,本文介绍的只是其中一种方式,并非唯一发布方式,使用其他方式的如果有疑问可以留言

  1. 访问合约发布网站myetherwallet(需要准备好前文说的MetaMask)

  2. 点击“Access my wallet”
    在ETH网络上发布代币智能合约(在以太坊发行自己的币种)_第16张图片

  3. 选择浏览器插件“Browser Extension”
    在ETH网络上发布代币智能合约(在以太坊发行自己的币种)_第17张图片

  4. 然后同意MetaMask授权
    我这授权过了,看不到效果了,授权后在MetaMask中可以查看已连接的网站
    在ETH网络上发布代币智能合约(在以太坊发行自己的币种)_第18张图片
    在ETH网络上发布代币智能合约(在以太坊发行自己的币种)_第19张图片

  5. 授权成功后,钱包管理网页应跳转至如下,这个页面左侧用户信息,注意要是私链或测试链中的用户地址信息,并且有一定的ETH,部署合约需要花费ETH,测试链可以在响应链的水龙头申请,然后之后的操作保证MetaMask选择用户是有ETH的这个用户
    在ETH网络上发布代币智能合约(在以太坊发行自己的币种)_第20张图片

  6. 选择发布合约
    在ETH网络上发布代币智能合约(在以太坊发行自己的币种)_第21张图片

  7. 填写构建的合约信息(构建流程见上文),查看artifacts->contracts->TokenPETMintable.sol->TokenPETMintable.json文件内容,按照下图对应关系填入
    在ETH网络上发布代币智能合约(在以太坊发行自己的币种)_第22张图片

  8. 点击Sign Transaction,点击confirm
    在ETH网络上发布代币智能合约(在以太坊发行自己的币种)_第23张图片

  9. 然后MetaMask会提示确认交易(需要由报酬,确认账户中有ETH,可以在水龙头申请一些ETH用来测试,否则个人的私网也没法处理本次工作,私链就自己发币就行了),点击确认,点击提交,在metamask 插件中或myetherwallet可以看到处理状态,然后等待交易完成
    在ETH网络上发布代币智能合约(在以太坊发行自己的币种)_第24张图片

  10. 查看钱包用户交易,可以看到合约部署的交易,myetherwallet网站中也可以查看该交易信息
    在这里插入图片描述

  11. 点击交易查看详情,可以跳转到以太坊区块链浏览器查看信息,如果是私链则线上的区块链浏览器无法查看,因为区块链浏览器没有你私链的连接信息和api(可能需要)
    在ETH网络上发布代币智能合约(在以太坊发行自己的币种)_第25张图片

  12. 交易中的To,就是发布到测试链中的合约地址
    在ETH网络上发布代币智能合约(在以太坊发行自己的币种)_第26张图片

  13. 查看链上合约的具体信息,点击To中的合约地址,查看合约信息
    在ETH网络上发布代币智能合约(在以太坊发行自己的币种)_第27张图片

  14. 在metamask连接私链或测试链,是刚刚发布代币的链就可以,选择添加代币,和之前说的添加本地网络代币步骤一样,就是代币合约地址使用上一步查看的合约地址,然后这里就多了另一个刚刚发布的币,可以进行交易

在ETH网络上发布代币智能合约(在以太坊发行自己的币种)_第28张图片

  1. 在私链或测试链发币(给用户发自己发行的币种)也可以用上面自己写脚本调用,这个网站只可以对测试链或可在公网访问的区块链操作,内部网络它也访问不到
    选择菜单Interact with Contract,在右侧填写要操作的合约地址,填写artifacts->contracts->TokenPETMintable.sol->TokenPETMintable.json文件的ABI内容(直接在第一行选择刚刚发布的合约,下面的内容一般会带出来)
    在ETH网络上发布代币智能合约(在以太坊发行自己的币种)_第29张图片
  2. 选择Mint方法,填写收款用户地址,发行代币数量,然后点击Write

在ETH网络上发布代币智能合约(在以太坊发行自己的币种)_第30张图片

  1. 同意交易

在ETH网络上发布代币智能合约(在以太坊发行自己的币种)_第31张图片
18. 交易成功后,到MetaMask查看用户的PET余额,可以看到已经有余额了,这里因为我设置的合约小数点为8位,所以交易金额都是以小数点后8位开始
在ETH网络上发布代币智能合约(在以太坊发行自己的币种)_第32张图片
在ETH网络上发布代币智能合约(在以太坊发行自己的币种)_第33张图片
GitHub源码参考:https://github.com/Aubrey-J/PET-ERC20

你可能感兴趣的:(学习笔记,ETH,ethernet,区块链,智能合约,web3)