0.0.5 • Published 1 year ago

@niftory/niftory-solidity v0.0.5

Weekly downloads
-
License
MIT
Repository
github
Last release
1 year ago

Niftory Smart Contracts for EVM Compatible Blockchains

This repository hosts all smart contracts (and related scripts, tests, etc.) for Niftory, an NFT management platform. Niftory NFTs are ERC1155 compatible.

Note: This README is autogenerated. Please modify docs from within the docs folder and run yarn build to regenerate.

Usage

In order to use the contract, just extend one of the contracts from the impl folder. Currently, there is only NiftoryStandardERC1155.

Typed APIs, generated with typechain, can be accessed via src/bindings. NiftoryStandardERC1155Interface from here is the best place to see the full accessible API in one place.

Overview

Each uniquely identifiable ERC1155 token maps to a unique set (via setId) and template (via templateId) pair. The IERC1155 token id (e.g. for the uri function) can be expressed as (setId << 64) + templateId, as setId and templateId are both 64 bits each.

A contract can have multiple sets, and each set can have multiple templates. Indexing for both starts at 1 (so there is no set with setId=0 or template with templateId=0 in any set).

Each template maps to exactly one uri, which can be modified by an Admin or SetAdmin (see next section). templates also keep track of how many NFTs have been minted for that template and how many are allowed to minted (maxMint). A template with a maxMint of 0 allows unlimited minting. A maxMint may be set later, however.

sets can be locked to prevent more templates from being added, and templates can have metadata modification and minting locked separately.

sets allow Admins to delegate control to a collection of templates to a SetAdmin, allowing the SetAdmin to lock and mint from sets it owns.

Roles and Actions

This contract uses a very simple RBAC style management with three different roles, as below.

Admin

An Admin is the superuser of the contract. An Admin can

  • Assign (or revoke) more Admins
  • Assign (or revoke) SetAdmins
  • Create & lock sets
  • Add templates to any set
  • Mint from any mintable template
  • Change the metadata for any template
  • Modify the maximum mint amount for any template
  • Lock metadata and minting for any template
  • Modify the global default URI

Set Admin

A SetAdmin is an adminstrator of sets it has been given power over, either from an Admin or another previous SetAdmin. A SetAdmin can

  • Assign (or revoke) SetAdmins from the sets it owns
  • Lock sets it owns
  • Add templates to sets it owns
  • Mint from mintable templates of sets it owns
  • Change the metadata of templates of sets it owns
  • Modify the maximum mint amount for templates of sets it owns
  • Lock metadata and minting for templates of sets it owns

Collector

Collector is another way of saying "no role" and can be anyone with an account on the blockchain. A Collector can

  • Hold and transfer tokens
  • Approve another account to manage tokens
  • Burn tokens

All the above functionality is provided by OpenZeppelin's ERC1155 implementation.

Architecture

There are three extensions that can be used to power this token, which all assume that an ERC1155 token uses the set/template scheme mentioned above.

The main NiftoryStandardERC1155 uses OpenZeppelin's ERC1155Burnable.sol as a base. There are three custom extensions used, which can be found in contracts/extensions

  • UriManager manages URI's for templates and allows modification. If the URI is blank, it will use the default _defaultUri.
  • RoleManager manages the Admin and SetAdmin based ownership. RoleManager maps an (address, setId) pair to a boolean value indicating whether address is a SetAdmin of set setId. The 0-th bit is used to indicate an Admin. This extension uses a custom library (lib/AddressIndexedBitmap.sol) in order to tightly pack the boolean role indicator
  • TemplateManager is broken into two parts - the SetManager and the deriving TemplateManager. The SetManager stores Sets in a setId => Set map. A Set needs to keep track of how many templates it contains, and also allows locking to stop more templates from being added. TemplateManager manages each Template, keeping track of what the max mint is, how many NFTs have been minted from it, whether metadata can still be modified, and whether minting is still unlocked.

There are also two libraries in the lib folder - AddressedIndexedBitmap.sol and TemplateBasedId.sol. AddressedIndexedBitmap was already mentioned above, but TemplateBasedId provides a 1-1 mapping from (uint64 setId, uint64 templateId) <=> uint256 id), in order to adhere to IERC1155.

