Call for Participation: NFT Token Standard Working Group [Status Updated]

A few notes on our implementation of ICRC7 for the origyn nft here: ICRC-7: Minimal Non-Fungible Token (NFT) Standard · Issue #7 · dfinity/ICRC · GitHub

Icrc7 Implementation Notes

Last week we implemented the current draft of the ICRC7 standard into the ORIGYN NFT.

While we have been working with the working group to help develop ICRC7, ORIGYN foundation has taken a stance since the beginning that we think that the general principles behind ICRC7 exacerbate the inherent issues with NFTs that arose out of the limitations of the Ethereum architecture and that the group should instead focus on an NFT standard that utilizes the full potential of the IC ecosystem.

The group is now discussing that with ICRC8 and we’re progressing well. Since the group wanted to do a more eth-like standard in ICRC7, we participated and contributed to its development as best as we felt the standard could be developed. We have every intention of supporting whatever standards are approved, just as we already support the EXT standard and the DIP721 standard. In that spirit, we undertook to implement the ICRC7 standard into the existing implementation of the origyn_nft standard. As is usually the case, some issues with a system won’t be seen until you actually try to implement it. In that spirit, the following is our implementation report of ICRC7 which we hope will be helpful in finalizing the standard.

icrc7_owner_of query - It seems odd that this does not have a result response. Since it is possible to request the owner of a token_id that does not exist, the best we could do was trap if the token doesn’t exist. It may make more sense for this function(and perhaps the other query functions that let you request a response for a token id that may not exist to have a return type of

{
#Ok(return_type);
#Err({
#NotFound;
#GenericError({
message: Text;
error_code: Nat})
};
}

Metadata Limitations - We’ve proposed elsewhere the ICRC16 standard for recursive, candid like, extensible metadata. We’d repropose it be considered here. We recently updated it so that can be a supertype of the ICRC3 transaction event type metadata and it makes sense to do the same here. Because we didn’t really have the control we wanted here(for example, we have a manager array and with no way to return a manager we were faced with having to have list of “com.origyn.manager.1”,“com.origyn.manager.2”,“com.origyn.manager.X…”. There is also not a Principal type which is odd considering how much principals are used in the IC(you can convert to Blob, but it is going to be really messy to read on transaction logs). Text is another option but takes more space). We chickened out and have one “metadata” field that is the json text representation of our nested, recursive metadata.

Versions evolve - The icrc7_supported_standards has a return of vec [(Name, URL)]. It may be that some standards evolve and thus end up with a version number. (we are already on origyn_nft v0.1.5 which does have some differences). We think this schema can support that with different URLs, but a version field might be worth a second consideration.

No way to get all token IDs - the collection metadata query does not return the token ids and there is no other query function to do so. We’d recommend an ircr7_token_ids( opt {skip: Nat; take: Nat}) to allow paginating IDs. I think there is an assumption that tokenids will be sequential and from 0 to total_supply-1, but this is not how we implement it. Origyn_nft has text based token_ids for readability and human cognition and recognisability. We convert these strings to a Nat when we implement ICRC7 or DIP721 and they are not sequential.

Is_atomic in transfer args - We do a number of potentially async functions when transferring around NFTs, including KYC, paying royalties, recognizing deposits, etc. Atomicity is not something we can support, and we’d argue that any sufficiently interesting or complex system with real-world utility is going to have the same problem on the IC. Encouraging that atomicity is possible/reliable is creating a very hard-to-untie knot for developers. This can become especially troublesome for generic 3rd party services that may assume you have atomicity when you actually don’t. We chose to reject any request for transfer where atomicity is requested.

Multiple token transfers but singular response - We keep separate ledgers for each token id. We could support batch transfer requests(and in fact do support this in the origyn_nft standard), but each transfer will have its own response. The fact that the standard assumes a singular response from this function is odd. As a result, we are currently rejecting any request for more than one token_id at a time.

Approve - Origyn NFTs see an existing escrow of tokens as the approval of a transfer as a market transaction. As a result, this function doesn’t have enough information in the event args to make sense to an origyn_nft and we trap automatically.

Metadata unification - The Collection metadata is hard coded to an object type, but the NFT metadata is extensible. Perhaps the Collection metadata should use the same format as NFT metadata?

Royalties - royalties were awkward to implement. We support a menu of royalty recipients and distinguish between primary and secondary markets. ICRC7 lets you pick one pay-to-account and one amount. We chose to sum up the secondary royalties and created a sub-account on the canister to direct these two. We can, in the future create a system for distributing anything sent to this account, but given that all transfers happen through our in-nft market mechanism the royalties would be auto-distributed. As a result, anything sent here was probably done by mistake. We’ll propose a better way to report this info in ICRC8, and there may not be a solution here because the demand is for simplicity. One solution might be to just move this to collection metadata if it is adjusted to be extensible considering this standard is just asking marketplace to honor this and there is no actual assumed enforcement mechanism.

Supply Cap - We don’t really have this concept(supply is controlled by the minter, so if you built some kind of capped supply you’d need to program that in the minting contract). We return null.

3 Likes