-
Notifications
You must be signed in to change notification settings - Fork 140
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
Changes from all commits
ac375df
213dbca
f48bed2
5a4c11f
86f7d1f
fb5e794
ee8b83f
235be55
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,166 @@ | ||
--- | ||
NEP: 359 | ||
Title: Non-transferable NFT Standard | ||
Author: Jasper Timm <[email protected]>, Sándor Juhász <[email protected]>, Balazs Nemethi <[email protected]> | ||
DiscussionsTo: https://github.com/nearprotocol/neps/pull/359 | ||
Status: Draft | ||
Type: Standards Track | ||
Category: Contract | ||
Created: 02-May-2022 | ||
Requires: 171 | ||
--- | ||
|
||
## Summary | ||
|
||
A standardised interface for constructing NFTs (non fungible tokens) that are not meant to be transfered. These non-transferable NFTs (NTNFTs), AKA Soulbound tokens (SBTs), AKA Account bound tokens (ABTs), AKA Non-transferable tokens (NTTs), should be bound to an owner address on minting so the owner never changes. | ||
|
||
## Motivation | ||
|
||
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 | ||
|
||
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. | ||
|
||
## Rationale and alternatives | ||
|
||
One possible alternative to this standard would be to implement the non-transferable nature by creating a NEP-171 contract whose transfer function is prohibited (or extremely limited). However, recognising this fact would be hard to determine without checking the code of the contract. Making this limitation explicit, via a standard, would build trust in the owners of tokens abiding to this new NEP standard. | ||
|
||
## Specification | ||
|
||
From a technical standpoint the functionality described by this standard will be a subset of the standard NFT functions as described in [NEP-171](./nep-0171.md). In general terms, it is the NEP-171 standard WITHOUT any transfer or approval/allowance functionality. | ||
|
||
### NTNFT Interface | ||
|
||
```ts | ||
// The base structure that will be returned for a token. If the contract is using | ||
// extensions such as Enumeration or Metadata, other | ||
// attributes may be included in this structure. | ||
type Token = { | ||
token_id: string, | ||
owner_id: string, | ||
} | ||
|
||
/****************/ | ||
/* VIEW METHODS */ | ||
/****************/ | ||
|
||
// 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 {} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||
``` | ||
|
||
To be more explicit then, an interface of this standard **SHOULD NOT** include the following functions from the NEP-171 standard: | ||
```ts | ||
function nft_transfer( | ||
receiver_id: string, | ||
token_id: string, | ||
approval_id: number|null, | ||
memo: string|null, | ||
) {} | ||
|
||
function nft_transfer_call( | ||
receiver_id: string, | ||
token_id: string, | ||
approval_id: number|null, | ||
memo: string|null, | ||
msg: string, | ||
): Promise {} | ||
|
||
function nft_resolve_transfer( | ||
owner_id: string, | ||
receiver_id: string, | ||
token_id: string, | ||
approved_account_ids: null|Record<string, number>, | ||
): boolean {} | ||
``` | ||
|
||
### Extending core functionality | ||
|
||
Although not explicitly required by this standard, the existing Metadata ([NEP-177](./nep-0177.md)) and Enumeration ([NEP-181](./nep-0181.md)) standards may extend the interface by the usual functions, for example: `nft_metadata, nft_total_supply, nft_supply_for_owner`. It would make sense to conform as close as possible to the field names and functions as described in these standards so as to offer supporting software which already interacts with NFTs the best chances at backwards compatibility with NTNFTs. | ||
|
||
However, [NEP-178](./nep-0178.md), which pertains to approval management, and [NEP-199](./nep-0199.md), which pertains to the royalty extension are both not applicable for this standard. | ||
|
||
### Events | ||
|
||
When reporting events in order to conform to the event standard [NEP-297](./nep-0297.md) this standard would be similar to the events specification for NEP-171, however there would be no need for an `nft_transfer` event. | ||
|
||
More explicitly then, Non Transferable Non-Fungible Token Events MUST have `standard` set to `"nep359"`, standard version set to `"1.0.0"`, `event` value is one of `nft_mint` or `nft_burn` and `data` must be of one of the following relavant types: `NftMintLog[] | NftBurnLog[]`: | ||
|
||
```ts | ||
interface NftEventLogData { | ||
standard: "nep359", | ||
version: "1.0.0", | ||
event: "nft_mint" | "nft_burn" | ||
data: NftMintLog[] | NftBurnLog[], | ||
} | ||
``` | ||
|
||
```ts | ||
// An event log to capture token minting | ||
// Arguments | ||
// * `owner_id`: "account.near" | ||
// * `token_ids`: ["1", "abc"] | ||
// * `memo`: optional message | ||
interface NftMintLog { | ||
owner_id: string, | ||
token_ids: string[], | ||
memo?: string | ||
} | ||
|
||
// An event log to capture token burning | ||
// Arguments | ||
// * `owner_id`: owner of tokens to burn | ||
// * `authorized_id`: approved account_id to burn, if applicable | ||
// * `token_ids`: ["1","2"] | ||
// * `memo`: optional message | ||
interface NftBurnLog { | ||
owner_id: string, | ||
authorized_id?: string, | ||
token_ids: string[], | ||
memo?: string | ||
} | ||
``` | ||
|
||
## Reference Implementation | ||
|
||
[Minimum Viable Interface](https://github.com/kycdao/near-sdk-rs/blob/ntnft/near-contract-standards/src/ntnft/core/mod.rs) | ||
|
||
[NFT Implementation](https://github.com/kycdao/near-sdk-rs/blob/ntnft/near-contract-standards/src/ntnft/core/core_impl.rs) | ||
|
||
## Unresolved Issues | ||
|
||
### Dealing with minted NTNFTs in cases of lost, stolen or new accounts | ||
|
||
Implementers should consider the case of what should happen to these NTNFTs if the user loses access to their account, it is somehow compromised or they simply wish to use a new account. As there are a number of ways this can be handled, this standard does not explicitly mandate that any particular function MUST be implemented to handle this. | ||
|
||
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 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. | ||
- The service could implement a `validity` status in the NTNFT's metadata that can be updated to show that the NTNFT is no longer valid. This would require the client services to understand the importance of this field and not simply check for the existence of the NTNFT when gating. | ||
|
||
The above methods may also be useful to services when they wish to revoke a users NTNFT, e.g. if the service finds the user was acting fraudulently. | ||
|
||
### Preventing transfer of account via trading wallet keys | ||
|
||
There will always exist the possibility that a user can simply transfer all the assets in their account, including any NTNFTs, to another user by simply giving them the private keys to the account. | ||
|
||
Ultimately, there is no way to prevent this. However, given common methods such as the one listed above for a user to do some sort of authenticated account recovery process, it would mean that any 'buyer' would run the risk the 'seller' simply recovers all their tokens using this process making such a trade less likely. | ||
|
||
## Future possibilities | ||
|
||
There are a few natural extensions to this standard which might be considered in NEPs for the future. | ||
|
||
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. | ||
|
||
## Copyright | ||
[copyright]: #copyright | ||
|
||
Copyright and related rights waived via [CC0](https://creativecommons.org/publicdomain/zero/1.0/). |
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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.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.
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.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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.