Skip to content

Latest commit

 

History

History
280 lines (199 loc) · 9.47 KB

adr-004.md

File metadata and controls

280 lines (199 loc) · 9.47 KB

Transition to Cosmos SDK's NFT module

Changelog

  • 04-11-2021: Initial Draft
  • 09-03-2022: Clarification on backwards incompatibility

Context

Currently, Cronos.org Chain offers support for non-fungible tokens (NFTs) using a custom NFT module in chain-main. The current implementation of NFT module is based on Irismod's NFT module. Given that different chains are using their custom implementation of NFT module, it is very difficult to achieve flawless interportability of NFTs across multiple chains using IBC. At the same time, there are more usecases that need to be supported using NFTs which may require IBC support. So, there is a need of a standardized NFT implementation which has support for reusing NFTs between modules and chains.

Decision

There are multiple ways to address above mentioned issues.

  1. Use Cosmos SDK's NFT module

    To solve interportablity and standardisation issues, we can adopt Cosmos SDK's NFT module which is expected to become standard for implementing NFTs on Cosmos SDK chains and also expected to get support for transferring NFTs via IBC.

    More details on interportability of Cosmos SDK's NFT module here

    To migrate all the NFTs in current NFT module to new Cosmos SDK NFT module, we can use in-place store migration (outlined in ADR 41).

    Advantages

    • Because this module is a part of Cosmos SDK, it'll get all the future improvement for free.
    • Much easier upgrades to newer versions of NFT module as the upgrades will be tested extensively by the community.

    Drawbacks

    • It'll become a bit difficult to add custom logic (especially when transferring NFTs) based on our requirements.
  2. Modify current NFT implementation in chain-main

    Cosmos SDK's NFT module ADR outlines the API contract implemented by NFT module.

    Advantages

    • It'll be very easy to add custom logic base on our requirements (for example, irisnet/irismod#183).

    Drawbacks

    • Because this module will be developed in isolation, we'll have to work extra hard to make sure that it confirms to Cosmos SDK's NFT standards.
    • Custom logic added to the module may make it impossible to stay in sync with Cosmos SDK's standards.

This ADR proposes the adoption of Option 1 to use native Cosmos SDK's NFT module.

Cosmos SDK's NFT module

Cosmos SDK's NFT module provides only one message type that can be used to send NFTs to someone.

service Msg {
  rpc Send(MsgSend) returns (MsgSendResponse);
}

message MsgSend {
  string class_id = 1;
  string id       = 2;
  string sender   = 3;
  string reveiver = 4;
}
message MsgSendResponse {}

This is similar to TransferNFT in current implementation.

service Msg {
   rpc TransferNFT(MsgTransferNFT) returns (MsgTransferNFTResponse);
}

message MsgTransferNFT {
  string id = 1;
  string denom_id = 2;
  string sender = 3;
  string recipient = 4;
}

message MsgTransferNFTResponse {}

denom_id in current implementation can directly be mapped to class_id and receipient can be mapped to receiver of Cosmos SDK's NFT module request.

Besides this, Cosmos SDK's NFT module specifies multiple message types that should be implemented by wrapper module.

  • MsgNewClass - Receive the user's request to create a class, and call the NewClass of the x/nft module.
  • MsgUpdateClass - Receive the user's request to update a class, and call the UpdateClass of the x/nft module.
  • MsgMintNFT - Receive the user's request to mint a nft, and call the MintNFT of the x/nft module.
  • BurnNFT - Receive the user's request to burn a nft, and call the BurnNFT of the x/nft module.
  • UpdateNFT - Receive the user's request to update a nft, and call the UpdateNFT of the x/nft module.

Backwards Compatibility

MsgIssueDenom

service Msg {
  rpc IssueDenom(MsgIssueDenom) returns (MsgIssueDenomResponse);
}

message MsgIssueDenom {
  string id = 1;
  string name = 2;
  string schema = 3;
  string sender = 4;
}

message MsgIssueDenomResponse {}

To implement MsgIssueDenom:

  • id can be mapped to id field of Class
  • name can be mapped to name field of Class
  • schema can be mapped to data field of Class
  • There is no field for storing sender information in Class so, sender information must be injected in data field of Class

