Skip to main content

使用 ERC-20 代币构建您自己的加密货币

在本分步教程中,您将学习如何在以太坊上创建和部署 ERC-20 令牌。

我们将在本教程中使用 Metamask 和 Remix IDE。

ERC 是 Ethereum Request for Comment 的缩写。从本质上讲,它们是已经被社区批准的标准,用于传达某些用例的技术要求和规范。

ERC-20 具体是一个标准,概述了可替换代币的技术规范。

可互换代币是指代币的所有 "部分 "都是相同的。将 1 个 ETH 换成另一个 1 个 ETH 并不会改变任何东西。你仍然拥有 1 个 ETH。因此,ETH 是一种可替代的代币。所有的法定货币也是可替换的。

NFT 是非可替代代币的例子(后面会详细介绍),每个代币都与不同的代币不同。

以太坊上的大多数代币都符合 ERC-20 规范。遵循像 ERC-20 这样的标准,使得使用 ERC-20 代币的应用开发者可以轻松地支持所有 ERC-20 代币,而不必为它们单独编写专门的代码。

例如,像 Uniswap 这样的去中心化交易所允许你将任何代币换成任何其他代币。这是唯一可能的,因为几乎所有的代币都遵循 ERC-20 标准,所以 Uniswap 可以编写代码,与所有遵循该标准的代币一起工作。

前提条件

一旦你把这些都设置好了,让我们开始吧!

编写代码

我们使用 Remix IDE 来编写智能合约。

在 Remix 中,创建一个新的合约文件,我把我的文件命名为 LW3Token.sol--你可以随心所欲地命名它

在合约中,写下以下代码。

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol";

contract LW3Token is ERC20 {
constructor(string memory _name, string memory _symbol) ERC20(_name, _symbol) {
_mint(msg.sender, 10 * 10 ** 18);
}
}

让我们把它逐行分解,了解发生了什么。

pragma solidity ^0.8.0;

这一行指定了要使用的 Solidity 的编译器版本。^0.8.0 表示任何大于 0.8.0 的版本。通常,你想使用最新的 Solidity 编译器版本,因为新的版本通常意味着新的特性或优化。

import "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol";

这一行从 OpenZeppelin(OZ)导入 ERC-20 代币标准。OZ 是一家以太坊安全公司。除其他外,OZ 为流行的智能合约标准开发参考合约,这些合约经过了全面的测试和安全。每当实施一个需要符合标准的智能合约时,尽量找一个 OZ 的参考实现,而不是从头开始重写整个标准。

如果你想看 ERC-20 标准合约的实现,可以通过以下链接查看 - https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol

注意:在大二的课程中,我们将深入研究 ERC-20 标准合约,了解该合约中的所有内容。

contract LW3Token is ERC20 {
...
}

这在我们的 Solidity 文件中指定了一个新合约,名为 LW3Token。同时,它说这个合约是 ERC20 的一个实例。ERC20 在这里指的是我们从 OpenZeppelin 导入的标准合约。

本质上,我们正在扩展我们从 OpenZeppelin 导入的 ERC20 标准合约。因此,所有内置于 ERC20 的功能和逻辑都可供我们使用,我们可以在上面添加我们自己的自定义逻辑。

如果你熟悉面向对象的编程原理,你可以把它看成是一个类对另一个类的扩展。

constructor(string memory _name, string memory _symbol) ERC20(_name, _symbol) {
...
}

这一点的语法稍微有点奇怪,你可能以前没有见过。Kotlin 其实也有一些类似的语法,但我想说的是。

基本上,我们创建了构造函数,在智能合约首次部署时被调用。在构造函数中,我们希望用户提供两个参数--_name 和_symbol,这两个参数指定了我们的加密货币的名称和符号。例如,名称=Ethereum,符号=ETH。

之后发生的事情就更有意思了。在指定构造函数后,我们立即调用 ERC20(_name, _symbol)。