Development

  • yarn - install all node dependencies
  • yarn clean - remove all hardhat generated files
  • yarn compile - compile Solidity files and generate docs
  • yarn build - clean and compile
  • yarn test - build and run tests (and show gas usage information)
  • yarn coverage - generate coverage reports

Solidity API

MetadataManager

State

struct State {
  string _contractUri;
  string tokenUri;
  mapping(uint256 => string) tokenUriOverrides;
  struct LockManager.State locks;
}

contractUri

function contractUri(struct MetadataManager.State self) internal view returns (string)

uri

function uri(struct MetadataManager.State self, uint64 setId, uint64 templateId, uint64 serialNumber) internal view returns (string)

modifyContractUri

function modifyContractUri(struct MetadataManager.State self, string newContractUri) internal

modifyTokenUri

function modifyTokenUri(struct MetadataManager.State self, string newTokenUri) internal

modifySetOverrides

function modifySetOverrides(struct MetadataManager.State self, uint64[] setIds, string[] newTokenUris) internal

modifyTemplateOverrides

function modifyTemplateOverrides(struct MetadataManager.State self, uint64 setId, uint64[] templateIds, string[] newTokenUris) internal

modifySerialOverrides

function modifySerialOverrides(struct MetadataManager.State self, uint64 setId, uint64 templateId, uint64[] serialNumbers, string[] newTokenUris) internal

lockContract

function lockContract(struct MetadataManager.State self) internal

lockSets

function lockSets(struct MetadataManager.State self, uint64[] setIds) internal

lockSetRange

function lockSetRange(struct MetadataManager.State self, uint64 setIdStart, uint64 setIdEnd) internal

lockTemplates

function lockTemplates(struct MetadataManager.State self, uint64 setId, uint64[] templateIds) internal

lockTemplateRange

function lockTemplateRange(struct MetadataManager.State self, uint64 setId, uint64 templateIdStart, uint64 templateIdEnd) internal

_getBestUri

function _getBestUri(struct MetadataManager.State self, uint64 setId, uint64 templateId, uint64 serialNumber) private view returns (string)

MintManager

Template

struct Template {
  mapping(uint256 => uint256) balances;
  uint64 minted;
  uint64 maxMint;
}

Set

struct Set {
  uint64 numTemplates;
}

State

struct State {
  mapping(uint256 => struct MintManager.Set) sets;
  mapping(uint256 => struct MintManager.Template) templates;
  struct LockManager.State locks;
  uint64 numSets;
}

addressHasToken

function addressHasToken(struct MintManager.State self, address addr, uint64 setId, uint64 templateId, uint64 serialNumber) internal view returns (bool)

doesSetExist

function doesSetExist(struct MintManager.State self, uint64 setId) internal view returns (bool)

doesTemplateExist

function doesTemplateExist(struct MintManager.State self, uint64 setId, uint64 templateId) internal view returns (bool)

checkSetExists

function checkSetExists(struct MintManager.State self, uint64 setId) internal view

checkTemplateExists

function checkTemplateExists(struct MintManager.State self, uint64 setId, uint64 templateId) internal view

numberOfSets

function numberOfSets(struct MintManager.State self) internal view returns (uint64)

numberOfTemplates

function numberOfTemplates(struct MintManager.State self, uint64 setId) internal view returns (uint64)

numberMinted

function numberMinted(struct MintManager.State self, uint64 setId, uint64 templateId) internal view returns (uint64)

addSets

function addSets(struct MintManager.State self, uint64 numSets) internal

addTemplates

function addTemplates(struct MintManager.State self, uint64 setId, uint64 numTemplates) internal

mint

function mint(struct MintManager.State self, address[] to, uint64 setId, uint64[] templateIds, uint64[] amounts) internal

lockContract

function lockContract(struct MintManager.State self) internal

lockSets

function lockSets(struct MintManager.State self, uint64[] setIds) internal

lockTemplates

function lockTemplates(struct MintManager.State self, uint64 setId, uint64[] templateIds) internal

