# ERC721

GMLayer ERC721 预设合约是GMLayer ERC721 基础合约的扩展，包含使用两种高效方法中的一种来铸造代币批次的功能。这是GMLayer 推荐用于游戏开发的预设合约

***

| 主要功能                                                                                 | 建议用途                                             |
| ------------------------------------------------------------------------------------ | ------------------------------------------------ |
| <ul><li>造币</li><li>元数据 设置和审讯</li><li>特许权使用费计算和链上特许权使用费执行</li><li>基于角色的受限功能</li></ul> | <ul><li>在GMLayer zkEVM 上启动您的 ERC721 集合</li></ul> |

### 安装、使用和部署[​](https://docs.immutable.com/docs/zkEVM/products/contracts/erc721#installation-usage-and-deployment) <a href="#installation-usage-and-deployment" id="installation-usage-and-deployment"></a>

#### 安装[​](https://docs.immutable.com/docs/zkEVM/products/contracts/erc721#installation) <a href="#installation" id="installation"></a>

预设合同包含在 **合同**库中，可通过该库轻松添加到项目中：

```
npm install @imtbl/contracts
```

我们建议使用Hardhat或Foundry等现有框架，以便从头开始建立自己的智能合约开发环境。

#### 使用方法[​](https://docs.immutable.com/docs/zkEVM/products/contracts/erc721#usage) <a href="#usage" id="usage"></a>

合同库可用于

* 使用GMLayer 的预设之一开发和部署自己的智能合约
* 使用Typescript 客户端与已部署的GMLayer 预设合同进行交互