我们从 OpenZeppelin 导入的 ERC20 合约有自己的构造函数,它需要名称和符号参数。由于我们正在扩展 ERC20 合约,我们需要在部署我们的合约时初始化 ERC20 合约。因此,作为我们构造函数的一部分,我们也需要调用 ERC20 合约的构造函数。

因此,我们要为我们的合约提供_name 和_symbol 变量,并立即将其传递给 ERC20 构造器,从而初始化 ERC20 智能合约。

_mint(msg.sender, 10 * 10 ** 18);

_mint 是 ERC20 标准合约中的一个内部函数,这意味着它只能由合约本身调用。外部用户不能调用这个函数。

由于你作为开发者想在部署这个合约时收到一些代币,所以我们调用_mint 函数来向 msg.sender 传递一些代币。

_mint 需要两个参数--一个要铸币的地址,以及要铸币的数量。

msg.sender 是一个由 Ethereum 虚拟机注入的全局变量,它是进行此次交易的地址。由于你将是部署这个合约的人,你的地址将出现在 msg.sender 中。

10 * 10 ** 18 指明您希望有 10 个完整的代币被铸造到您的地址。

注意:你可能想知道为什么我们不直接在金额中写 10,而要写 10 ** 18(实际上是 10 ^ 18)。

本质上,Solidity 不支持浮点数--也就是小数。另外,由于 ERC20 代币与货币打交道,使用浮点数字是个坏主意。

作为一个例子,考虑用支持浮点数的语言进行简单的计算(1/3)*3。你认为这会返回什么?

如果你认为它会返回 1,那你就错了。

由于浮点计算的不准确性,因为计算机不能表示无限的数字,(1/3) * 3实际上会产生类似 0.999999999 的结果。

因此,在表示金融货币时,由于计算误差,不使用小数。作为一种替代方法,我们将每种货币表示为相对于该货币的最小不可分割部分的金额。例如,1 美元被表示为 100 美分,因为在处理美元时,你不可能比 1 美分更小。在这个数字系统中,1 美分只是 1,而不是 0.01。0.33 美元被表示为 33,而不是(1/3)

ERC20 代币默认以 18 位小数工作。因此,在这种情况下,1 个完整的 LW3Token 实际上表示为 10 ^ 18。因此,为了得到 10 个完整的 LW3 代币,我们使用10 * 10 ** 18

编译

编译合约的方法是:按 "保存 "键(Windows 上的 CTRL + S,Mac 上的 Command + S),或者到 Remix 的编译器标签,选择 LW3Token.sol,然后点击编译。

部署

进入 Remix 的 Deployer 选项卡。

选择 Injected Web3 环境(确保你在 Goerli 测试网络上),并连接你的 Metamask 钱包。

选择 LW3Token.sol 合约,并输入构造参数_name 和_symbol 的值。

点击交易并批准来自 Metamask 的交易,以部署你的合约!

部署后,合约应该显示在已部署的合约部分。点击复制地址按钮来复制合约地址。

进入 Goerli Etherscan,搜索您的合约地址,您应该可以看到它。

把它截图并分享到 Discord 上,以炫耀你新创建的代币 :D

在 Metamask 中查看代币

你可能会注意到,即使你向你的地址铸造了代币,它们也没有在 Metamask 中显示出来。

这是因为 Metamask 无法检测到随机的 ERC20 代币余额(因为有成百上千的代币)。他们有一个最知名的 ERC20 代币的列表,可以自动显示,但除此之外,对于你自己的代币,你通常需要告诉 Metamask 手动将其添加到你的钱包。

要做到这一点。

复制你的合约地址

打开 Metamask,点击资产标签中的导入代币 输入你的代币合约地址,它应该自动检测名称和小数点的数量 点击添加,你将在 Metamask 中看到你的余额!

恭喜你!你已经成功地部署和铸造了代币。你已经成功部署并铸造了你自己的 ERC20 代币! 从这里开始,继续前进