setMaxMints

function setMaxMints(struct MintManager.State self, uint64 setId, uint64[] templateIds, uint64[] maxMints) internal

transfer

function transfer(struct MintManager.State self, address from, address to, uint256[] tokenIds) internal

burn

function burn(struct MintManager.State self, address from, uint256[] tokenIds) internal

OperatorManager

State

struct State {
  mapping(uint256 => bool) operators;
}

isApproved

function isApproved(struct OperatorManager.State self, address account, address operator) internal view returns (bool)

checkApproved

function checkApproved(struct OperatorManager.State self, address account, address operator) internal view

modifyApproval

function modifyApproval(struct OperatorManager.State self, address account, address operator, bool approved) internal

_operatorKey

function _operatorKey(address account, address operator) private pure returns (uint256)

RoleManager

_CONTRACT_ADMIN_BIT

uint64 _CONTRACT_ADMIN_BIT

State

struct State {
  mapping(uint256 => uint256) roles;
}

isContractAdmin

function isContractAdmin(struct RoleManager.State self, address addr) internal view returns (bool)

isSetAdmin

function isSetAdmin(struct RoleManager.State self, address addr, uint64 setId) internal view returns (bool)

checkContractAdmin

function checkContractAdmin(struct RoleManager.State self, address addr) internal view

checkSetAdmin

function checkSetAdmin(struct RoleManager.State self, address addr, uint64 setId) internal view

grantContractAdmin

function grantContractAdmin(struct RoleManager.State self, address[] addrs) internal

grantSetAdmin

function grantSetAdmin(struct RoleManager.State self, uint64[] setIds, address[] addrs) internal

grantSetRangeAdmin

function grantSetRangeAdmin(struct RoleManager.State self, uint64 fromSetId, uint64 toSetId, address[] addrs) internal

revokeContractAdmin

function revokeContractAdmin(struct RoleManager.State self, address[] addrs) internal

revokeSetRangeAdmin

function revokeSetRangeAdmin(struct RoleManager.State self, uint64 fromSetId, uint64 toSetId, address[] addrs) internal

UpgradeManager

State

struct State {
  mapping(address => bool) admins;
}

isAdmin

function isAdmin(struct UpgradeManager.State self, address account) internal view returns (bool)

checkAdmin

function checkAdmin(struct UpgradeManager.State self, address account) internal view

grantAdmin

function grantAdmin(struct UpgradeManager.State self, address account) internal

revokeAdmin

function revokeAdmin(struct UpgradeManager.State self, address account) internal

NiftoryOptimizedERC1155

AdminsAssigned

event AdminsAssigned(uint64 setId, address[] admins)

AdminsRevoked

event AdminsRevoked(uint64 setId, address[] admins)

SetsAdded

event SetsAdded(uint64[] setIds)

SetsLocked

event SetsLocked(uint64[] setIds)

TemplatesAdded

event TemplatesAdded(uint64 setId, uint64[] templateIds)

TemplatesMetadataLocked

event TemplatesMetadataLocked(uint64 setId, uint64[] templateIds)

SetMetadataLocked

event SetMetadataLocked(uint64 setId)

TemplatesMaxMintModified

event TemplatesMaxMintModified(uint64 setId, uint64[] templateIds, uint64[] newMaxes)

TemplatesMintingLocked

event TemplatesMintingLocked(uint64 setId, uint64[] templateIds)

SetMintingLocked

event SetMintingLocked(uint64 setId)

_roleManager

struct RoleManager.State _roleManager

_operatorManager

struct OperatorManager.State _operatorManager

_mintManager

struct MintManager.State _mintManager

_metadataManager

struct MetadataManager.State _metadataManager

constructor

constructor() public

initialize

function initialize(address owner, string contractUri, string tokenUri) public

supportsInterface

function supportsInterface(bytes4 interfaceId) public pure returns (bool)

_Returns true if this contract implements the interface defined by interfaceId. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] to learn more about how these ids are created.

This function call must use less than 30 000 gas._

balanceOf

function balanceOf(address account, uint256 id) public view returns (uint256)

