Skip to main content

CEP-78 Enhanced NFT Standard Introduction

Usage

Building the Contract

The main.rs file within the contract provides the installer for the NFT contract. Users can compile the contract to Wasm using the make build-contract command from the Makefile provided.

The pre-built Wasm for the contract and all other utility session code can be found as part of the most current release. Users wishing to build the Wasm themselves can pull the code and use the make build-contract command provided in the Makefile. Please note, however, that you must install wasm-strip to build the contract.

The call method will install the contract with the necessary entrypoints and call the init() entrypoint, which allows the contract to self-initialize and set up the necessary state variables for operation.

Required Runtime Arguments

The following are the required runtime arguments that must be passed to the installer session code to correctly install the NFT contract. For more information on the modalities that these arguments set, please refer to the Modalities documentation.

  • "collection_name": The name of the NFT collection, passed in as a String. This parameter is required and cannot be changed post installation.
  • "collection_symbol": The symbol representing a given NFT collection, passed in as a String. This parameter is required and cannot be changed post installation.
  • "total_token_supply": The total number of NFTs that a specific instance of a contract will mint passed in as a U64 value. This parameter is required.
  • "ownership_mode": The OwnershipMode modality that dictates the ownership behavior of the NFT contract. This argument is passed in as a u8 value and is required at the time of installation.
  • "nft_kind": The NFTKind modality that specifies the off-chain items represented by the on-chain NFT data. This argument is passed in as a u8 value and is required at the time of installation.
  • "json_schema": The JSON schema for the NFT tokens that will be minted by the NFT contract passed in as a String. This parameter is required if the metadata kind is set to CustomValidated(3) and cannot be changed post installation.
  • "nft_metadata_kind": The base metadata schema for the NFTs to be minted by the NFT contract. This argument is passed in as a u8 value and is required at the time of installation.
  • "identifier_mode": The NFTIdentifierMode modality dictates the primary identifier for NFTs minted by the contract. This argument is passed in as a u8 value and is required at the time of installation.
  • "metadata_mutability": The MetadataMutability modality dictates whether the metadata of minted NFTs can be updated. This argument is passed in as a u8 value and is required at the time of installation.

The following are the optional parameters that can be passed in at the time of installation.

  • "minting_mode": The MintingMode modality that dictates the access to the mint() entry-point in the NFT contract. This is an optional parameter that will default to restricting access to the installer of the contract. This parameter cannot be changed once the contract has been installed.

  • "allow_minting": The "allow_minting" flag allows the installer of the contract to pause the minting of new NFTs. The allow_minting is a boolean toggle that allows minting when true. If not provided at install the toggle will default to true. This value can be changed by the installer by calling the set_variables() entrypoint.

  • "whitelist_mode": The WhitelistMode modality dictates whether the contract whitelist can be updated. This optional parameter will default to an unlocked whitelist that can be updated post installation. This parameter cannot be changed once the contract has been installed.

  • "holder_mode": The NFTHolderMode modality dictates which entities can hold NFTs. This is an optional parameter and will default to a mixed mode allowing either Accounts or Contracts to hold NFTs. This parameter cannot be changed once the contract has been installed.

  • "contract_whitelist": The contract whitelist is a list of contract hashes that specifies which contracts can call the mint() entrypoint to mint NFTs. This is an optional parameter which will default to an empty whitelist. This value can be changed via the set_variables post installation. If the whitelist mode is set to locked, a non-empty whitelist must be passed; else, installation of the contract will fail.

  • "burn_mode": The BurnMode modality dictates whether minted NFTs can be burnt. This is an optional parameter and will allow tokens to be burnt by default. This parameter cannot be changed once the contract has been installed.

  • "owner_reverse_lookup_mode": The OwnerReverseLookupMode modality dictates whether the lookup for owners to token identifiers is available. This is an optional parameter and will not provide the lookup by default. This parameter cannot be changed once the contract has been installed.

  • "events_mode": The EventsMode modality selects the event schema used to record any changes that occur to tokens issued by the contract instance.

  • "additional_required_metdata": An additional metadata schema that must be included. This argument is passed in as a u8 value.

  • "optional_metdata": An optional metadata schema that may be included. This argument is passed in as a u8 value.