**智能合约开发**[**​**](https://docs.immutable.com/docs/zkEVM/products/contracts/erc721#smart-contract-development)

```
pragma solidity ^0.8.19;
import '@imtbl/contracts/contracts/token/erc721/preset/GMLayerERC721.sol';

contract MyERC721 is GMLayerERC721 {
    constructor(
        address owner,
        string memory name,
        string memory symbol,
        string memory baseURI,
        string memory contractURI,
        address royaltyAllowlist,
        address _receiver,
        uint96 _feeNumerator
    )
        GMLayerERC721(
            owner,
            name,
            symbol,
            baseURI,
            contractURI,
            royaltyAllowlist,
            _receiver,
            _feeNumerator
        )
    {}
}
```

**Typescript 客户**[**​**](https://docs.immutable.com/docs/zkEVM/products/contracts/erc721#typescript-client)

`@imtbl/contracts` Typescript 客户端，可用于与已部署的 `ERC721 Preset` 合同：

```
import { ERC721Client } from '@imtbl/contracts';

const contractAddress = 'YOUR_CONTRACT_ADDRESS';

const client = new ERC721Client(contractAddress);

...

const mintTransaction = await client.populateMintByQuantity(receiver, 10);
const tx = await signer.sendTransaction(mintTransaction);
```

默认情况下，在 `ERC721Client` 已经 根据网络结构配置燃料费 。

#### 部署[​](https://docs.immutable.com/docs/zkEVM/products/contracts/erc721#deployment) <a href="#deployment" id="deployment"></a>

要在GMLayer zkEVM 上部署智能合约，请参阅部署智能合约快速入门指南。

#### 配置硬头盔[​](https://docs.immutable.com/docs/zkEVM/products/contracts/erc721#configure-hardhat) <a href="#configure-hardhat" id="configure-hardhat"></a>

更新项目的 `hardhat.config.js/ts` 文件，其中包含以下代码。 该文件位于智能合约存储库中。

```
solidity: {
    version: "0.8.17",
    settings: {
      optimizer: {
        enabled: true,
        runs: 200,
      },
    },
  },

```

### 功能和设计[​](https://docs.immutable.com/docs/zkEVM/products/contracts/erc721#functionality-and-design) <a href="#functionality-and-design" id="functionality-and-design"></a>

虽然合约包含推荐的功能，但也可以根据开发者的需求进行扩展或重构。需要注意的是，扩展功能可能会在智能合约中引入漏洞，因此应小心谨慎。

### 功能性[​](https://docs.immutable.com/docs/zkEVM/products/contracts/erc721#functionality) <a href="#functionality" id="functionality"></a>

#### 造币[​](https://docs.immutable.com/docs/zkEVM/products/contracts/erc721#minting) <a href="#minting" id="minting"></a>

铸造 ERC721NFT (非同质化通证) 会在区块链上创建一个特定于合约的唯一资产。预设使用两种方法之一来铸造代币：

* 按数量铸造时，合约使用 ERC721Psi 方法来高效地铸造多个代币。该方法从ERC721Psi 方法返回的值开始铸造代币。 `bulkMintThreshold`可以通过子类化预设来重写。
* 通过 ID 造币时，合约使用内部 ERC721 `_mint` 功能。以这种方式铸造的代币所指定的 ID 必须小于 `bulkMintTreshold`.

默认情况下 `bulkMintThreshold` 返回值 `2 ** 128`或 `340282366920938463463374607431768211456`.

这两种方法都是经过许可的。括号内的内容为"..."。 `mint` 函数允许拥有矿工角色的用户向指定地址铸造一定数量的代币（有关权限的详细信息，请参阅下面的访问控制部分）。

#### 销毁[​](https://docs.immutable.com/docs/zkEVM/products/contracts/erc721#burning) <a href="#burning" id="burning"></a>

销毁 销毁 ERC721NFT (非同质化通证) 。

#### 批量铸币和焚烧[​](https://docs.immutable.com/docs/zkEVM/products/contracts/erc721#batch-minting-and-burning) <a href="#batch-minting-and-burning" id="batch-minting-and-burning"></a>

预设合约提供了几种有效铸造和烧毁代币的方法：

* `mintBatch`：用调用者指定的 ID 生成一批令牌
* `mintBatchByQuantity`代币：铸造一批具有顺序 ID 的代币
* `burnBatch`：销毁 一批令牌，指定每个令牌的 ID。

#### 安全铸币和焚烧[​](https://docs.immutable.com/docs/zkEVM/products/contracts/erc721#safe-minting-and-burning) <a href="#safe-minting-and-burning" id="safe-minting-and-burning"></a>

ERC721 预设合约包括所有铸币和焚烧方法的安全版本。这些方法需要额外费用燃料费 ，但会执行额外检查以确保操作安全：

#### 元数据[​](https://docs.immutable.com/docs/zkEVM/products/contracts/erc721#metadata) <a href="#metadata" id="metadata"></a>

元数据 是NFT (非同质化通证) 集合的组成部分，定义了其独特的属性和效用；集合所有者定义了这些数据。集合中的元数据 通过其通用资源标识符（URI）进行引用。元数据 源可存储在链上或链下，支持不同的模式。

元数据 可能是一个易变对象，经常由集合所有者更新。这可能与数据集的具体用途或机制有关，并意味着与数据集集成的服务需要在其系统中拥有最新的元数据 。

GMLayer 预设合约支持令牌和集合级别的元数据 。基础 URI 和合约 URI 在预设的构造函数中设置，预设还提供了更新这些内容的函数。

**类型**[**​**](https://docs.immutable.com/docs/zkEVM/products/contracts/erc721#types)

在 ERC721 数据集中有三个规范元数据 URI：

1. **基本 URI**：单一的元数据 URI，是所有令牌 ID 的公分母
2. **令牌 URI**：元数据 URI 专用于单个令牌 ID
3. **合同 URI**：适用于整个集合的单个元数据 URI。例如，市场用于提供店面信息

**存储**[**​**](https://docs.immutable.com/docs/zkEVM/products/contracts/erc721#storage)

在链外存储元数据 意味着数据存储在合约存储之外的链外位置。指向链外元数据 源的指针存储在合约存储区内。

在链上存储元数据 意味着数据存储在合约的存储空间内。链上元数据 的格式通常是 JSON 格式，但并不总是如此，集成系统应对此进行相应处理。

链上元数据 仍是一种模式，在生态系统中的应用不如链下元数据 广泛，因此支持和工具较少（以及燃料费 成本增加），缺乏链下存储所能提供的丰富性。因此，建议采用链外元数据 存储。

**模式**[**​**](https://docs.immutable.com/docs/zkEVM/products/contracts/erc721#schemas)

元数据 模式提供了一个标准，使与您的 ERC721 合约集成的应用程序能够知道预期返回的元数据 是什么，以及如何解释它。OpenSea 的元数据 模式是根据官方的 ERC721元数据 标准构建的，是社区采用最多的模式，用于在生态系统内定义和理解元数据 ，支持链上和链下元数据 。该模式可在[此处](https://docs.opensea.io/docs/metadata-standards#metadata-structure)找到。因此，在定义元数据 时，推荐使用该模式（这适用于集合 URI 和令牌 URI 的模式）。

OpenSea 模式使用的格式是 JSON。示例如下：

```
{
  "description": "" 
  "external_url": "", 
  "image": "", 
  "name": "",
  "attributes": []
}
```

**特质**[**​**](https://docs.immutable.com/docs/zkEVM/products/contracts/erc721#traits)

OpenSea 使用的模式支持属性，允许创建者提供有关其 NFT 的附加信息。在这些属性中，特质允许您 描述NFT (非同质化通证) 的属性以及显示格式。三种不同的属性类型分别是数字、日期和字符串。例如，可以使用这些特质对英雄NFT (非同质化通证) 进行如下描述：

```
{
"attributes": [
    {
      "trait_type": "Hero", 
      "value": "Fighter"
    }, 
    {
      "display_type": "number", 
      "trait_type": "Strength", 
      "value": 2
    }
  ]
}
```

有关在元数据 中使用属性及其特征的更多信息，请参阅此处。

#### 门禁控制[​](https://docs.immutable.com/docs/zkEVM/products/contracts/erc721#access-control) <a href="#access-control" id="access-control"></a>

预设合约继承了 OpenZeppelin 的 AccessControl 模块，该模块允许您 为铸币等特定功能定义基于角色的访问修改器。

访问控制定义了联系人内部角色的本体。 角色是一个结构，包含成员列表和定义的管理员角色，该结构中的每个成员都具有管理员角色。有关访问控制的更多信息，请参阅 OpenZeppelin 文档[。](https://docs.openzeppelin.com/contracts/2.x/access-control#role-based-access-control)

修改器 `onlyRole()` 用于限制该角色的管理员使用功能。例如，只有具有 `MINTER` 角色可执行功能 `mint`.......。 `DEFAULT_ADMIN_ROLE` 是预设中的另一个角色，其功能受到限制。这些功能包括

1. `setBaseURI` 允许管理员更新基本 URI。
2. `setContractURI` 允许管理员更新合同 URI。
3. `grantMinterRole` 允许管理员授予 `MINTER` 用户的角色。
4. `transferOwnership` 允许管理员在合同中设置新的所有者。

所有者的本体在预设合同中，用于显示目的（例如，交易市场 店面通常会显示元数据 藏品的相关信息，如合同所有者标示的藏品所有者）。所有者是在合同部署时设置的，与为 `DEFAULT_ADMIN_ROLE`.所有权可以转让给其他地址，只要他们是本组织的成员。 `DEFAULT_ADMIN_ROLE`.请注意，此实现并非 OpenZeppelin 的 Ownable 标准。

### 界面[​](https://docs.immutable.com/docs/zkEVM/products/contracts/erc721#interface) <a href="#interface" id="interface"></a>

| 功能                                   | 说明                                                                                                                                                              |
| ------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| grantMinterRole(user)                | 授予用户矿工角色，仅限管理员使用                                                                                                                                                |
| mint(to,tokenId)                     | 允许矿工角色铸造 ID 为 `tokenId` 至 `to`                                                                                                                                  |
| mintBatch(idMints\[])                | 允许 "挖矿者 "角色以指定的 ID（"ID"）铸造一批代币。`idMints.tokenIds`）发送到一批指定的钱包 (`idMints.to`)                                                                                     |
| mintByQuantity(to, quantity) (按数量交货) | 允许矿工角色向指定钱包铸造一定数量的代币                                                                                                                                            |
| mintBatchByQuantity(mints\[])        | 允许矿工角色铸造一批代币 (`mints.quantity`）发送到一批指定的钱包 (`mints.to`)                                                                                                          |
| 销毁(tokenId)                          | 烧毁带有 ID 的令牌 `tokenId`                                                                                                                                           |
| burnBatch(tokenIds\[])               | 中指定 ID 的令牌。 `tokenIds`                                                                                                                                          |
| safeMint(to,tokenId)                 | 允许矿工角色 [安全地](https://docs.immutable.com/docs/zkEVM/products/contracts/erc721#safe-minting-and-burning) 创建一个 ID 为 `tokenId` 至 `to`                               |
| safeMintBatch(idMints\[])            | 允许矿工角色 [安全地](https://docs.immutable.com/docs/zkEVM/products/contracts/erc721#safe-minting-and-burning) 将一批具有指定 ID (`idMints.tokenIds`）发送到一批指定的钱包 (`idMints.to`) |
| safeMintByQuantity(to, quantity)     | 允许矿工角色向指定钱包[安全](https://docs.immutable.com/docs/zkEVM/products/contracts/erc721#safe-minting-and-burning)铸造一定数量的代币                                              |
| safeMintBatchByQuantity(mints\[])    | 允许矿工角色 [安全地](https://docs.immutable.com/docs/zkEVM/products/contracts/erc721#safe-minting-and-burning) 铸造一批代币 (`mints.quantity`）发送到一批指定的钱包 (`mints.to`)         |
| <p><br>safeBurn(tokenId)</p>         | [安全地](https://docs.immutable.com/docs/zkEVM/products/contracts/erc721#safe-minting-and-burning) 烧毁 ID 为 `tokenId`                                               |
| safeBurnBatch(tokenIds\[])           | [安全地](https://docs.immutable.com/docs/zkEVM/products/contracts/erc721#safe-minting-and-burning) 中指定 ID 的令牌。 `tokenIds`                                          |

GMLayer **ERC721 底座**[**​**](https://docs.immutable.com/docs/zkEVM/products/contracts/erc721#immutable-erc721-base)

| 功能                            | 说明                       |
| ----------------------------- | ------------------------ |
| baseURI()                     | 返回基本 URI                 |
| contractURI()                 | 返回合同 URI                 |
| 所有者()                         | 返回合同的当前所有者               |
| setBaseURI(baseURI\_)         | 设置基本 URI，仅限管理员使用         |
| setContractURI(\_contractURI) | 设置合同 URI，仅限管理员使用         |
| 转让所有权（地址 newOwner）            | 转让合同所有权，更新合同所有者，仅限于当前所有者 |
| 支持接口（interfaceId）             | 返回合同是否支持所提供的接口 ID        |

\\