_Returns the amount of tokens of token type id owned by account.

Requirements:

  • account cannot be the zero address._

balanceOfBatch

function balanceOfBatch(address[] accounts, uint256[] ids) public view returns (uint256[])

_xref:ROOT:erc1155.adoc#batch-operationsBatched version of {balanceOf}.

Requirements:

  • accounts and ids must have the same length._

setApprovalForAll

function setApprovalForAll(address operator, bool approved) public

_Grants or revokes permission to operator to transfer the caller's tokens, according to approved,

Emits an {ApprovalForAll} event.

Requirements:

  • operator cannot be the caller._

isApprovedForAll

function isApprovedForAll(address account, address operator) public view returns (bool)

_Returns true if operator is approved to transfer account's tokens.

See {setApprovalForAll}._

safeTransferFrom

function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes) public

safeBatchTransferFrom

function safeBatchTransferFrom(address from, address to, uint256[] ids, uint256[] amounts, bytes) public

uri

function uri(uint256 id) public view returns (string)

_Returns the URI for token type id.

If the \{id\} substring is present in the URI, it must be replaced by clients with the actual token type ID._

contractURI

function contractURI() public view returns (string)

_checkOwner

function _checkOwner() internal view

Throws if the sender is not the owner.

burn

function burn(uint256[] ids) public

addSets

function addSets(uint64 numSets) public

addTemplates

function addTemplates(uint64 setId, uint64 numTemplates) public

mint

function mint(address[] to, uint64 setId, uint64[] templateIds, uint64[] amounts) public

lockMintingForContract

function lockMintingForContract() public

lockMintingForSets

function lockMintingForSets(uint64[] setIds) public

lockMintingForTemplates

function lockMintingForTemplates(uint64 setId, uint64[] templateIds) public

setMaxMints

function setMaxMints(uint64 setId, uint64[] templateIds, uint64[] maxMints) public

modifyContractMetadataUri

function modifyContractMetadataUri(string newUri) public

modifyTokenMetadataUri

function modifyTokenMetadataUri(string newUri) public

modifySetMetadataOverrides

function modifySetMetadataOverrides(uint64[] setIds, string[] newUris) public

modifyTemplateMetadataOverrides

function modifyTemplateMetadataOverrides(uint64 setId, uint64[] templateIds, string[] newUris) public

modifySerialMetadataOverrides

function modifySerialMetadataOverrides(uint64 setId, uint64 templateId, uint64[] serialNumbers, string[] newUris) public

lockMetadataForContract

function lockMetadataForContract() public

lockMetadataForSets

function lockMetadataForSets(uint64[] setIds) public

lockMetadataForTemplates

function lockMetadataForTemplates(uint64 setId, uint64[] templateIds) public

grantContractAdmin

function grantContractAdmin(address[] admins) public

grantSetAdmin

function grantSetAdmin(uint64[] setIds, address[] admins) public

grantSetRangeAdmin

function grantSetRangeAdmin(uint64 fromSetId, uint64 toSetId, address[] admins) public

Beacon

_upgradeManager

struct UpgradeManager.State _upgradeManager

constructor

constructor(address implementation) public

_checkOwner

function _checkOwner() internal view

Throws if the sender is not the owner.

grantAdmin

function grantAdmin(address account) public

revokeAdmin

function revokeAdmin(address account) public

deployProxy

function deployProxy(bytes data, bool forceCall) public returns (address proxy)

BeaconProxy

_BEACON_SLOT

bytes32 _BEACON_SLOT

BeaconUpgraded

event BeaconUpgraded(address beacon)

_roleManager

struct RoleManager.State _roleManager

constructor

constructor(address beacon, bytes data, bool forceCall) public payable

_implementation

function _implementation() internal view returns (address)

This is a virtual function that should be overridden so it returns the address to which the fallback function and {_fallback} should delegate.

redirectBeaconProxy

function redirectBeaconProxy(address newBeacon, bytes data, bool forceCall) public

_setBeacon

function _setBeacon(address newBeacon, bytes data, bool forceCall) private

AddressIndexedBitmap

A bitmap that can be efficiently indexed by an (address, uint64) pair.

