创建 ERC-20 供应量

在本指南中,您将学习如何创建一个具有自定义供应机制的 ERC-20 token。我们将展示两种使用 OpenZeppelin Contracts 的惯用方法来实现此目的,您能够将这些方法运用到您的智能合约开发实践中。

构建在 Ethereum 上的 token 实现的标准接口称为 ERC-20,并且 Contracts 包含一个被广泛使用的实现:恰如其名的 ERC20 合约。这个合约,就像标准本身一样,非常简单和基础。事实上,如果您尝试按原样部署 ERC20 的实例,它将毫无用处…​…​它将没有供应量!一个没有供应量的 token 有什么用?

供应量的创建方式未在 ERC-20 文档中定义。每个 token 都可以自由地尝试其自己的机制,范围从最去中心化到最中心化,从最幼稚到最具研究性,以及更多。

固定供应量

假设我们想要一个固定供应量为 1000 的 token,最初分配给部署合约的帐户。如果您使用过 Contracts v1,您可能编写过如下代码:

contract ERC20FixedSupply is ERC20 {
    constructor() {
        totalSupply += 1000;
        balances[msg.sender] += 1000;
    }
}

从 Contracts v2 开始,这种模式不仅不鼓励,而且不允许。变量 totalSupplybalances 现在是 ERC20 的私有实现细节,您不能直接写入它们。相反,有一个内部 _mint 函数可以做到这一点:

contract ERC20FixedSupply is ERC20 {
    constructor() ERC20("Fixed", "FIX") {
        _mint(msg.sender, 1000);
    }
}

像这样封装状态可以更安全地扩展合约。例如,在第一个示例中,我们必须手动使 totalSupply 与修改后的余额保持同步,这很容易忘记。事实上,我们省略了一些也很容易忘记的东西:标准要求的 Transfer 事件,并且一些客户端依赖于此事件。第二个示例没有这个错误,因为内部 _mint 函数会处理它。

奖励矿工

内部 _mint 函数是关键的构建块,允许我们编写实现供应机制的 ERC-20 扩展。

我们将实现的机制是对生产 Ethereum 区块的矿工的 token 奖励。在 Solidity 中,我们可以访问全局变量 block.coinbase 中当前区块矿工的地址。每当有人在我们的 token 上调用函数 mintMinerReward() 时,我们将向该地址铸造 token 奖励。该机制听起来可能很愚蠢,但您永远不知道这会导致什么样的动态,并且值得分析和试验!

contract ERC20WithMinerReward is ERC20 {
    constructor() ERC20("Reward", "RWD") {}

    function mintMinerReward() public {
        _mint(block.coinbase, 1000);
    }
}

正如我们所看到的,_mint 使正确地执行此操作变得非常容易。

自动化奖励

到目前为止,我们的供应机制是手动触发的,但 ERC20 还允许我们通过 _update 函数扩展 token 的核心功能。

从上一节的供应机制中添加,我们可以使用此函数为区块链中包含的每个 token 转移铸造矿工奖励。

Unresolved include directive in modules/ROOT/pages/erc20-supply.adoc - include::api:example$ERC20WithAutoMinerReward.sol[]

总结

我们已经了解了如何实现 ERC-20 供应机制:通过内部的 _mint。希望这能帮助您了解如何使用 OpenZeppelin Contracts 以及它背后的一些设计原则,您可以将它们应用到您自己的智能合约中。