Skip to content

taurushq-io/TERC-721

Repository files navigation

TERC-721

ERC-721 is the main standard to represent non-fungibles tokens (NFT) on Ethereum and EVM blockchain. This ERC defines the functions, events and the behavior of a token implementing this interface.

One of the main libraries used to build ERC-721 contract is OpenZeppelin. This library provides already all functions which are part of the standard. Nevertheless, OpenZeppelin does not provide a deployable contract, but only an abstract contract which can be used to build other contracts though inheritance but cannot be deployed directly on the blockchain. You can find more information about their implementation in their documentation.

TERC-721 aims to provide a minimal deployable implementation for standalone deployment (immutable) and proxy deployment (upgradeable) which allows the issuer (and only him) to mint and burn tokens.

TERC-721 exists in two different version: standalone and proxy:

  • TERC721Standalone for an immutable deployment, without proxy

TERC721Standalone

  • TERC721Upgradeable for an upgradeable deployment, with a compatible proxy (Transparent or Beacon)

TERC721Upgradeable

[TOC]

ERC

In addition to ERC-721, TERC-721 uses the following ERCs:

  • ERC-4906: emit BatchMetadataUpdatewhen the baseURI is updated
  • ERC-6093: Custom errors for ERC-721 tokens (through OpenZeppelin)
  • eip-3643: implements the following function: version()
  • TERC721Upgradeable only:
    • implements ERC-7201 to manage the storage location.

Common characteristics

These ERC-721 tokens have the following characteristics:

Mint

  • Mint functions only accessible with the MINTER role

  • Batch mint functions only accessible with the MINTER role

TERC721ShareMint

Burn

  • A burn function only accessible with the BURNER role
  • A batch burn function only accessible with the BURNER role

TERC721ShareBurn

ERC721

  • At deployment, the issuer can set the name, symbol and the baseURI

  • Once deployed, it is no longer possible to modify the name and symbol except via an upgrade in the case of the proxy. A setter function is available to set the baseURI again.

Access Control

There are three roles: MINTER_ROLE, BURNER_ROLE and DEFAULT_ADMIN_ROLE

The DEFAULT_ADMIN_ROLE has all the roles by default

TERC-721.drawio

Schema

TERC721Standalone

Inheritance

surya_inheritance_TERC721Standalone.sol

Graph

surya_graph_TERC721Standalone.sol

TERC721 Upgradeable

Inheritance

surya_inheritance_TERC721Upgradeable.sol

Graph

surya_graph_TERC721Upgradeable.sol

Surya Description Report

Contracts Description Table

TERC721Standalone

Contract Type Bases
β”” Function Name Visibility Mutability Modifiers
TERC721Standalone Implementation TERC721Share, TERC721StandaloneBurn, TERC721StandaloneMint
β”” Public ❗️ πŸ›‘ ERC721
β”” setBaseURI Public ❗️ πŸ›‘ onlyRole
β”” baseURI Public ❗️ NO❗️
β”” supportsInterface Public ❗️ NO❗️
β”” hasRole Public ❗️ NO❗️
β”” _setBaseURI Internal πŸ”’ πŸ›‘
β”” _baseURI Internal πŸ”’
TERC721StandaloneMint
Contract Type Bases
β”” Function Name Visibility Mutability Modifiers
TERC721StandaloneMint Implementation ERC721, AccessControl, TERC721ShareMint
β”” mintTokenId Public ❗️ πŸ›‘ onlyRole
β”” batchMintTokenIds Public ❗️ πŸ›‘ onlyRole
β”” batchMintTokenIds Public ❗️ πŸ›‘ onlyRole
β”” nextTokenId Public ❗️ NO❗️
β”” setNextTokenId Public ❗️ πŸ›‘ onlyRole
β”” mint Public ❗️ πŸ›‘ onlyRole
β”” batchMint Public ❗️ πŸ›‘ onlyRole
β”” batchMint Public ❗️ πŸ›‘ onlyRole
β”” supportsInterface Public ❗️ NO❗️
β”” _mintAndEvent Internal πŸ”’ πŸ›‘
TERC721StandaloneBurn
Contract Type Bases
β”” Function Name Visibility Mutability Modifiers
TERC721StandaloneBurn Implementation ERC721, AccessControl, TERC721ShareBurn
β”” burn Public ❗️ πŸ›‘ onlyRole
β”” batchBurn Public ❗️ πŸ›‘ onlyRole
β”” supportsInterface Public ❗️ NO❗️

TERC721Upgradeable