Once the Class object is prepared, we can call NewClass of x/nft module.

MsgMintNFT

service Msg {
  rpc MintNFT(MsgMintNFT) returns (MsgMintNFTResponse);
}

message MsgMintNFT {
  string id = 1;
  string denom_id = 2;
  string name = 3;
  string uri = 4;
  string data = 5;
  string sender = 6;
  string recipient = 7;
}

message MsgMintNFTResponse {}

To implement MsgMintNFT:

  • id can be mapped to id field of NFT
  • denom_id can be mapped to class_id field of NFT
  • uri can be mapped to uri field of NFT
  • Since there is no field for name in NFT, we'll have to inject name in data field of NFT
  • Owners in Cosmos SDK's NFT module are tracked differently. So, we do not have to set owner (it does not exist) field in NFT
  • data can be mapped to data field in NFT

Once the NFT object is prepared, we can call MintNFT of x/nft module.

MsgEditNFT

service Msg {
  rpc EditNFT(MsgEditNFT) returns (MsgEditNFTResponse);
}

message MsgEditNFT {
  string id = 1;
  string denom_id = 2;
  string name = 3;
  string uri = 4;
  string data = 5;
  string sender = 6;
}

message MsgEditNFTResponse {}

To implement MsgEditNFT:

  • id can be mapped to id field of NFT
  • denom_id can be mapped to class_id field of NFT
  • uri can be mapped to uri field of NFT
  • Since there is no field for name in NFT, we'll have to inject name in data field of NFT
  • data can be mapped to data field in NFT

Once the NFT object is prepared, we can call the UpdateNFT of x/nft module.

MsgTransferNFT

service Msg {
  rpc TransferNFT(MsgTransferNFT) returns (MsgTransferNFTResponse);
}

message MsgTransferNFT {
  string id = 1;
  string denom_id = 2;
  string sender = 3;
  string recipient = 4;
}

message MsgTransferNFTResponse {}

Message to transfer the ownership of NFT is directly provided by Cosmos SDK's NFT module using MsgSend. To implement MsgTransferNFT:

  • id can be mapped to id of MsgSend
  • denom_id can be mapped to class_id of MsgSend
  • sender can be mapped to sender of MsgSend
  • recipient can be mapped to receiver of MsgSend

Once MsgSend object is created, we can call the Send of x/nft module.

MsgBurnNFT

service Msg {
  rpc BurnNFT(MsgBurnNFT) returns (MsgBurnNFTResponse);
}

message MsgBurnNFT {
  string id = 1;
  string denom_id = 2;
  string sender = 3;
}

message MsgBurnNFTResponse {}

To implement MsgBurnNFT, we can directly call the BurnNFT of x/nft (after performing validations).

Backwards incompatibility

It is possible to support all the transactions and queries in a backwards compatible way except for DenomByName query. Because current implementation of NFT module specifies denom_name as a unique parameter unlike Cosmos SDK's native x/nft module, it is not possible to support a query which returns single Denom object with given denom_name.

Deprecation Plan

On the release of new wrapper NFT module on Cronos.org chain, all the above messages should be considered as deprecated and will be removed in approx. 3 months via an upgrade. After the upgrade, the messages specified by Cosmos SDK's NFT module will handle all the operations.

Status

Proposed

Consequences

Positive

Cosmos SDK's module will have support from multiple members of the community and will get all the future improvements for free (for example, IBC support, inter-module asset support using ADR-33)

Negative

  • Our current implementation is slightly different from Cosmos SDK's NFT module which can result in backwards incompatibility. This can be temporarily avoided by creating a wrapper module (which we anyway need to create for minting and burning NFTs) and adding same messages as the current module along with the sandard message types mentioned here. But, it is necessary to have a deprecation plan for old message types and transition all the downstream services to new standardized message types.
  • There'll be a lot of duplicate message types until legacy messages are removed.

Neutral

Our current implementation is very similar to Cosmos SDK's NFT module implementation and all the usecases currently supported by Cronos.org Chain can easily be supported using new module.

References