Best if used as a decorator for a mapping of (uint256 => uint256)

_ADDRESS_SHIFT

uint256 _ADDRESS_SHIFT

getBit

function getBit(mapping(uint256 => uint256) bitmap, address addr, uint64 index) internal view returns (bool)

setBit

function setBit(mapping(uint256 => uint256) bitmap, address addr, uint64 index) internal

set the bit at position index for addr in bitmap

Parameters

NameTypeDescription
bitmapmapping(uint256 => uint256)the underlying bitmap - target of decorator
addraddressthe address to index into the bitmap
indexuint64the bit to set

setBitRange

function setBitRange(mapping(uint256 => uint256) bitmap, address addr, uint64 start, uint64 end) internal

clearBit

function clearBit(mapping(uint256 => uint256) bitmap, address addr, uint64 index) internal

clear the bit at position index for addr in bitmap

Parameters

NameTypeDescription
bitmapmapping(uint256 => uint256)the underlying bitmap - target of decorator
addraddressthe address to index into the bitmap
indexuint64the bit to clear

clearBitRange

function clearBitRange(mapping(uint256 => uint256) bitmap, address addr, uint64 start, uint64 end) internal

_addressKey

function _addressKey(address addr) private pure returns (uint256)

ArrayOps

singleton

function singleton(address a) internal pure returns (address[])

singleton

function singleton(uint256 a) internal pure returns (uint256[])

singleton

function singleton(uint64 a) internal pure returns (uint64[])

singleton

function singleton(bool a) internal pure returns (bool[])

fill

function fill(address[] arr, address a) internal pure

BitmapOps

Library for manipulating bitmaps. A bitmap is a uint256 -> uint256 mapping. It is assumed that the "word selector" is actually 64 bits, but we use 256 bits for the mapping key because we can do more with it. However, this means that we always need to provide the full key separately.

getBit

function getBit(mapping(uint256 => uint256) bitmap, uint256 key, uint64 index, uint256 subWordIndexShift) internal view returns (bool)

getBitRangeForWord

function getBitRangeForWord(mapping(uint256 => uint256) bitmap, uint256 key, uint64 start, uint64 end, uint256 subWordIndexShift) internal view returns (uint256)

setBit

function setBit(mapping(uint256 => uint256) bitmap, uint256 key, uint64 index, uint256 subWordIndexShift) internal

setBitRange

function setBitRange(mapping(uint256 => uint256) bitmap, uint256 key, uint64 start, uint64 end, uint256 subWordIndexShift) internal

clearBit

function clearBit(mapping(uint256 => uint256) bitmap, uint256 key, uint64 index, uint256 subWordIndexShift) internal

clearBitRange

function clearBitRange(mapping(uint256 => uint256) bitmap, uint256 key, uint64 start, uint64 end, uint256 subWordIndexShift) internal

_wordIndex

function _wordIndex(uint256 key, uint64 index, uint256 subWordIndexShift) private pure returns (uint256)

BytesOps

toAsciiBytes

function toAsciiBytes(uint64 value) internal pure returns (bytes)

bytesMatchAtOffset

function bytesMatchAtOffset(bytes input, bytes target, uint256 offset) internal pure returns (bool)

slice

function slice(bytes input, uint256 start, uint256 end) internal pure returns (bytes)

flatten

function flatten(bytes[] input, uint256 numSegments) internal pure returns (bytes)

IdCodec

_TEMPLATE_SHIFT

uint256 _TEMPLATE_SHIFT

_SET_SHIFT

uint256 _SET_SHIFT

Decoded

struct Decoded {
  uint64 setId;
  uint64 templateId;
  uint64 serialNumber;
}

encodeAsSetMask

function encodeAsSetMask(uint64 setId) internal pure returns (uint256)

encodeAsTemplateMask

function encodeAsTemplateMask(uint64 setId, uint64 templateId) internal pure returns (uint256)

encodeAsTokenId

function encodeAsTokenId(uint64 setId, uint64 templateId, uint64 serialNumber) internal pure returns (uint256)

decodeSetId

function decodeSetId(uint256 tokenId) internal pure returns (uint64)