Contract Type Bases
β”” Function Name Visibility Mutability Modifiers
TERC721Upgradeable Implementation Initializable, TERC721Share, TERC721UpgradeableBurn, TERC721UpgradeableMint
β”” Public ❗️ πŸ›‘ NO❗️
β”” initialize Public ❗️ πŸ›‘ initializer
β”” __TERC721Upgradeable_init_unchained Internal πŸ”’ πŸ›‘ onlyInitializing
β”” setBaseURI Public ❗️ πŸ›‘ onlyRole
β”” baseURI Public ❗️ NO❗️
β”” hasRole Public ❗️ NO❗️
β”” supportsInterface Public ❗️ NO❗️
β”” _setBaseURI Internal πŸ”’ πŸ›‘
β”” _baseURI Internal πŸ”’
β”” _getTERC721UpgradeableStorage Private πŸ”
TERC721UpgradeableMint
Contract Type Bases
β”” Function Name Visibility Mutability Modifiers
TERC721UpgradeableMint Implementation ERC721Upgradeable, AccessControlUpgradeable, TERC721ShareMint
β”” mintTokenId Public ❗️ πŸ›‘ onlyRole
β”” batchMintTokenIds Public ❗️ πŸ›‘ onlyRole
β”” batchMintTokenIds Public ❗️ πŸ›‘ onlyRole
β”” nextTokenId Public ❗️ NO❗️
β”” setNextTokenId Public ❗️ πŸ›‘ onlyRole
β”” mint Public ❗️ πŸ›‘ onlyRole
β”” batchMint Public ❗️ πŸ›‘ onlyRole
β”” batchMint Public ❗️ πŸ›‘ onlyRole
β”” supportsInterface Public ❗️ NO❗️
β”” _mintAndEvent Internal πŸ”’ πŸ›‘
β”” _getTERC721UpgradeableMintStorage Private πŸ”
TERC721UpgradeableBurn
Contract Type Bases
β”” Function Name Visibility Mutability Modifiers
TERC721UpgradeableBurn Implementation ERC721Upgradeable, AccessControlUpgradeable, TERC721ShareBurn
β”” burn Public ❗️ πŸ›‘ onlyRole
β”” batchBurn Public ❗️ πŸ›‘ onlyRole
β”” supportsInterface Public ❗️ NO❗️

Legend

Symbol Meaning
πŸ›‘ Function can modify state
πŸ’΅ Function is payable

Dependencies

The toolchain includes the following components, where the versions are the latest ones that we tested:

  • Foundry
  • Solidity 0.8.28 (via solc-js)
  • OpenZeppelin Contracts (submodule) v5.3.0
  • OpenZeppelin Contracts upgradeable (submodule) v5.3.0

Audit

See report made by SecFault Security

The audit was performed on the version 0.2.0 and the version containing the fix is the version 1.0.0

The functions setNextTokenIdand nextTokenIdhave been added in the version 1.0.0 and therefore were not included in the audit.

Audit tools

Slither

Report file

See crytic/slither

slither .  --checklist --filter-paths "openzeppelin-contracts|openzeppelin-contracts-upgradeable|test|forge-std" > slither-report.md

Mythril

Report file

myth analyze src/TERC721Standalone.sol --solc-json solc_setting.json

See Consensys/mythril

Cyfrin Aderyn

Report file

aderyn --output report.md

See Cyfrin/aderyn

Tools

Surya

See ./doc/script and Consensys/surya

Prettier

npx prettier --write --plugin=prettier-plugin-solidity 'src/**/*.sol'
npx prettier --write --plugin=prettier-plugin-solidity 'test/**/*.sol'

Surya

See ./doc/script

Foundry

Foundry is a blazing fast, portable and modular toolkit for Ethereum application development written in Rust.

Foundry consists of:

  • Forge: Ethereum testing framework (like Truffle, Hardhat and DappTools).
  • Cast: Swiss army knife for interacting with EVM smart contracts, sending transactions and getting chain data.
  • Anvil: Local Ethereum node, akin to Ganache, Hardhat Network.
  • Chisel: Fast, utilitarian, and verbose solidity REPL.

Usage

Explain how it works.

Toolchain installation

The contracts are developed and tested with Foundry, a smart contract development toolchain.

To install the Foundry suite, please refer to the official instructions in the Foundry book.

Initialization

You must first initialize the submodules, with

forge install

See also the command's documentation.

Later you can update all the submodules with:

forge update

See also the command's documentation.

Compilation

The official documentation is available in the Foundry website

 forge build

Testing

You can run the tests with

forge test --ffi

To run a specific test, use

forge test --match-contract <contract name> --match-test <function name>

See also the test framework's official documentation, and that of the test commands.

Coverage

coverage

  • Perform a code coverage
forge coverage
  • Generate LCOV report
forge coverage --report lcov
  • Generate index.html
forge coverage --ffi --report lcov && genhtml lcov.info --branch-coverage --output-dir coverage

See Solidity Coverage in VS Code with Foundry & Foundry forge coverage

Documentation

https://book.getfoundry.sh/

OpenSea integration

Burn mechanism

The burn mechanism implemented in TERC721 is not compatible with the OpenSea guideline

We don’t allow NFTs that are guaranteed to be burned or burned at the full discretion of the creator. There must be an element of randomization, chance, or an event that triggers the burn

See OpenSea support - How does OpenSea handle NFTs with a burn mechanism?

Metadata update (ERC-4906)

The contract emits the event BatchMetadataUpdatewhen the baseURI is updated as supported by OpenSea to refresh token metadata.

To refresh a whole collection, emit _toTokenId with type(uint256).max

See docs.opensea - metadata updates

Intellectual property

The original code is copyright (c) Taurus 2025, and is released under MIT license.

About

Minimal ERC-721 tokens with mint and burn

Resources

License

Contributing

Security policy

Stars

Watchers

Forks