Skip to content

Instantly share code, notes, and snippets.

@fend25
Last active December 1, 2022 12:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fend25/70f9adad7072ad2758c3eaefd2d54f59 to your computer and use it in GitHub Desktop.
Save fend25/70f9adad7072ad2758c3eaefd2d54f59 to your computer and use it in GitHub Desktop.
Unique ERC721Metadata-compatible specification

Unique ERC721-compatible collections specification.

Collection and token properties.

We don't specify any special requirements for common Unique collections. But ERC721-compatible collections MUST meet these requirements:

  1. Collection's flag erc721metadata MUST be true // getting flags not available in solidity interfaces right now

  2. Collection MAY have property {key: "baseURI", value: "<base URI of the tokens>"}

  3. Collection MUST have such tokenPropertyPermission:
    {key: "URI", permission: {mutable: true, collectionAdmin: true, tokenOwner: false}} - token full URI

  4. Collection MAY have such tokenPropertyPermission:
    {key: "URISuffix", permission: {mutable: true, collectionAdmin: true, tokenOwner: false}} - token URI suffix

Functions

UniqueNFT stub interface has to contain such functions:

supportsInterface (ERC165)

function supportsInterface(bytes4 interfaceID) external view returns (bool);

When called with interfaceID 0x5b5e139f (ERC721Metadata), it MUST return true if collection's flag erc721metadata is true, otherwise false.

Other interfaceID values are assumed to be processed as usual.

tokenURI

function tokenURI(uint256 tokenId) public view virtual override returns (string memory);

Definitions:

  • "baseURI is non-empty" means that there is a property in the collection with key "baseURI" and value which IS NOT empty string.
  • "URI is non-empty" means that there is a property in the token with key "URI" and value which IS NOT empty string.
  • "URISuffix is non-empty" means that there is a property in the token with key "URISuffix" and value which IS NOT empty string. In other words, when baseURI and URI and s is empty string, tokenURI function MUST consider it as absence of this property at all.

In other words, reading of token properties URI and URISuffix should be safe and don't throw if there is no such tokenPropertyPermission.

Desired behaviour:

if the collections has flag erc721metadata value not true, throw an error.

Otherwise,

  • if token property URI (safe property read) is non-empty, return it, token property URI
  • otherwise, if the collection property baseURI is empty or absent, return "" (empty string)
  • otherwise, if token property URISuffix (safe property read) is non-empty, return concatenation of collection property baseURI and token property URISuffix
  • otherwise, return collection property baseURI

Example in pseudocode:

let isCollectionERC721MetadataCompatible = collection.flags.erc721metadata === true

let baseURI = collectionProperty("baseURI")
let URI = tokenProperty(tokenId, "URI")
let URISuffix = tokenProperty(tokenId, "URISuffix")

let baseURIIsOk = !!baseURI && baseURI.length > 0
let URIIsOk = !!URI && URI.length > 0
let suffixIsOk = !!URISuffix && URISuffix.length > 0

if (!isCollectionERC721MetadataCompatible) {
  throw;
} else if (URIIsOk) {
  return URI;
} else if (!baseURIIsOk) {
  return "";
} else if (suffixIsOk) {
  return baseURI + URISuffix;
} else {
  return baseURI;
}

A bit simpler implementation can be found here: ERC721URIStorage tokenURI implementation

Methods which will appear somewhen late

safeMint

function safeMint(
  address to,
  uint tokenId,
) external returns (uint);

This function just mints a token, without any properties being set. No checks regarding some properties values are assumed here - just a clean minting.

If tokenId is 0, it SHOULD mint with autoincrement. Otherwise, if tokenId is not valid (not equal to nextTokenId) - revert.

safeMintWithTokenURI

function safeMintWithTokenURI(
  address to, 
  uint tokenId,
  string tokenUri
) external returns (uint);

Mints a token and creates a property in this token with key "url" and value of argument tokenUri value.

If tokenId is 0, it SHOULD mint with autoincrement. Otherwise, if tokenId is not valid (not equal to nextTokenId) - revert.

safeMintWithTokenURISuffix

function safeMintWithTokenURISuffix(
  address to, 
  uint tokenId,
  string tokenUriSuffix
) external returns (uint);

Mints a token and creates a property in this token with key "suffix" and value of argument tokenUriSuffix value.

If tokenId is 0, it SHOULD mint with autoincrement. Otherwise, if tokenId is not valid (not equal to nextTokenId) - revert.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment