# ERC721

The GMLayer ERC721 Preset Contract is an extension to the GMLayer ERC721 base contract and includes the ability to mint batches of tokens using one of two efficient methods. This is the preset contract that GMLayer recommends for game development.

***

| Function                                                                                                                                                                 | Suggested use                                                       |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------- |
| <ul><li>Mint</li><li>Metadata Setup and interrogation</li><li>Royalty calculation and on-chain royalty enforcement</li><li>Role-based restricted functionality</li></ul> | <ul><li>Launching your ERC721 collection on GMLayer zkEVM</li></ul> |

### Install, Use, and Deploy[​](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>

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

Preset contracts are contained in the **Contracts Library**, which can be easily added to a project:

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

We suggest using available frameworks such as Hardhat or Foundry to build your smart contract development environment from scratch.

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

Scope of use of the contract repository

* Develop and deploy your smart contracts using one of GMLayer's presets.
* Using Typescript clients to interact with deployed GMLayer preset contracts.

**smart contract development**[**​**](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 User**[**​**](https://docs.immutable.com/docs/zkEVM/products/contracts/erc721#typescript-client)

`@imtbl/contracts` Typescript client that can be used with deployed `ERC721 Preset` contracts：

```
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);
```

By default, the Gas Fee is already configured  `ERC721Client` based on the network structure.

#### Deploy[​](https://docs.immutable.com/docs/zkEVM/products/contracts/erc721#installation-usage-and-deployment)[​](https://docs.immutable.com/docs/zkEVM/products/contracts/erc721#deployment) <a href="#deployment" id="deployment"></a>

To deploy smart contracts on GMLayer zkEVM, see the Deploying Smart Contracts Quick Start Guide.

#### Deployment of hardhat[​](https://docs.immutable.com/docs/zkEVM/products/contracts/erc721#configure-hardhat) <a href="#configure-hardhat" id="configure-hardhat"></a>

Update the project's `hardhat.config.js/ts` file with the following code. This file is located in the smart contract repository.

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

```

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

While the contract contains the recommended functionality, it can be extended or refactored according to the developer's needs. It is important to note that extending functionality may introduce vulnerabilities in the smart contract, so care should be taken.

### Function <a href="#functionality-and-design" id="functionality-and-design"></a>

#### MINT <a href="#minting" id="minting"></a>

Minting an ERC721NFT (Non-Fungible Token) creates a unique asset on the blockchain specific to a contract. It is preset to use one of two methods to mint tokens:

* When minting by quantity, the contract uses the ERC721Psi method to efficiently mint multiple tokens. This method starts minting tokens from the value returned by the ERC721Psi method.`bulkMintThreshold`can be overridden by subclassing the preset.
* When minting tokens by ID, the contract uses the internal ERC721 `_mint` function. The ID specified for tokens minted in this way must be less than `bulkMintTreshold`.

By default`bulkMintThreshold` returns a value of `2 ** 128`or  `340282366920938463463374607431768211456`.

Both methods are licensed. The brackets read "...". `mint` function allows a user with the miner role to mint a certain number of tokens to a specified address (see the Access Control section below for more information on permissions).

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

Burn ERC721NFT (Non-Fungible Token).

#### Bulk mint and burn[​](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>

Preset contracts provide several ways to effectively mint and burn tokens:

* `mintBatch`: Generate a batch of tokens with the ID specified by the caller.
* `mintBatchByQuantity`Token: Mint a batch of tokens with sequential ID.
* `burnBatch`: Burn a batch of tokens, specifying the ID of each token.

#### Safe mint and burn[​](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>

The ERC721 preset contract includes safe versions of all minting and incineration methods. These methods require an additional Gas fee, but additional checks are performed to ensure safe operation:

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

Data is a component of an NFT (Non-Fungible Token) collection that defines its unique properties and utility; the collection owner defines this data. Metadata in a collection is referenced by its Universal Resource Identifier (URI). Metadata sources may be stored up or down the chain and support different schemas.

Metadata may be a volatile object that is frequently updated by the collection owner. This may be related to the specific use or mechanism of the dataset and means that services integrating with the dataset need to have up-to-date metadata in their systems.

GMLayer predefined contracts support token and collection-level。 metadata. The base URI and contract URI are set in the constructor of the preset, which also provides functions to update them.

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

There are three canonical metadata URIs in the ERC721 dataset:

1. **Base URI**: A single metadata URI that is the common denominator of all token ID.
2. **Token URI**: metadata URI dedicated to a single token ID.
3. **Contract URI**: A single metadata URI that applies to the entire collection. e.g., Marketplace is used to provide store information.

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

Storing metadata off-chain means that the data is stored in an off-chain location outside the contract store. Pointers to off-chain metadata sources are stored in the contract store.

Storing metadata on-chain means that the data is stored in the contract's storage. The format of the on-chain metadata is usually JSON, but not always, and the integration system should handle this accordingly.

On-chain metadata is still a schema that is not as widely used in the ecosystem as off-chain metadata, and therefore has less support and tools (as well as increased fuel costs) and lacks the richness that off-chain storage can provide. Therefore, off-chain metadata storage is recommended.

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

The metadata schema provides a standard for applications that integrate with your ERC721 contract to know what metadata is expected to be returned and how it should be interpreted.OpenSea's metadata schema is built on the official ERC721 metadata standard and is the community's most-adopted schema for defining and understanding metadata within the ecosystem, with support for both on-chain and off-chain metadata. The schema can be found [here](https://docs.opensea.io/docs/metadata-standards#metadata-structure). Therefore, it is recommended to use this schema when defining metadata (this applies to the schema for collection URIs and token URIs).

The format used by the OpenSea schema is JSON. an example is shown below:

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

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

The schema used by OpenSea supports attributes that allow creators to provide additional information about their NFTs. Within these properties, traits allow you to describe the attributes of the NFT (Non-Fungible Token) as well as the display format. The three different types of attributes are numbers, dates, and strings. For example, the hero NFT (Non-Fungible Token) can be described using these traits as follows:

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

For more information on using Trait and their characteristics in metadata, see here.

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

Preset contracts inherit OpenZeppelin's Access Control module, which allows you to define role-based access modifiers for specific features such as minting.&#x20;

AccessControl defines an ontology of roles within a contact. A role is a structure that contains a list of members and a defined administrator role, and each member of the structure has an administrator role. For more information about access control, see the OpenZeppelin documentation.

The modifier `onlyRole()` is used to limit the use of functions to administrators with that role. For example, only the role with `MINTER` can perform the function `mint......`., `DEFAULT_ADMIN_ROLE` is another role in the preset whose functions are restricted. These functions include.

1. `setBaseURI` Allows administrators to update the base URI.
2. `setContractURI` Allows administrators to update contract URIs.
3. `grantMinterRole` Allows administrators to grant roles to MINTER users.
4. `transferOwnership` Allows administrators to set up new owners in the contract.

The ontology of the owner is in the preset contract for display purposes (e.g., marketplace Storefronts typically display metadata Information about the collection, such as the owner of the collection as labeled by the contract owner). The owner is set when the contract is deployed, which is`DEFAULT_ADMIN_ROLE`Ownership can be transferred to other addresses as long as they are members of the organization. `DEFAULT_ADMIN_ROLE`.note that this implementation is not OpenZeppelin's standard for Ownable.

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

| Function                                                      | Note                                                                                                                                                                                                                                |
| ------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| grantMinterRole(user)                                         | Grant the user the role of miner, for administrators only.                                                                                                                                                                          |
| mint(to,tokenId)                                              | Allow the miner role-casting `tokenId` to `to`                                                                                                                                                                                      |
| mintBatch(idMints\[])                                         | Allows the "miner" role to mint a batch of tokens with a specified ID ("ID".`idMints.tokenIds`）to send to a batch of specified wallets (`idMints.to`).                                                                              |
| mintByQuantity(to, quantity) (delivery according to quantity) | Allows a miner character to mint a certain number of tokens into a specified wallet.                                                                                                                                                |
| mintBatchByQuantity(mints\[])                                 | Allows the miner role to mint a batch of tokens(`mints.quantity`）to send to a specified batch of wallets (`mints.to`).                                                                                                              |
| Burn(tokenId)                                                 | Burn token with ID `tokenId`                                                                                                                                                                                                        |
| BurnBatch(tokenIds\[])                                        | The token for the specified ID. `tokenIds`                                                                                                                                                                                          |
| safeMint(to,tokenId)                                          | Allows the miner role to [securely ](https://docs.immutable.com/docs/zkEVM/products/contracts/erc721#safe-minting-and-burning)create a token with an ID of `tokenId` to `to`                                                        |
| safeMintBatch(idMints\[])                                     | Allows the miner role to [securely](https://docs.immutable.com/docs/zkEVM/products/contracts/erc721#safe-minting-and-burning) send a batch with a specified ID(`idMints.tokenIds`）to a batch with a specified wallet (`idMints.to`) |
| safeMintByQuantity(to, quantity)                              | Allows a miner character to [securely](https://docs.immutable.com/docs/zkEVM/products/contracts/erc721#safe-minting-and-burning) mint a certain number of tokens into a specified wallet                                            |
| safeMintBatchByQuantity(mints\[])                             | Allows the miner role to [securely](https://docs.immutable.com/docs/zkEVM/products/contracts/erc721#safe-minting-and-burning) mint a batch of tokens(`mints.quantity`）and send them to a specified batch of wallets (`mints.to`)    |
| <p><br>safeBurn(tokenId)</p>                                  | [Securely](https://docs.immutable.com/docs/zkEVM/products/contracts/erc721#safe-minting-and-burning) burn the ID as `tokenId`                                                                                                       |
| safeBurnBatch(tokenIds\[])                                    | [Securely](https://docs.immutable.com/docs/zkEVM/products/contracts/erc721#safe-minting-and-burning) specifies tokens with IDs.`tokenIds`                                                                                           |

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

| Function                                 | Note                                                                           |
| ---------------------------------------- | ------------------------------------------------------------------------------ |
| baseURI()                                | Returns the base URI.                                                          |
| contractURI()                            | Return contract URI.                                                           |
| owner()                                  | Returns the current owner of the contract.                                     |
| setBaseURI(baseURI\_)                    | Set the base URI, for administrators only.                                     |
| setContractURI(\_contractURI)            | Set contract URI for administrators only.                                      |
| Transfer of ownership（address new owner） | Transfer of contract ownership, renewal of contract owner, current owner only. |
| Supported Interfaces（interfaceId）        | Returns whether the contract supports the provided interface ID.               |

<br>


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://gmlayer.gitbook.io/english-1/dapp/contract-booking/erc721.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
