创建 ERC20 供应 - OpenZeppelin 文档

本文介绍了如何使用 OpenZeppelin Contracts 创建具有自定义供应机制的 ERC20 代币。

你没有在阅读本文档的当前版本。5.x 是当前版本。

创建 ERC20 供应量

在本指南中,你将学习如何创建一个具有自定义供应机制的 ERC20 代币。我们将展示两种使用 OpenZeppelin Contracts 的惯用方法来实现此目的,你可以将其应用于你的智能合约开发实践。

以太坊上构建的代币实现的标准接口称为 ERC20,Contracts 包含了一个被广泛使用的实现:名为 ERC20 的合约。这个合约,就像标准本身一样,非常简单和基础。实际上,如果你尝试按原样部署 ERC20 的实例,它将毫无用处…… 它将没有供应量!一个没有供应量的代币有什么用?

供应量的创建方式未在 ERC20 文档中定义。每个代币都可以自由地尝试自己的机制,从最去中心化到最中心化,从最幼稚到最具研究性,等等。

固定供应量

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

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

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

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

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

奖励矿工

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

我们将实现的机制是为生产以太坊区块的矿工提供的代币奖励。在 Solidity 中,我们可以访问当前区块的矿工地址,该地址位于全局变量 block.coinbase 中。每当有人在我们的代币上调用函数 mintMinerReward() 时,我们将向该地址薄荷代币奖励。该机制听起来可能很傻,但你永远不知道这可能会导致什么样的动态,值得分析和实验!

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

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

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

模块化机制

Contracts 中已经包含一种供应机制:ERC20PresetMinterPauser。这是一种通用机制,其中一组帐户被分配 minter 角色,授予他们调用 mint 函数的权限,这是 _mint 的外部版本。

这可以用于中心化铸币,其中外部拥有的帐户(即,拥有加密密钥对的人)决定创建多少供应量以及为谁创建。这种机制有非常合理的用例,例如 传统资产支持的稳定币

但是,具有 minter 角色的帐户不必是外部拥有的,也可以是实现无需信任机制的智能合约。实际上,我们可以实现与上一节相同的行为。

contract MinerRewardMinter {
    ERC20PresetMinterPauser _token;

    constructor(ERC20PresetMinterPauser token) public {
        _token = token;
    }

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

当使用 ERC20PresetMinterPauser 实例初始化,且被授予该合约的 minter 角色时,此合约将产生与上一节中实现的完全相同的行为。使用 ERC20PresetMinterPauser 的有趣之处在于,我们可以通过将角色分配给多个合约来轻松组合多个供应机制,而且我们可以动态地执行此操作。

要了解有关角色和权限系统的更多信息,请访问我们的 访问控制指南

自动化奖励

到目前为止,我们的供应机制是手动触发的,但是 ERC20 还允许我们通过 _beforeTokenTransfer Hook扩展代币的核心功能(请参阅 使用Hook)。

从前面的章节中添加到供应机制,我们可以使用此Hook为区块链中包含的每个代币转账铸造矿工奖励。

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

    function _mintMinerReward() internal {
        _mint(block.coinbase, 1000);
    }

    function _beforeTokenTransfer(address from, address to, uint256 value) internal virtual override {
        _mintMinerReward();
        super._beforeTokenTransfer(from, to, value);
    }
}

总结

我们已经看到了两种实现 ERC20 供应机制的方法:通过 _mint 在内部实现,以及通过 ERC20PresetMinterPauser 在外部实现。希望这有助于你了解如何使用 OpenZeppelin 及其背后的一些设计原则,你可以将它们应用于你自己的智能合约。

← ERC20

ERC721 →

  • 原文链接: docs.openzeppelin.com/co...
  • 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
OpenZeppelin
OpenZeppelin
江湖只有他的大名,没有他的介绍。