Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Non-transferable NFT Standard #359

Closed
wants to merge 8 commits into from
Closed

Conversation

JasperTimm
Copy link

This is a proposal for a new NEP regarding a Non-transferable NFT Standard.

Based on discussions in this thread: https://gov.near.org/t/non-transferable-nft-standard/18227

@JasperTimm JasperTimm requested a review from a team as a code owner May 23, 2022 18:01
neps/nep-0359.md Outdated

The first is setting a standard for an 'authenticated account recovery' process. If such a process, like that described above, were standardised it would give users confidence that their NTNFTs would not be lost if they need to migrate to a new account. It would also enable frontend software to assist users in the account recovery process when they know the contract supports it.

Other future NEPs might focus on more specific metadata which the NTNFT would provide, for specific use-cases. An example could be for when the NTNFT is used for KYC purposes that the metadata should specifically include fields such as `expiry date`, `validity` and `KYC_level`.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The current standards actually account for that. There is e.g. an expires_at field, and specifically for domain-specific data (e.g. KYC), the extra field exists.

The existing issued_at and expired_at would also remove your need for a validity field, e.g. with a user authenticating himself every x months by depositing a yocto, and getting a valid new NTNFT, or the current being extended. I digress however, these details should be left to the implementer. Long story short: No need to extend the metadata.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new validity status was required for use cases where the smart contract owner might need to remove/update a status regardless of the expired_at date.

Example 1: when a KYC provider issues a soulbound NFT as proof, the verified user faces certain charges, and regulators request to limit their ability to access financial services. The issuer would need to inform the relying services about this status change abruptly.

Example 2: a DAO issued the soulbound NFT as a proof of membership; however, when implementing, they wanted the users to owe their proofs of "temporary" membership. However, the user might no longer be actively participating in the DAO. While expired_at could be used, it would give continuous work to the DAO operators, while with validity, the DAO can turn on/off the membership.

Copy link
Contributor

@willemneal willemneal May 23, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One thing that confuses me is the KYC_level. Know Your Customer level sounds funny. In general I have found that KYC has morphed to mean identity verification so it's certainly not a misuse here, just find it strange.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with @willemneal that we shouldn't use terms like KYC. That's such a bizarre term / jargon that probably never should have been invented and certainly doesn't fit here.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there's probably already an understanding that people will customize the metadata for their own uses without explicitly mentioning examples here in this standard. In an effort to keep this as simple as possible it might be better if we simply remove line 163 altogether then.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree with @JasperTimm ^

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the line regarding addn metadata in the latest commit

As each of these attestations would be unique, it also makes sense to build upon the existing infrastructure already built for NFTs by basing this new standard on [NEP-171](./nep-0171.md). This would mean existing software, such as wallets, have 'backwards compatibility' with these tokens, allowing it to display simple details such as title, symbol and images.

In addition, having the non-transferable nature standardised would mean that in the future, software could give users a hint in the UI that these tokens are account bound and disabling any transfer functionality.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non transferrable NFTs are a really bad idea, it's just a spam engine, what if I want to just transfer it to another wallet that I own myself? Can't you just track transfer counts from when you issue a certificate, then dapps can check and identify in their own way? Really ruins the magic of what an NFT is, a fluid moving asset.

All of a sudden we are going to have some NFTs that can transfer and some can't, I can see the confusion cluster-f for platforms now.

If the transfer function is disabled or doesn't meet basic "owner can transfer" mechanics, it should be labeled a noncompliant spam contract.

Forcing platforms to do a UI implementation on a transfer button everywhere and explain why it's disabled increases complexity 100x. Standards need to keep it simple.

You can also just implement a whitelist contract and you are accomplishing the same thing, sort of misses the point of an NFT.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Non transferrable NFTs are a really bad idea, it's just a spam engine, what if I want to just transfer it to another wallet that I own myself?

This is covered pretty extensively already in the standard under dealing with 'new accounts'. Having an nft_transfer function that only works in specific cases (e.g. where the contract owner must also approve) would be more confusing I feel. Implementers are free to implement something like this in a new function though. As we said, we're only suggesting ways for this case to be handled.

Can't you just track transfer counts from when you issue a certificate, then dapps can check and identify in their own way? Really ruins the magic of what an NFT is, a fluid moving asset.

Putting the onus on dapps to check transfer counts and using it to trigger some further validity check certainly feels like more complexity than simply looking for whether a token implements a certain standard in my opinion.

All of a sudden we are going to have some NFTs that can transfer and some can't, I can see the confusion cluster-f for platforms now.

If the transfer function is disabled or doesn't meet basic "owner can transfer" mechanics, it should be labeled a noncompliant spam contract.

Forcing platforms to do a UI implementation on a transfer button everywhere and explain why it's disabled increases complexity 100x. Standards need to keep it simple.

I think @blackghost1987 already responded to this quite well: "if a platform doesn't want to enable/disable the transfer button, they simply won't implement the support for the new NTNFT standard, while keep supporting NEP-171 tokens, so nobody is forcing anyone"

We're not forcing anyone to implement anything. Platforms implementing UIs will implement what their user base demands. If there's broad adoption of this standard, it would make sense to support it better. If not, they won't.

You can also just implement a whitelist contract and you are accomplishing the same thing, sort of misses the point of an NFT.

I get the impression the core of these criticisms stems from what we're currently 'used to' using NFTs for, being transferable by nature. But we also have use cases for something that is quite similar, it's just that it shouldn't be transferable by default. To make it as easy as possible on UI developers, we're trying to use all the existing work they've done interfacing with NFT metadata to make these tokens displayable for users without much effort.

Copy link

@nategeier nategeier Jun 1, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apologies for being mildly rude before, we at the Mintbase team helped build the NEP-171 and this process was extremely time consuming, energy draining and feared getting sucked into the dark hole again.

The "core of these criticisms" stems from being an NFT platform builder in the trenches since 2018 and seeing the fads come and go, knowing that this just adds unnecessary complexity. The basic definition of an NFT: "can be transferred by the owner".

If you want to call it an SBT or anything else that has nothing to do with NFT, I'm good with that, the confusion will be folks getting an NFT certificate (no one will call it an NTNFT) and yelling at the wallets + platforms why can they not transfer it.

I love Vitalik, but the guy largely ignored NFTs until just about a year ago. Where do we stop? Remember when everyone hyped fractional ownership NFTs and then just like that, everyone forgot about it. It's the same here. Can't we just nail single, basic ownership NFTs first past the PFP hype. We still have not sorted interoperability, the main reason why Paras and Mintbase are not mixed perfectly yet. Logs need more work on the standards.

Overall even if we call it SBT or anything, I still think it will die / lose interest either from lack of support by platforms and wallets or people finding other better ways by diving into provenance or nailing decentralized identity.

Maybe a NTNFT is better done once identity gets sorted better down the road, where we don't call it non-transferrable, but only DID identity-webbed transfers are g2g, but right now it's just nice trend marketing.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the response Nate, I can appreciate you've been working in the NFT space for a long time and seen fads come and go. For what it's worth - it certainly feels like there's a need for something LIKE non-transferable NFTs, I'm pretty sure this one is not a fad.

And I think I can agree that what we create now is probably quite different to what decentralized identity will look like in the future. But we try to solve the problems we see today.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want to say that I absolutely agree with @nategeier here. I think it's totally fine for Michael Jordan to sell his high school diploma, and for me to purchase it. But I'm not going to go to MJ's high school reunion and get in, because it's very easy to verify that I'm not actually Michael Jordan. It was minted to MJ and he can do whatever he likes with it. Not to mention, perhaps there's a vast security breach like what happened with solar winds and Microsoft, and someone may no longer trust the private key that was in plain text on their computer. Maybe they just decide they want to move accounts. Or maybe they change their gender identity and no longer want to be tied to a previous account, and should be able to move it at will.

There are companies like The Graph, SubQuery, and NEAR Lake that are making indexing a cinch. It seems like we're pretending like it's hard to figure out whether a person was minted and NFT, but I don't think that's the case at all, and I think I would have to hear a reason why that's such a problem.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lastly know that if this goes through, there is no reason we should not also have a new NEP to remove the transfer function for fungible tokens too. Example:

If I send 100 FT to Tom, he passed the first year of college.
125, he passed 1.25 years of college.
This could be his certificate.

All the arguments here will assume FT is fair game.

@BenKurrek
Copy link
Contributor

I don't really see the need to have this as a separate standard. Usually, standards are put into place to provide a canonical way of doing a common task. This is to prevent different implementations and to encourage interoperability. In this case, I don't really see any utility in standardizing a non transferrable token. There aren't really any changes to metadata, enumeration methods etc...