Example deploy

The following is an example of installing the NFT contract via a deploy using the Rust CLI Casper client. You can find more examples here.

casper-client put-deploy -n http://65.108.0.148:7777/rpc --chain-name "casper-test" --payment-amount 500000000000 -k keys/secret_key.pem --session-path contract/target/wasm32-unknown-unknown/release/contract.wasm \
--session-arg "collection_name:string='enhanced-nft-1'" \
--session-arg "collection_symbol:string='ENFT-1'" \
--session-arg "total_token_supply:u64='10'" \
--session-arg "ownership_mode:u8='0'" \
--session-arg "nft_kind:u8='1'" \
--session-arg "json_schema:string='nft-schema'" \
--session-arg "allow_minting:bool='true'" \
--session-arg "owner_reverse_lookup_mode:u8='0'" \
--session-arg "nft_metadata_kind:u8='2'" \
--session-arg "identifier_mode:u8='0'" \
--session-arg "metadata_mutability:u8='1'"

Utility Session Code

Specific entrypoints in use by the current implementation of the NFT contract require session code to accept return values passed by the contract over the Wasm boundary. In order to help with the installation and use of the NFT contract, session code for such entrypoints has been provided. It is recommended that users and DApp developers attempting to engage with the NFT contract do so with the help of the provided utility session code. The session code can be found in the client folder within the project folder.

Entrypoint nameSession code
"mint"client/mint_session
"balance_of"client/balance_of_session
"get_approvedclient/get_approved_session
"owner_of"client/owner_of_session
"transfer"client/transfer_session

Checking Token Ownership

Learn to check token ownership starting with version v1.1.1. The OwnerReverseLookupMode modality must be set to Complete as described here.

Upgrading to Version 1.1.1

Upgrade to v1.1.1 using a Standard NamedKey Convention or a Custom NamedKey Convention.

Installing and Interacting with the Contract using the Rust Casper Client

You can find instructions on installing an instance of the CEP-78 contract using the Rust CLI Casper client here.

Test Suite and Specification

The expected behavior of the NFT contract implementation is asserted by its test suite found in the tests folder. The test suite and the corresponding unit tests comprise the specification around the contract and outline the expected behaviors of the NFT contract across the entire range of possible configurations (i.e modalities and toggles like allow minting). The test suite ensures that as new modalities are added, and current modalities are extended, no regressions and conflicting behaviors are introduced. The test suite also asserts the correct working behavior of the utility session code provided in the client folder. The tests can be run by using the provided Makefile and running the make test command.

Error Codes

