为什么ERC721的铸币功能有访问控制?

问题描述

我看到的大多数使用 Open Zeppelin 的 ERC721 示例都要求 mint 函数具有访问控制,其中仅允许合约所有者调用函数。对于example

function mint(address to) public virtual {
    require(hasRole(MINTER_ROLE,_msgSender()),"ERC721PresetMinterPauserAutoId: must have minter role to mint");

    _mint(to,_tokenIdTracker.current());
    _tokenIdTracker.increment();
}

或以下使用 Ownable 库。

function mint(address receiver) external onlyOwner returns (uint256) {
    _tokenIds.increment();

    uint256 newTokenId = _tokenIds.current();
    _mint(receiver,newTokenId);

    return newTokenId;
}

这是否意味着每次铸造新代币时都必须部署新合约?这不仅在gas费用方面似乎过高,而且ERC721合约还有properties用于映射不同的所有者和代币:

// Mapping from token ID to owner address
mapping (uint256 => address) private _owners;

// Mapping owner address to token count
mapping (address => uint256) private _balances;

如果铸造仅限于合同所有者,这将没有意义。

对我来说,部署单个 ERC721 contract(及其依赖项)并让用户调用 mint 函数更有意义。 ERC721的薄荷功能的最佳实践是什么?

解决方法

ERC-721 标准没有定义铸造新代币的“最佳”或“正确”方式(例如是否应该开放或限制),由每个合约开发者实施或省略铸造以反映他们需求的方式提供功能。

规范中不包括创建 NFT(“铸造”)和销毁 NFT(“燃烧”)。您的合同可以通过其他方式实施这些。请参阅事件文档了解您在创建或销毁 NFT 时的责任。

但是拥有一个被授权铸造新代币(例如 MINTER_ROLEonlyOwner)的地址白名单似乎比允许任何人自由铸造新代币更常见。


尽管理论上可以在每次铸造新代币时部署新合约,但这不是标准方法(而且我个人还没有看到任何合约这样做)。在大多数情况下,铸造过程“只是”创建一个新 ID,存储与 ID 关联的新字符串/URL 值,将此新令牌与所有者地址(令牌的,而不是合约所有者)相关联,并更新一些元数据,例如作为地址拥有的代币数量(参见下面的示例)。

然后,代币所有者可以转移他们的代币,让任何人控制他们的代币,并根据合约实施做其他事情。

您在问题中指出的映射(_owners_balances)表明它们存储代币所有者(而非合约所有者)地址以及每个地址持有的代币数量。>

示例:

  1. 合约所有者将代币 ID 1 铸造到地址 0x123

    • _owners[1] 的值为 0x123(为 0,默认值)

    • _balances[0x123] 的值变为 1(原为 0,默认值)

  2. 合约所有者将代币 ID 2 铸造到地址 0x123

    • _owners[1] 的值仍然是 0x123

    • _owners[2] 的值现在是 0x123(原为 0,默认值)

    • _balances[0x123] 的值变为 2(因为他们现在拥有 2 个代币)

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...