This proposition, from my eyes, seems as if it's only stripping parts of the existing core NFT standard. If someone wants to make a non-transferrable token, they simply need to remove all the aspects in the NFT standard that pertain to transferring NFTs. I'm not sure having a dedicated standard for non-transferrable tokens is necessary as the implementation is almost trivial.

@blackghost1987
Copy link

I don't really see the need to have this as a separate standard. Usually, standards are put into place to provide a canonical way of doing a common task. This is to prevent different implementations and to encourage interoperability. In this case, I don't really see any utility in standardizing a non transferrable token. There aren't really any changes to metadata, enumeration methods etc...

This proposition, from my eyes, seems as if it's only stripping parts of the existing core NFT standard. If someone wants to make a non-transferrable token, they simply need to remove all the aspects in the NFT standard that pertain to transferring NFTs. I'm not sure having a dedicated standard for non-transferrable tokens is necessary as the implementation is almost trivial.

Yeah, @BenKurrek is right, this is only stripping parts of the existing core NFT standard. Can this be done with NEP-171? Yeah sure. Does that makes this new standard unnecessary? Not at all. It's like saying we shouldn't produce spoons anymore because we already invented sporks... 😄

The transferability is not a core functionality of an NFT, or at least it shouldn't be. There are valid use-cases for NFTs that doesn't need / want transfer. So you should see this from a different standpoint: Why does NEP-171 forces people to implement transfer if they don't want it?

From this standpoint it looks like this standard should have been the original NFT standard, exactly because it's so trivial, and the transfer function should have been an extension for it. It's worth noting that Enumeration and Metadata doesn't do anything with transfer, so transfers (and approvals) are really a totally unrelated part of NEP-171. This is not how it happened originally, because of historical reasons of course. The most well-known use-cases for NFTs were about transfers, so nobody thought about making it optional. I don't think it's realistic to go back now and strip the transfer functions from NEP-171 and put them in a new optional extension... That's why we are proposing a new standard, without touching the well-known and well-supported functionality of NEP-171.

Today if somebody wants to implement a non-transferable NFT, they have two choices: either use NEP-171 but not really conform to it, or don't use any standards at all. Both solutions have many bad consequences. That's the problem we are trying to solve with this PR.

@chadoh
Copy link
Contributor

chadoh commented May 25, 2022

Lots of use-cases are a better fit for non-transferable NFTs than transferable ones. Certifications and reputation are two obvious use-cases. Some in-game items would be, too. I know that @ryancwalsh from the NEAR Education team has been working on certifications for students who complete the NEAR Certified Developer program, and could use this standard.

The current NFT Metadata standard includes a spec field. I agree that this proposal seems like a breaking change to the NFT spec, rather than its own thing. Contracts could represent this by setting their spec to nft-3.0.0, or whatever indicates a breaking change by the time this lands.

@BenKurrek
Copy link
Contributor

I don't really see the need to have this as a separate standard. Usually, standards are put into place to provide a canonical way of doing a common task. This is to prevent different implementations and to encourage interoperability. In this case, I don't really see any utility in standardizing a non transferrable token. There aren't really any changes to metadata, enumeration methods etc...
This proposition, from my eyes, seems as if it's only stripping parts of the existing core NFT standard. If someone wants to make a non-transferrable token, they simply need to remove all the aspects in the NFT standard that pertain to transferring NFTs. I'm not sure having a dedicated standard for non-transferrable tokens is necessary as the implementation is almost trivial.

Yeah, @BenKurrek is right, this is only stripping parts of the existing core NFT standard. Can this be done with NEP-171? Yeah sure. Does that makes this new standard unnecessary? Not at all. It's like saying we shouldn't produce spoons anymore because we already invented sporks... 😄

The transferability is not a core functionality of an NFT, or at least it shouldn't be. There are valid use-cases for NFTs that doesn't need / want transfer. So you should see this from a different standpoint: Why does NEP-171 forces people to implement transfer if they don't want it?

From this standpoint it looks like this standard should have been the original NFT standard, exactly because it's so trivial, and the transfer function should have been an extension for it. It's worth noting that Enumeration and Metadata doesn't do anything with transfer, so transfers (and approvals) are really a totally unrelated part of NEP-171. This is not how it happened originally, because of historical reasons of course. The most well-known use-cases for NFTs were about transfers, so nobody thought about making it optional. I don't think it's realistic to go back now and strip the transfer functions from NEP-171 and put them in a new optional extension... That's why we are proposing a new standard, without touching the well-known and well-supported functionality of NEP-171.

