NFT Standard Discussion

Over the weekend I was spitballing with Nate and want to clarify something. The terms “escrow” and “approvals” are, in my mind, synonymous, but I believe in this discussion “escrow” is used to refer to the separate contract keeping track of approvals. That’s okay and I can work with that. I think this is the core item we’re discussing: to separate or to not separate the approvals.

We can separate these concerns but not enforce that they live in separate contracts, letting developers do as they prefer. So you can put both standards in the same contract if you want, the same way that a fungible token has the “core” and “metadata” standards in one contract. The two standards:

  1. NFT Core standard — only the basic mapping between owners and tokens, and the necessary token info, including nft_transfer and nft_transfer_call. (May or may not use Storage Management standard)
  2. Approval standard — this uses the familiar approve per Token ID (which is critical and missing from NEP4) and would include the Storage Management standard.

NFT Core standard only

pub struct Token {
    pub owner_id: AccountId,
    pub metadata: String,
}

pub struct Core {
    /// TokenID » Token object
    pub tokens: LookupMap<TokenId, Token>,
    …
}

NFT Core + Approval standards (same contract)

pub struct Token {
  pub owner_id: AccountId,
  pub approver_id: AccountId, // Always env::current_account_id()
  pub metadata: String,
  pub approvals: Vec<AccountId>, // Can add this field here or elsewhere
}

impl Contract {
  pub fn get_approvals(&self, token_id: String) -> Vec<AccountId> {}
  …
}

NFT Core + Approval standards (separate contracts)

NFT Core contract

pub struct Token {
  pub owner_id: AccountId,
  pub approver_id: AccountId, // Points to another contract
  pub metadata: String,
}

Approvals contract

// NFT Contract + ID. Example: "volcano-art:19"
pub type ContractTokenId = String;

pub struct Approvals {
  pub approval_map: LookupMap<ContractTokenId, UnorderedSet<AccountId>>,
}

Let’s remember that standards are primarily defining the methods. What parameters they take, what functionality they do, when they should fail, what they should return. As long as the required functions on the standard are behaving in a way consistent with the spec, we can have both the options outlined above.

3 Likes