Mason 发布的文章

这段时间以来,以太坊通证很流行。这些通证可以用来代表现实世界的各种价值单位:黄金谎言猫咪 甚至是类似 公司股票 一样的东西。迄今为止,人们已经募集了 20 亿美元的通证。那些通证是以 ERC20 为标准的,人们可以轻松地在钱包之间进行交易。在这篇教程中,我准备指导你部署你自己的 ERC20 通证到真实的以太坊网络上去。

事先准备:

  • 一个文本编辑器(Atom 不错,不过我喜欢 Vim
  • 对命令行和终端(模拟器)有起码的了解。Mac 内置的应用“终端”就很好,不过我喜欢 iTerm2
  • Chrome 浏览器
  • Node.js 8(或更高版本)
  • 你的通证的名字。我的准备叫做 HamburgerCoin(汉堡币)

你需要做的第一件事是安装 MetaMask。访问 Metamask 网站 并点击“Get Chrome Extention”。

Metamask 可以让你通过 Chrome 在以太坊上进行交易。它依靠运行着公开以太坊节点的 Infura ,所以你不用自己运行以太坊全节点。如果你颇具探索精神,你也可以下载和安装 Mist 以替代它。运行 Mist 就可以让你运行你自己的以太坊节点。运行自己的节点你就需要将你的计算机与该网络进行同步,这需要不短的时间。从技术上讲这更安全,因为这样你不必信任 Infura 来处理你的交易。Infura 可以忽略你的交易而干预你,但是它并不能偷走你的钱。因为安装 Metamask 比 Mist 更快也更简单,所以我假设你在下面的教程中使用 Metamask。

接着你需要安装 truffle

 $ npm install -g truffle

现在为你自己的新通证创建一个新目录,cd 到其中并初始化你的 truffle 项目。

$ mkdir hamburger-coin
$ cd hamburger-coin
$ truffle init

很好,你的 truffle 项目已经设置好了!

现在来创建我们的通证。首先我们需要安装 OpenZepplin 框架。OpenZepplin 框架包括了大量预先构建好的合约,包括我们要部署的 ERC20 通证合约。

(只需要按下回车接受默认值即可)

$ npm init
package name: (hamburger-coin)
version: (1.0.0)
description:
entry point: (truffle.js)
test command:
git repository:
keywords:
author:
license: (ISC)
About to write to /Users/masonf/src/hamburger-coin/package.json:

{
  "name": "hamburger-coin",
  "version": "1.0.0",
  "description": "",
  "main": "truffle.js",
  "directories": {
    "test": "test"
  },
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}


Is this ok? (yes) yes
$ npm install zeppelin-solidity

现在我们可以创建我们的通证合约了。创建一个 contracts/HamburgerCoin.sol 文件并加入如下内容:

pragma solidity ^0.4.18;
import "zeppelin-solidity/contracts/token/StandardToken.sol";

contract HamburgerCoin is StandardToken {
  string public name = "HamburgerCoin"; 
  string public symbol = "HBC";
  uint public decimals = 2;
  uint public INITIAL_SUPPLY = 10000 * (10 ** decimals);

  function HamburgerCoin() public {
    totalSupply_ = INITIAL_SUPPLY;
    balances[msg.sender] = INITIAL_SUPPLY;
  }
}

(LCTT 译注:上述合约内容中指定了合约的名称、符号和供应量。在 ERC20 当中,通证的供应量其实是整数,上述合约中通证的实际供应量是 10000 * 100 个,出于显示 2 位小数的需求,你在合约浏览器、钱包软件中看到和操作的 1 个通证,实际上在交易中是以 100 个进行的。)

OpenZepplin 的 StandardToken 是一个标准的 ERC20 通证。如果你感兴趣,你可以看看它的 源代码 以了解是如何工作的。

实际上并不太复杂。该合约有一个 地址到余额 的映射(LCTT 译注:你可以理解为哈希、关联数组),它也有一个 允许转账 的列表。你可以看做是支票。你可以写张支票,但是直到它被兑付前,钱并不会被转账。

如果有人要转走一些资金,你可以在合约上调用 approve 方法,设置你要发送的通证数量。这就像是写支票一样。

然后调用 transferFrom 会实际进行转账。

我们可以从头写这些合约,但是最好采用经过完备的社区测试的合约。从头写一个 ERC20 通证那就是另外一篇文章了。

试着运行 compile 来编译我们的合约:

$ truffle compile
Compiling ./contracts/HamburgerCoin.sol...
Compiling zeppelin-solidity/contracts/math/SafeMath.sol...
Compiling zeppelin-solidity/contracts/ownership/Ownable.sol...
Compiling zeppelin-solidity/contracts/token/BasicToken.sol...
Compiling zeppelin-solidity/contracts/token/ERC20.sol...
Compiling zeppelin-solidity/contracts/token/ERC20Basic.sol...
Compiling zeppelin-solidity/contracts/token/MintableToken.sol...
Compiling zeppelin-solidity/contracts/token/StandardToken.sol...
Writing artifacts to ./build/contracts Next you'll need to add a migration file which will tell truffle how to deploy your contract.

接下来我们需要增加一个 truffle 迁移

创建 migrations/2_deploy_hamburgercoin.js 文件并添加如下内容:

var HamburgerCoin = artifacts.require("./HamburgerCoin.sol");

module.exports = function(deployer) {
  deployer.deploy(HamburgerCoin);
};

现在让我们配置 truffle 以能够使用 Infura 公共节点。如果我们要部署到公共节点,那就需要钱包的私钥。我们可以将该私钥包含在我们的源代码当中,但是如果任何人可以访问你的源代码(和版本库),他就能够偷走我们所有的汉堡币!要避免这种情况,我们会使用 dotenv node.js 模块。(LCTT 译注:dotenv 用于存储机密信息的文件 .env 是以 “.” 开头的,默认不会进入版本库,当然,如果有人能查看你全部的项目文件,你的私钥还是会被泄露。)

让我们安装部署到 Infura 所需的所有模块。

npm install --save-dev dotenv truffle-wallet-provider ethereumjs-wallet

(LCTT 译注:可能安装过程中会有很多警告,大多应该是属于定义了未使用的变量和方法的编译警告,可以忽略。)

现在编辑 truffle.js 并(原样)加入如下内容:

require('dotenv').config();
const Web3 = require("web3");
const web3 = new Web3();
const WalletProvider = require("truffle-wallet-provider");
const Wallet = require('ethereumjs-wallet');

var mainNetPrivateKey = Buffer.from(process.env["MAINNET_PRIVATE_KEY"], "hex")
var mainNetWallet = Wallet.fromPrivateKey(mainNetPrivateKey);
var mainNetProvider = new WalletProvider(mainNetWallet, "https://mainnet.infura.io/");

var ropstenPrivateKey = Buffer.from(process.env["ROPSTEN_PRIVATE_KEY"], "hex")
var ropstenWallet = Wallet.fromPrivateKey(ropstenPrivateKey);
var ropstenProvider = new WalletProvider(ropstenWallet, "https://ropsten.infura.io/");


module.exports = {
  networks: {
    development: {
      host: "localhost",
      port: 8545,
      network_id: "*" // Match any network id
    },
    ropsten: {
      provider: ropstenProvider,
      // You can get the current gasLimit by running
      // truffle deploy --network rinkeby
      // truffle(rinkeby)> web3.eth.getBlock("pending", (error, result) =>
      //   console.log(result.gasLimit))
      gas: 4600000,
      gasPrice: web3.toWei("20", "gwei"),
      network_id: "3",
    },
    mainnet: {
      provider: mainNetProvider,
      gas: 4600000,
      gasPrice: web3.toWei("20", "gwei"),
      network_id: "1",
    }
  }
};

(LCTT 译注:原文采用 new Buffer 来获取私钥设置,但 node.js 升级后,废弃了 new Buffer 这种用法,运行时会发出警告,所以上面我修改为使用 Buffer.from 。)

接下来我们从 Metamask 中得到我们的私钥:

  1. 点击你的 Chrome 窗口右上角的狐狸图标。
  2. 点击 “Account 1” 右侧的省略号。
  3. 点击 “Export Private Key”。
  4. 输入你的密码。
  5. 点击该文字以复制私钥到剪贴板。

然后打开 .env文件,并像下面这样贴入你的私钥(对于 Ropsten 测试网和 Mainnet 主网,你的私钥是一样的):

ROPSTEN_PRIVATE_KEY="123YourPrivateKeyHere"
MAINNET_PRIVATE_KEY="123YourPrivateKeyHere"

接下来,让我们部署到 Ropsten 以太坊测试网。

以太坊测试网是一个你可以测试合约的地方。此外还有 KovanRinkeby 测试网。我在这个教程中选择 Ropsten 是因为现在很容易得到 Ropsten 的测试 ETH。这些测试网都类似,你可以使用任何一个你喜欢的,但是在此教程当中我假设你在使用 Ropsten。访问 https://faucet.metamask.io/ 以得到一些测试 ETH。从 faucet 得到一些 ETH 后,你就可以部署了。

$ truffle deploy --network ropsten
Compiling ./contracts/HamburgerCoin.sol...
Compiling ./contracts/Migrations.sol...
Compiling zeppelin-solidity/contracts/math/SafeMath.sol...
Compiling zeppelin-solidity/contracts/token/BasicToken.sol...
Compiling zeppelin-solidity/contracts/token/ERC20.sol...
Compiling zeppelin-solidity/contracts/token/ERC20Basic.sol...
Compiling zeppelin-solidity/contracts/token/StandardToken.sol...
Writing artifacts to ./build/contracts

Using network 'ropsten'.

Running migration: 1_initial_migration.js
  Deploying Migrations...
  ... 0xc2bbe6bf5a7c7c7312c43d65de4c18c51c4d620d5bf51481ea530411dcebc499
  Migrations: 0xd827b6f93fcb50631edc4cf8e293159f0c056538
Saving successful migration to network...
  ... 0xe6f92402e6ca0b1d615a310751568219f66b9d78b80a37c6d92ca59af26cf475
Saving artifacts...
Running migration: 2_deploy_contracts.js
  Deploying HamburgerCoin...
  ... 0x02c4d47526772dc524851fc2180b338a6b037500ab298fa2f405f01abdee21c4
  HamburgerCoin: 0x973b1a5c753a2d5d3924dfb66028b975e7ccca51
Saving artifacts...

在 “Saving aritfacts” 上面的这行即是你的合约的新地址。

复制并黏贴该地址到 Ropsten Etherscan 搜索框,你就能看到你新部署的合约。

现在你可以在任何 ERC20 兼容的钱包,如 MistMyEtherWallet(LCTT 译注:或 ImToken 这样的手机应用)里面使用你的通证了。

为了这篇教程,我构建了一个名为 Etherface 的钱包来做演示。

首先你需要添加你的通证到 Etherface:

  1. 访问 http://etherface.io/
  2. 确认你在 Metamask 中选择了 “Ropsten” 网络。
  3. 点击 “Tokens”。
  4. 点击右上角的加号按钮。
  5. 输入上面的合约地址。

如果你有朋友想要一些汉堡币,你现在就可以发送给他们了。如果没有,你也可以在你的两个账号间测试转账:

  1. 在 Metamask 中点击 “切换账号”按钮(在右上角),并改变你的账号为 “Account 2”。
  2. 点击 “Account 2” 右边的省略号,然后选择 “Copy Address to clipboard”。
  3. 切换回 “Account 1”,这很重要!否则交易会失败。
  4. 在 Etherface 中你的余额下点击 “Send”。
  5. 黏贴 “Account 2” 的地址。
  6. 输入你要发送的数量。
  7. Metamask 会弹出确认窗口,点击 “Submit”。
  8. 等大约 15-30 秒。
  9. 你的 “Account 1” 的余额应该会减少,“Account 2” 现在会有了一些汉堡币!

最后,让我们来部署到主网(LCTT 译注:这会花费你真实的 ETH,你可以通过查看前面部署到 Ropsten 的合约信息中了解花费了多少 gas,以相应估计实际要花费多少 ETH):

$ truffle deploy --network mainnet

你可以如前面一样加你的通证到 Etherface ,并发送你新打造的通证给你的朋友们了!