Today if somebody wants to implement a non-transferable NFT, they have two choices: either use NEP-171 but not really conform to it, or don't use any standards at all. Both solutions have many bad consequences. That's the problem we are trying to solve with this PR.

Good point - you've changed my mind :P

@ryancwalsh
Copy link

I really like this point from @blackghost1987 . I think @encody felt similarly when disabling the transferability of the NFT standard for our certificates project.

neps/nep-0359.md Outdated Show resolved Hide resolved
neps/nep-0359.md Outdated Show resolved Hide resolved
neps/nep-0359.md Outdated Show resolved Hide resolved
neps/nep-0359.md Outdated Show resolved Hide resolved
neps/nep-0359.md Outdated Show resolved Hide resolved
neps/nep-0359.md Outdated

For each of these methods, it would presumably be necessary for the service which created the smart contract to make efforts (off-chain) to identify the user. Once they're satisfied the user has identified themselves they could use any of the following methods to invalidate the old NTNFT and, if required, mint a new token (presumably with the same metadata) to the new account.

- The service would burn the NTNFT in the user's old account using: `function burn_token(token_id: string): null {}`. Giving the user access to this function may also be considered - in cases where they still have access to their account users could pre-emptively call this to prevent anyone using their NTNFTs to impersonate them.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There isn't a standard for burning tokens - should we enforce the name of the function here? I think it would be fine to simply say the token should be burnt and an event should be emitted.

Suggested change
- The service would burn the NTNFT in the user's old account using: `function burn_token(token_id: string): null {}`. Giving the user access to this function may also be considered - in cases where they still have access to their account users could pre-emptively call this to prevent anyone using their NTNFTs to impersonate them.
- The service would burn the NTNFT in the user's old account and an `NftBurnLog` should be emitted. Giving the user access to this functionality may also be considered - in cases where they still have access to their account users could pre-emptively do this to prevent anyone using their NTNFTs to impersonate them.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @BenKurrek !

You're right - there's no point in dictating the function signature for a burn here. We had actually discussed the idea of adding a standardised burn function to another NEP I believe. As the events standard is the only mention of burn I think the suggested change works well.

Thanks for the other suggestions as well, I'm happy with them but I'll give @nembal and @blackghost1987 a chance to give them a 👍🏽 before accepting them.

@cif
Copy link

cif commented May 27, 2022

The transferability is not a core functionality of an NFT, or at least it shouldn't be. There are valid use-cases for NFTs that doesn't need / want transfer.

Totally understand the desire to create a standard around access control like use cases so clients can coalesce around them, but what is the motivation for altering current NFT standards for that purpose?

Without the ability transfer a credential, how is that record any better kept as an NFT vs contract state hashed by account?

Clients (and NFT standard!) will need to come a long way before the presentation use case is realized. We could well discover that those clients need to behave different between things like event ticketing and allowing the cops to validate my license when I get pulled over.

So you should see this from a different standpoint: Why does NEP-171 forces people to implement transfer if they don't want it?

I didn't write the spec, but I assume the current standpoint would be that the spec requires transfer because portability is an intrinsic attribute of a token.

Today if somebody wants to implement a non-transferable NFT, they have two choices: either use NEP-171 but not really conform to it, or don't use any standards at all. Both solutions have many bad consequences. That's the problem we are trying to solve with this PR.

As you point out here there not really a good way around having contracts / oracles in the validation process so again, why not delegate this to contract state for specific use cases vs using NFTs?

@nembal
Copy link

nembal commented May 30, 2022

Totally understand the desire to create a standard around access control like use cases so clients can coalesce around them, but what is the motivation for altering current NFT standards for that purpose?

The desire was due to the intrinsic differentiation from transferable NFTs. The two are different in nature and better kept separate. With the introduction (removal) of non-transferability, the community will have a clear playing field to introduce extension building on the core standard. [Burn, Revoke, ZK proofs, nad other offchain data linking methods] without the need to mix in transferability.

Without the ability transfer a credential, how is that record any better kept as an NFT vs contract state hashed by account?

It is easier to work with for developers, plus it has the personalized ability of a JPG that offers a considerable gain when it comes to adoption and recognition. (think of it as a customized proof symbol)

Clients (and NFT standard!) will need to come a long way before the presentation use case is realized. We could well discover that those clients need to behave different between things like event ticketing and allowing the cops to validate my license when I get pulled over.