CodeError
1InvalidAccount
2MissingInstaller
3InvalidInstaller
4UnexpectedKeyVariant
5MissingTokenOwner
6InvalidTokenOwner
7FailedToGetArgBytes
8FailedToCreateDictionary
9MissingStorageUref
10InvalidStorageUref
11MissingOwnerUref
12InvalidOwnersUref
13FailedToAccessStorageDictionary
14FailedToAccessOwnershipDictionary
15DuplicateMinted
16FailedToConvertCLValue
17MissingCollectionName
18InvalidCollectionName
19FailedToSerializeMetaData
20MissingAccount
21MissingMintingStatus
22InvalidMintingStatus
23MissingCollectionSymbol
24InvalidCollectionSymbol
25MissingTotalTokenSupply
26InvalidTotalTokenSupply
27MissingTokenID
28InvalidTokenIdentifier
29MissingTokenOwners
30MissingAccountHash
31InvalidAccountHash
32TokenSupplyDepleted
33MissingOwnedTokensDictionary
34TokenAlreadyBelongsToMinterFatal
35FatalTokenIdDuplication
36InvalidMinter
37MissingMintingMode
38InvalidMintingMode
39MissingInstallerKey
40FailedToConvertToAccountHash
41InvalidBurner
42PreviouslyBurntToken
43MissingAllowMinting
44InvalidAllowMinting
45MissingNumberOfMintedTokens
46InvalidNumberOfMintedTokens
47MissingTokenMetaData
48InvalidTokenMetaData
49MissingApprovedAccountHash
50InvalidApprovedAccountHash
51MissingApprovedTokensDictionary
52TokenAlreadyApproved
53MissingApproveAll
54InvalidApproveAll
55MissingOperator
56InvalidOperator
57Phantom
58ContractAlreadyInitialized
59MintingIsPaused
60FailureToParseAccountHash
61VacantValueInDictionary
62MissingOwnershipMode
63InvalidOwnershipMode
64InvalidTokenMinter
65MissingOwnedTokens
66InvalidAccountKeyInDictionary
67MissingJsonSchema
68InvalidJsonSchema
69InvalidKey
70InvalidOwnedTokens
71MissingTokenURI
72InvalidTokenURI
73MissingNftKind
74InvalidNftKind
75MissingHolderMode
76InvalidHolderMode
77MissingWhitelistMode
78InvalidWhitelistMode
79MissingContractWhiteList
80InvalidContractWhitelist
81UnlistedContractHash
82InvalidContract
83EmptyContractWhitelist
84MissingReceiptName
85InvalidReceiptName
86InvalidJsonMetadata
87InvalidJsonFormat
88FailedToParseCep78Metadata
89FailedToParse721Metadata
90FailedToParseCustomMetadata
91InvalidCEP78Metadata
92FailedToJsonifyCEP78Metadata
93InvalidNFT721Metadata
94FailedToJsonifyNFT721Metadata
95InvalidCustomMetadata
96MissingNFTMetadataKind
97InvalidNFTMetadataKind
98MissingIdentifierMode
99InvalidIdentifierMode
100FailedToParseTokenId
101MissingMetadataMutability
102InvalidMetadataMutability
103FailedToJsonifyCustomMetadata
104ForbiddenMetadataUpdate
105MissingBurnMode
106InvalidBurnMode
107MissingHashByIndex
108InvalidHashByIndex
109MissingIndexByHash
110InvalidIndexByHash
111MissingPageTableURef
112InvalidPageTableURef
113MissingPageLimit
114InvalidPageLimit
115InvalidPageNumber
116InvalidPageIndex
117MissingUnmatchedHashCount
118InvalidUnmatchedHashCount
119MissingPackageHashForUpgrade
120MissingPageUref
121InvalidPageUref
122CannotUpgradeWithZeroSupply
123CannotInstallWithZeroSupply
124MissingMigrationFlag
125InvalidMigrationFlag
126ContractAlreadyMigrated
127UnregisteredOwnerInMint
128UnregisteredOwnerInTransfer
129MissingReportingMode
130InvalidReportingMode
131MissingPage
132UnregisteredOwnerFromMigration
133ExceededMaxTotalSupply
134MissingCep78PackageHash
135InvalidCep78InvalidHash
136InvalidPackageHashName
137InvalidAccessKeyName
138InvalidCheckForUpgrade
139InvalidNamedKeyConvention
140OwnerReverseLookupModeNotTransferable
141InvalidAdditionalRequiredMetadata
142InvalidOptionalMetadata
143MissingOptionalNFTMetadataKind
144InvalidOptionalNFTMetadataKind
145MissingAdditionalNFTMetadataKind
146InvalidAdditionalNFTMetadataKind
147InvalidRequirement
148MissingEventsMode
149InvalidEventsMode
150CannotUpgradeToMoreSupply
151MissingOperatorDict
152MissingApprovedDict
153MissingSpenderAccountHash
154InvalidSpenderAccountHash
155MissingOwnerTokenIdentifierKey
156InvalidTransferFilterContract
157MissingTransferFilterContract
158TransferFilterContractNeedsTransferableMode
159TransferFilterContractDenied
160MissingACLWhiteList
161InvalidACLWhitelist
162EmptyACLWhitelist