Unique NFT ASA Implementation - General - Algorand
Unique NFT ASA Implementation
post by krotkiewicz on Feb 27, 2021
I am looking to create a game on Algorand. Here is how I see it.
Participants can "redeem" prime numbers as NFTs. They can exchange it between each other freely, and I am planning to create a marketplace app where all prime numbers would be listed, and users could bid/ask on them.
The only problem I have is that there is no straightforward way to ensure NFTs uniqueness. It would be nice to have an extra parameter UniqueID that the user can set during NFT creation, and the network would enforce it.
I am thinking about how to work around that limitation, but nothing solid comes to my mind. Here are the weak ones:
- I can create a backend endpoint that a user can call. The endpoint checks uniqueness in DB and then creates an asset and passes it to the user.
An obvious drawback is that it is centralised and could potentially censorship users.
It is all about the marketplace app. It could list just the ones that were created first. I don’t like it either. It requires to have DB that tracks all the NFTs. Plus, there is an edge case when you make 2 ASAs in a single block.
I was thinking about a trick with ManagerAddr that has to be set to a specific contract address that would allow any other user to destroy the ASA if it is not unique. This seems fun and would even potentially add more gamification to the app, which is good. The bad thing is that it is probably not possible to implement. There is no way to store all created ASAs in some hashmap or hashmap like entity in the blockchain.
I would appreciate any feedback. Thank you.
post by fabrice on Feb 27, 2021
That looks interesting.
First two remarks:
- I don’t think you will be able to check primality on-chain. But I guess this is not a real issue as you can do it offchain.
- Block proposers can “steal” prime numbers: if they see the creation of an NFT for a prime number, they can just not include the transaction and create it themselves.
Let’s first ignore this second issue.
You can ensure uniqueness of NFT by issuing the NFT from a smart contract account where the prime number p is hardcoded.
Concretely, you first create an application App (stateful TEAL) whose role will be described later.
Let C_p be the smart contract account for the stateless TEAL script that:
- have
phardcoded as a constant - require any transaction from C_p to be in a group of transactions with a call to App
Now, to create an NFT for the prime p, Alice would send the following group of transactions:
- Alice sends 1 Algo to C_p
- C_p opts-in to App - App will check that C_p was not already opt-in. If not, it will store in the local storage of C_p two variables:
p = pandcreator=Alice - C_p creates the NFT
Then Alice opts in to the NFT.
Finally, Alice send the following group of transactions:
- C_p calls App. App check that
pandcreatorare set, and erasecreator. It also checks the second transaction is an NFT transfer from C_p tocreator. - C_p sends the NFT to Alice
Now to solve the issue that a block proposer can steal the prime number, what you can do is add a registration phase to the App
To register p, Alice opts in to App providing a hash value h = SHA256(Alice || r || p), where Alice is Alice’s address and r is a 32-byte random number chosen by Alice, and || is the string concatenation.
The App stores in Alice’s local storage the round round of the App call and h.
Then to create an NFT for p as above, Alice needs also to provide r and have in its local storage the above h. Furthermore, the App restricts the creation of an NFT for a registration h to happen after round round + 10,000.
Now, if a block proposer try to steal p, it will first see h. h does not reveal anything about p, so the block proposer cannot do anything meaningful about it.
Then, 10,000 rounds later, Alice will reveal r and p to allow the creation of the NFT for p.
To be able to steal p, the block proposer would then need to re-register p using h' = SHA256(r' || BadBlockProposer || p) and wait 10,000 rounds! This means that the block proposer needs to prevent the transaction from Alice to be committed for 10,000 rounds. This is virtually impossible (except if the bad block proposer has virtually all the Algos in the blockchain).
post by krotkiewicz on Mar 3, 2021
Great idea. Thank you. Let me try to build something around that concept.
post by robert on Apr 22, 2021
Hi @krotkiewicz - did you implement that mechanism?
We are planning to make an algob template for this concept. Would love to hear your feedback.
post by cusma on Apr 22, 2021
I believe that @aldur already worked on that.
post by aldur on Apr 23, 2021
Hey there!
I have just made the code available here. As you will see it is very rough, but should be enough to get you started. Feel free to add any contributions you feel is needed.
post by krotkiewicz on Apr 29, 2021
Hi @robert, I didn’t have a chance to prepare (yet) that mechanism.
Thanks @aldur for your solution.
post by yanik on May 9, 2021
As I understand there currently no Algorand standard for NFT?
post by robert on May 24, 2021
The standard way to create an NFT is to create ASA with total issuance = 1. It’s great, although not super cheap: each ASA requires 0.1 ALGO deposit.
post by robert on Dec 9, 2021
We implemented Unique NFT smart contract proposed by @fabrice in Algo Builder templates: algo-builder/examples/unique-nft-asa at develop · scale-it/algo-builder · GitHub