Sure thing. But event tickets are sometimes issued without locking them to a person, but sometimes they are issued to a single individual removing the option for a secondary market. Having tooling that enables the base case for these distinctive uses is

@mattlockyer
Copy link
Contributor

Add burn for owner please.

https://twitter.com/mattdlockyer/status/1531622257482600448?t=lgHV9Gek5WqEqsTEJaUBDQ&s=09

JasperTimm and others added 3 commits May 31, 2022 16:50
Some small grammar / clarification changes from suggestions

Co-authored-by: Benjamin Kurrek <[email protected]>
Remove addn metadata line and add AKAs for SBTs etc
@JasperTimm
Copy link
Author

Add burn for owner please.

https://twitter.com/mattdlockyer/status/1531622257482600448?t=lgHV9Gek5WqEqsTEJaUBDQ&s=09

We've certainly mentioned it as something that could be added by implementers. In all likelihood I'm sure most people will add it. In an effort to keep this standard as open as possible though, I'm not sure it makes sense to mandate it as part of the standard.

Maybe someone wants to track both positive AND negative attestations/feedback to someone's account, in which case you don't want the user burning them off at their discretion.

@ryancwalsh
Copy link

@JasperTimm So maybe @mattlockyer 's suggestion makes more sense for wallet teams to consider. Instead of just listening to all events about when NFTs were created or transferred, they could also be overridden by the person whose account ID the NFT mentions? So would the person's choice to "hide" a certain NFT then be stored on-chain too? And maybe there would be an option to preemptively block an NFTs from appearing in my wallet unless I allowlist them?

I'm having trouble thinking through which specific problems we (someone) could solve and whether there could be standards for wallets that we'd hope all wallets would follow.

@JasperTimm
Copy link
Author

@JasperTimm So maybe @mattlockyer 's suggestion makes more sense for wallet teams to consider. Instead of just listening to all events about when NFTs were created or transferred, they could also be overridden by the person whose account ID the NFT mentions? So would the person's choice to "hide" a certain NFT then be stored on-chain too? And maybe there would be an option to preemptively block an NFTs from appearing in my wallet unless I allowlist them?

I'm having trouble thinking through which specific problems we (someone) could solve and whether there could be standards for wallets that we'd hope all wallets would follow.

I think you've described my thoughts on this pretty well already @ryancwalsh - it should be something for wallet teams to consider. Adding burn by owner to help with spam implies that's how we want to deal with it - forcing each user to delete each one. IF it becomes a problem, I think a better approach is going to be for wallet teams to use registries to hide/allow an entire contract.

We're just trying to keep this standard as modular as possible. I get the feeling there's a desire for a standardised burn function and we planned on adding such a proposal in the future. I just think it doesn't make sense to add it here.

/****************/

// Returns the token information associated with the given `token_id` or `null` if there is no such token.
function nft_token(token_id: string): Token|null {}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a reason why Vitalik chose a whole new name: SBT, so I don't think any of these function names should keep NFT alone. Maybe change to ntnft_token or sbt_token this goes for the others.

People use these function calls for their indexers and it might confuse. I know we are filtering out by NEP version, but extra padding is good.

I am not against the concept, i really just dont think taking the transfer fucntion out solves the certificate delimenta

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand where you’re coming from Nate but our philosophy from the start has been to keep things as similar as possible to the existing NFT standard to make life easier for implementers. As you mentioned, the NEP number alone should be enough to filter them out.

@frol
Copy link
Collaborator

frol commented Aug 9, 2022

I see a lot of heated discussions and I feel that I agree with all the arguments presented so far. The only contradictory part here is the proposed solution, so I would like to take a step back and sum up all the discussions, but before that, let's get on the same page in the terminology.

NFT (non-fungible token) is a token that is unique. That is all.

ERC-721 has the following abstract:

The following standard allows for the implementation of a standard API for NFTs within smart contracts. This standard provides basic functionality to track and transfer NFTs.

We considered use cases of NFTs being owned and transacted by individuals as well as consignment to third party brokers/wallets/auctioneers (“operators”). NFTs can represent ownership over digital or physical assets. We considered a diverse universe of assets, and we know you will dream up many more:

Physical property — houses, unique artwork
Virtual collectables — unique pictures of kittens, collectable cards
“Negative value” assets — loans, burdens and other responsibilities
In general, all houses are distinct and no two kittens are alike. NFTs are distinguishable and you must track the ownership of each one separately.