decodeTemplateId

function decodeTemplateId(uint256 tokenId) internal pure returns (uint64)

decodeSerialNumber

function decodeSerialNumber(uint256 tokenId) internal pure returns (uint64)

decode

function decode(uint256 tokenId) internal pure returns (struct IdCodec.Decoded decoded)

LockManager

This library provides arbitrary bitmap-based locking facilities for Contracts - 0 | 0 | 0 | 0 Sets - 0 | setIdWordIndex | 0 | 0 Templates - 0 | setId | templateIdWordIndex | 0 Serials - 0 | setId | templateId | serialNumberWordIndex In the above table,

  • 0 represents a 64 bit word
  • setId, templateId, serialNumber are 64 bit numbers
  • each value in the mapping
  • a 'word' is a 256 bit segment of the bitmap, LSB aligned
  • *WordIndex is the 64-bit index of the word in the bitmap (i / 256)

_SET_SHIFT

uint256 _SET_SHIFT

_TEMPLATE_SHIFT

uint256 _TEMPLATE_SHIFT

_CONTRACT_KEY

uint256 _CONTRACT_KEY

_SET_BLANK_KEY

uint256 _SET_BLANK_KEY

State

struct State {
  mapping(uint256 => uint256) locks;
}

isContractLocked

function isContractLocked(struct LockManager.State self) internal view returns (bool)

isSetLocked

function isSetLocked(struct LockManager.State self, uint64 setId) internal view returns (bool)

isTemplateLocked

function isTemplateLocked(struct LockManager.State self, uint64 setId, uint64 templateId) internal view returns (bool)

isSerialLocked

function isSerialLocked(struct LockManager.State self, uint64 setId, uint64 templateId, uint64 serialNumber) internal view returns (bool)

checkContractUnlocked

function checkContractUnlocked(struct LockManager.State self) internal view

checkSetUnlocked

function checkSetUnlocked(struct LockManager.State self, uint64 setId) internal view

checkTemplateUnlocked

function checkTemplateUnlocked(struct LockManager.State self, uint64 setId, uint64 templateId) internal view

lockContract

function lockContract(struct LockManager.State self) internal

lockSets

function lockSets(struct LockManager.State self, uint64[] setIds) internal

checkSerialUnlocked

function checkSerialUnlocked(struct LockManager.State self, uint64 setId, uint64 templateId, uint64 serialNumber) internal view

lockSetRange

function lockSetRange(struct LockManager.State self, uint64 start, uint64 end) internal

lockTemplates

function lockTemplates(struct LockManager.State self, uint64 setId, uint64[] templateIds) internal

lockTemplateRange

function lockTemplateRange(struct LockManager.State self, uint64 setId, uint64 start, uint64 end) internal

lockSerials

function lockSerials(struct LockManager.State self, uint64 setId, uint64 templateId, uint64[] serialNumbers) internal

lockSerialRange

function lockSerialRange(struct LockManager.State self, uint64 setId, uint64 templateId, uint64 start, uint64 end) internal

_templateBlankKey

function _templateBlankKey(uint64 setId) private pure returns (uint256)

_serialBlankKey

function _serialBlankKey(uint64 setId, uint64 templateId) private pure returns (uint256)

_indexToWordIndex

function _indexToWordIndex(uint64 index) private pure returns (uint256)

_setIdWordIndex

function _setIdWordIndex(uint64 setId) private pure returns (uint256)

_templateIdWordIndex

function _templateIdWordIndex(uint64 setId, uint64 templateId) private pure returns (uint256)

_serialNumberWordIndex

function _serialNumberWordIndex(uint64 setId, uint64 templateId, uint64 serialNumber) private pure returns (uint256)

UriEncoder

_SET_TAG

bytes _SET_TAG

_TEMPLATE_TAG

bytes _TEMPLATE_TAG

_SERIAL_TAG

bytes _SERIAL_TAG

_MAX_SEGMENTS

uint256 _MAX_SEGMENTS

encode

function encode(string uri, uint64 setId, uint64 templateId, uint64 serialNumber) internal pure returns (string)