Skip to main content

ERC721OwlAttributes

ERC721OwlAttributes

This implementation is an extension of OwlProtocol's base {ERC721Owl} that enables on-chain encoding. In most uses of ERC721, contract deployers have chosen to keep all metadata off-chain. While this is economical in terms of gas costs it also disallows on-chain actors (first-party or third-party) to deploy contracts that depend on the metadata. This contract solves the latter without sacrificing on the former.

In this contract, each tokenId is auto-incremented, solely determined by the order of the mint. Each tokenId is also paired with a dna at the time of mint. The dna will hold an encoding of all attributes for that specific tokenId, stored in the dnas mapping.

A "dna" will be stored in its decimal form, however all the metadata can be decoded from its binary form, given the configuration of its "genes". A "gene" represents a potential attribute that a tokenId can posses. The size of the "gene" (how many bits it will be allocated in the binary form) will be determined by the amount of possible options the attribute (that the "gene" represents) can have.

A quick exemplification of the concept of "genes": Suppose an {ERC721OwlAttributes} instance with 3 attributes and 4 options for each attribute: 4 options can be encoded into two bits (log(4) = 2). Since there are three total attributes, the tokenIds in this {ERC721OwlAttributes} instance will require 6 bits for encoding. Suppose the attributes options are in arrays:

attributes1 = [option1, ..., option4]
attributes2 = [option1, ..., option4]
attributes3 = [option1, ..., option4]

So if a tokenId was minted with a "dna" that had a binary format of 01 10 11, that tokenId's metadata would be:

  • option2 for attributes1
  • option3 for attributes2
  • option4 for attributes3

01 10 11 in its decimal form is 27 which is what would be mapped to the tokenId it was assigned during minting.

If it were ever required, the genes array for this {ERC721OwlAttribtues} instance would be [0, 2, 4, 6]. They are, in order, the index ranges of each "gene" in the binary format of the "dna". The genes array must begin at 0 and be strictly increasing. The max size of a "dna" is 256 bits so no element in the genes should be above 255 (it is a uint8[] array).

The dnas mapping can be dynamically updated by DNA_ROLE through the updateDna() function.

DNA_ROLE

bytes32 DNA_ROLE

ERC165TAG

bytes4 ERC165TAG

dnas

mapping(uint256 => uint256) dnas

nextId

struct CountersUpgradeable.Counter nextId

initialize

function initialize(address _admin, string _name, string _symbol, string baseURI_, address _forwarder, address _receiver, uint96 _feeNumerator) external virtual

Initializes contract (replaces constructor in proxy pattern)

NameTypeDescription
_adminaddressowner
_namestringname
_symbolstringsymbol
baseURI_stringuri
_forwarderaddresstrusted forwarder address for openGSN
_receiveraddressaddress of receiver of royalty fees
_feeNumeratoruint96numerator of fee proportion (numerator / 10000)

proxyInitialize

function proxyInitialize(address _admin, string _name, string _symbol, string baseURI_, address _forwarder, address _receiver, uint96 _feeNumerator) external virtual

Initializes contract through beacon proxy (replaces constructor in proxy pattern)

__ERC721OwlAttributes_init

function __ERC721OwlAttributes_init(address _admin, string _name, string _symbol, string baseURI_, address _forwarder, address _receiver, uint96 _feeNumerator) internal

__ERC721OwlAttributes_init_unchained

function __ERC721OwlAttributes_init_unchained() internal

grantDna

function grantDna(address to) public

Must have DEFAULT_ADMIN_ROLE

Grants DNA_ROLE to to

NameTypeDescription
toaddressaddress to

tokenURI

function tokenURI(uint256 tokenId) public view virtual returns (string uri)

returns uri for token metadata.

NameTypeDescription
tokenIduint256tokenId metadata to fetch
NameTypeDescription
uristringat which metadata is housed

mint

function mint(address to, uint256 dna) public virtual

Must have MINTER_ROLE

Allows MINTER_ROLE to mint NFTs

NameTypeDescription
toaddressaddress to
dnauint256of next tokenId

safeMint

function safeMint(address to, uint256 dna) public virtual

Must have MINTER_ROLE

Allows caller to mint NFTs (safeMint)

NameTypeDescription
toaddressaddress to
dnauint256of next tokenId

updateDna

function updateDna(uint256 tokenId, uint256 dna) external

Must have DNA_ROLE

Allows changing the dna of a tokenId

NameTypeDescription
tokenIduint256whose dna to change
dnauint256new dna for the provided tokenId

getDna

function getDna(uint256 tokenId) external view returns (uint256)

Getter for dna of tokenId

NameTypeDescription
tokenIduint256whose dna to change
NameTypeDescription
[0]uint256dna of tokenId

supportsInterface

function supportsInterface(bytes4 interfaceId) public view virtual returns (bool)

ERC165 Support

NameTypeDescription
interfaceIdbytes4hash of the interface testing for
NameTypeDescription
[0]boolbool whether interface is supported