Being inspired by Eth ecosystem, NEAR went with NEP-171 by closely following ERC-721 and thus inheriting all the potential problems (see the "we considered" part). I think what we all agree here is that we want standards to be modular and compatible!

There are cases when a web3 service would like to attribute something to a specific address and only that address. In such cases these attestations would no longer be applicable if they were transfered to a different account.

Example use-cases:

  • badges, POAPs
  • proofs of KYC or other verifications
  • credentials
  • ticketing, access control
  • certificates

All of these do not require non-transferability of NFT.

NFT owner is not necessarily the nominated person, e.g. I can hold and transfer a certificate of a friend of mine, but the certificate itself states that it was issued for my friend and transferring this certificate does not make me or a receiver of this NFT any smarter. NFT in all these cases could be something that literally says "proof of that Vlad F (frol.near) passed NEAR certification program", and if I want to, I can transfer this NFT to another account and then root.near will own an NFT that still confirms that "Vlad F (frol.near) passed NEAR certification program".

Thus, it sounds like maybe we want to further standardize the Token metadata of NEP-171 with "nominated account" field.

This brings us to the comments communicated above and in the previous NFT discussions - modularity! I see that in addition to potentially standardizing "nominated person" there are ideas around standardizing burn interface, it might be a need to standardize mint as well; and then why not standardize batch operations and, ultimately, transfer interface through a list of supported features in the contract metadata?

Having this fine control with supported features, we can make NEP-171 to be just a representation of a fixed set of features, and we will never need to spend so much time talking about an extension (in this case it is not even that, we talk about extracting a subset) of the existing standard.

What will it take for me to approve this NEP?

I would like to propose using this question in every NEP review in order to keep the discussion constructive and make sure there is a clear set of expectations that will inform the community about specific concerns and get NEP finally adopted when the major concerns are resolved.

I follow "approve contract standards by default unless they bring risk to the ecosystem" policy, the unresolved items below really block me from confidently vote for approval as I feel tooling out there might get confused with the mixed signals.

  • (The standard meets this requirement) This NEP should not break the existing tooling. Missing nft_transfer* methods should not be a huge problem for the tooling as it should handle potential transfer errors anyway, yet it might still be quite surprising.
  • This NEP must bring improvements over NEP-171 with nft_transfer method that just returns and error on use (in the current state of the standard, tools will either still need to probe nft_transfer or download Wasm contract file for introspection to see if the is a method with such a name exposed)
  • This NEP must not confuse the existing tooling (indexers will miss the events while the contract methods are named the same way as in NEP-171 and users may assume they should behave as any other NEP-171-compatible contract)

Ideally, however, I would love to see an alternative approach of exposing a list of supported features / standards, so we can extend NFTs in the future without breaking changes and adopt them faster.

@cif
Copy link

cif commented Aug 9, 2022

The point I was trying to make earlier on this thread is that without transferability, a significant portion of the literal English definition of a "token" goes away when you consider the use case of "only entity A can only ever possess this credential".

I can transfer this NFT to another account and then root.near will own an NFT that still confirms that "Vlad F (frol.near) passed NEAR certification program".

In this scenario, wouldn't the token contract be paying for storage only to reference an owner for which there is no true meaning or use case?

Our diplomas are printed and framed to hang in our offices and not issued as a pocket sized item we can redeem for a drink at the bar, though the drink token in some cases could be more valuable IMO 😂

Why not lean into a NEAR flavored W3C Verifiable Credentials spec for VC use cases? I agree on all the modularity and extensibility vibes into a standard, maybe eventually NFTs are a transferable subset of the bigger VC ideas being discussed here (zk, wallet, presentation etc)? a la @nembal comment to my OP

IMO the idea of a non-transferable NFT is hard to get behind because the heuristics don't register for me, so far as to say "SBT" or "NTNFT" are both misnomers. That said, change my mind?

Last thought I promise: Vote YES to standardized mint and burn, this would be super helpful in redemption use cases we are currently working on right now.

@ori-near
Copy link
Contributor

ori-near commented Aug 10, 2022

Thank you for your comment, @frol. Discussing and making decisions on NEPs is crucial for helping the protocol evolve. Given the complexity of the protocol and the large number of participants across the ecosystem, the NEP process introduces Working Groups as a way to operationalize the review of NEPs that builds community support. I propose that we use this first NEP as the first one to help bootstrap the Contracts Standards work group.

