这段时间以来,以太坊通证很流行。这些通证可以用来代表现实世界的各种价值单位:黄金、 谎言、 猫咪 甚至是类似 公司股票 一样的东西。迄今为止,人们已经募集了 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 中得到我们的私钥:
- 点击你的 Chrome 窗口右上角的狐狸图标。
- 点击 “Account 1” 右侧的省略号。
- 点击 “Export Private Key”。
- 输入你的密码。
- 点击该文字以复制私钥到剪贴板。
然后打开 .env
文件,并像下面这样贴入你的私钥(对于 Ropsten 测试网和 Mainnet 主网,你的私钥是一样的):
ROPSTEN_PRIVATE_KEY="123YourPrivateKeyHere"
MAINNET_PRIVATE_KEY="123YourPrivateKeyHere"
接下来,让我们部署到 Ropsten 以太坊测试网。
以太坊测试网是一个你可以测试合约的地方。此外还有 Kovan 和 Rinkeby 测试网。我在这个教程中选择 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 兼容的钱包,如 Mist 、MyEtherWallet(LCTT 译注:或 ImToken 这样的手机应用)里面使用你的通证了。
为了这篇教程,我构建了一个名为 Etherface 的钱包来做演示。
首先你需要添加你的通证到 Etherface:
- 访问 http://etherface.io/ 。
- 确认你在 Metamask 中选择了 “Ropsten” 网络。
- 点击 “Tokens”。
- 点击右上角的加号按钮。
- 输入上面的合约地址。
如果你有朋友想要一些汉堡币,你现在就可以发送给他们了。如果没有,你也可以在你的两个账号间测试转账:
- 在 Metamask 中点击 “切换账号”按钮(在右上角),并改变你的账号为 “Account 2”。
- 点击 “Account 2” 右边的省略号,然后选择 “Copy Address to clipboard”。
- 切换回 “Account 1”,这很重要!否则交易会失败。
- 在 Etherface 中你的余额下点击 “Send”。
- 黏贴 “Account 2” 的地址。
- 输入你要发送的数量。
- Metamask 会弹出确认窗口,点击 “Submit”。
- 等大约 15-30 秒。
- 你的 “Account 1” 的余额应该会减少,“Account 2” 现在会有了一些汉堡币!
最后,让我们来部署到主网(LCTT 译注:这会花费你真实的 ETH,你可以通过查看前面部署到 Ropsten 的合约信息中了解花费了多少 gas,以相应估计实际要花费多少 ETH):
$ truffle deploy --network mainnet
你可以如前面一样加你的通证到 Etherface ,并发送你新打造的通证给你的朋友们了!
发表回复