@abacabadabacaba, @evgenykuzyakov, @mfornet – Could you please fully read this NEP and comment in the thread with any feedback/concerns, and specifically if you approve this NEP? If not, please specify why and what it would take for you to approve it. I can schedule the first working group meeting after your review. Thank you!

@ryancwalsh
Copy link

IMO the idea of a non-transferable NFT is hard to get behind because the heuristics don't register for me, so far as to say "SBT" or "NTNFT" are both misnomers. That said, change my mind?

I think this is a perfect time to invent a new word. Nothing related to souls, tokens, transferability, etc. And not a compound word. Just a brand new word that we define. Googling it will then be super easy too.

@mfornet
Copy link
Member

mfornet commented Aug 13, 2022

Thanks, @JasperTimm, for writing the NEP, and all of you for the insightful discussion. As I see it, there is room for this standard in the ecosystem. Nothing prevents developers from making custom (non-compliant) NEP-171 implementing exactly this (non-transferable nft tokens). The main point of this NEP is to provide a standard mechanism that allows external tools (either on-chain or off-chain) to understand what this contract is about.

Just the existence of this standard increases the complexity for all tools that interact with NFTs (NEP-171), given that it tries to be compatible with NEP-171 (when it makes sense). In this regard, there should be an explicit intention to make life as easy as possible for current and future tools that use NFTs.

Interface Detection

I feel that something is missing that helps dapps interacting with it understand that this is about Non-transferable NFTs. Currently, it relies on Events or, optionally, on Token Metadata.

IMO neither of those entirely solves the problem in question. They depend on the existence of some token (or transaction) to figure out which standard is implemented. This problem should probably be resolved as part of a different standard that supports Standard Interface Detection (similar to EIP-165).

Otherwise, a custom method could be provided with global metadata of the contract. Something like:

interface ContractMetadata {
    standard: "nep359",
    version: "1.0.0",
    mint_allowed: boolean,
    burn_allowed: boolean,
}

fn *_get_metadata() -> ContractMetadata

This is not blocking on my end from approving this NEP. I guess that most tools use on-chain events to detect the tokens in the first place. Having this built-in mechanism would allow on-chain contracts to decide whether they want to support the contract or not.

Burn method

On the idea of making life as easy as possible for other tools, there should be a mechanism that tells if this token can be burnt or not. Some tools like wallets might provide an option to filter out all non-transferable non-burnable tokens. See previous ContractMetadata as a potential solution.

@ori-near
Copy link
Contributor

Hi everyone! We are hosting the first Contract Standards Working Group meeting next week to discuss this NEP! Please register below.

Meeting Info
📅 Date: Monday, Aug 22, 5pm UTC
🗒️ Topic: NEP 359 – NT NFT Standard
✏️ Register: https://bit.ly/contract_standards

What are Working Groups?
An initiative to bootstrap a way to review NEPs that builds community support and contributes to the NEAR protocol and standards. You can learn more about NEPs and the working groups here: https://near.org/working-groups/.

@JasperTimm
Copy link
Author

Hi all,

Some really helpful discussions so far, thanks for all the responses, I've tried following all of them. I'm sure this will all be discussed in the upcoming working group, but as a prelude I hoped to respond to a couple of points I thought were important.

@frol mentioned them already:

This NEP must bring improvements over NEP-171 with nft_transfer method that just returns and error on use (in the current state of the standard, tools will either still need to probe nft_transfer or download Wasm contract file for introspection to see if the is a method with such a name exposed)

I think @mfornet's response already matches my view - I feel like adding a standard for interface detection would be a good way to handle this, but I hope not having it would not prevent this standard from being approved.

Maybe a follow up question should be: how are tools currently detecting whether an account has an NFT?

I looked up NEAR wallet's implementation for this: https://github.com/near/near-wallet/blob/master/packages/frontend/docs/NonFungibleTokenDiscovery.md

NOTE: I'm not trying to criticize here, merely point out that NFT discovery is not an easy or solved problem and that this new standard is not somehow 'breaking' this.

To quote the relevant part then:

The wallet will consider contracts as non-fungible token contracts relevant to the user if they meet any of the following conditions:

  • Any account makes a call to the contract with any method prefixed with nft_ and the receiver_id property of the args is the user's account ID.

  • The contract emits a Non-Fungible Token Event with NftTransferLog data and the new_owner_id value is the user's account ID.

I presume the first point was inspired by nft_transfer, but assuming we want to capture mints as well as transfers, that would assume our mint function was called something like nft_mint and had an argument named receiver_id. And whilst that is used in an example (https://github.com/near-examples/NFT/blob/master/nft/src/lib.rs#L92), it's not explicitly part of the standard... standardising mint and burn functions (as has been mentioned) would help here.

I'm not sure why an NftMintLog event is not being captured here. But if it did, the standard field in the event would list which NEP standard it is, giving clarification.

Which brings us nicely to the second point, which has been mentioned by a few people:

This NEP must not confuse the existing tooling (indexers will miss the events while the contract methods are named the same way as in NEP-171 and users may assume they should behave as any other NEP-171-compatible contract)

So I looked up the implementation for the most common NEAR indexer. From what I understand, NEAR lake (https://github.com/near/near-lake-indexer) will eventually replace the existing NEAR indexer for NEAR Explorer. But using the existing indexer for now, it looks like Events are explicitly separated by the standard field: https://github.com/near/near-indexer-for-explorer/blob/master/src/db_adapters/assets/event_types.rs#L4

Am I missing something here?

@frol
Copy link
Collaborator

frol commented Aug 19, 2022

@JasperTimm Good point on general problem of interface detection.

I'm not sure why an NftMintLog event is not being captured here. But if it did, the standard field in the event would list which NEP standard it is, giving clarification.

The Wallet doc was not accurate, so I submitted near/near-wallet#2886 PR. TL;DR: Wallet takes into account MINT events as well.

I feel like adding a standard for interface detection would be a good way to handle this, but I hope not having it would not prevent this standard from being approved.

Unfortunately, lack of interface detection led us into this state where Wallet historically needed to identify NFT standards probabilistically (since there was no Events standard at that time, and thus there was no reasonable way to index NFT contracts). After NFT contract is found with this probabilistic model, Wallet attempts to use nft_token and nft_transfer* methods.

Merging this standard without interface detection will pose a lot more complications on the tooling and make it even more probabilistic and thus users interactions may fail "unexpectedly". Thus, I see is as a risk to the ecosystem making it more fragile than it is necessary.

But using the existing indexer for now, it looks like Events are explicitly separated by the standard field

This is also implicit identification, though it is much better than trying to rely on nft_* method names, and while Indexers attempt to solve the problem even in introspection, I don't want to throw even more problems into this space as currently tooling already need to use old and hacky identification and new one that not yet completely covers all the probabilistic discovered contracts.

I lean towards the following decision (I ask other work group members only read this after they submit their considerations)

I would really love to see the interface discoverability NEP where among other things one could specify that the contract does not support transfers.

I hate to say it, but having all the risks I mentioned above, I lean towards rejecting this proposal.

One good thing I want to say is that with @ori-near and work groups dedicated to NEPs, we can now iterate quicker, and I can see that new NEP could go through the process faster then ever.

@ori-near
Copy link
Contributor

Thank you to everyone who attended the first Contract Standards working group meeting today! The working group members reviewed the NEP and reached the following consensus:

Status: Rejected
[x] @mfornet
[x] @frol
[x] @abacabadabacaba

Meeting Recording:
https://youtu.be/6Tok9_iwtYk

@ori-near ori-near closed this Aug 23, 2022
@frol
Copy link
Collaborator

frol commented Aug 23, 2022

@JasperTimm I would like to take another chance to thank you for the contribution and exploring the space together!

As we discussed previously in the comments, and during the working group meeting, it would be great to define the a NEP for the NFT interfaces discovery (transfer, mint, burn). I am happy to join the discussion early on, just cc me on the forum.

@frol frol mentioned this pull request Sep 14, 2022
2 tasks
@ori-near ori-near added S-approved A NEP that was approved by a working group. S-rejected A NEP that was rejected by a working group. WG-contract-standards Contract Standards Work Group should be accountable and removed S-approved A NEP that was approved by a working group. labels Sep 22, 2022
@ori-near ori-near added the A-NEP A NEAR Enhancement Proposal (NEP). label Dec 20, 2022
@frol
Copy link
Collaborator

frol commented Dec 21, 2022

Hey everyone, I want to bring to your attention that @robert-zaremba championed a new NEP for SBT here #393. Please, take a look!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-NEP A NEAR Enhancement Proposal (NEP). S-rejected A NEP that was rejected by a working group. WG-contract-standards Contract Standards Work Group should be accountable
Projects
Status: REJECTED
Development

Successfully merging this pull request may close these issues.