NFT News, Updates, Sources, To Buy & Sell, Advice, Disscussions, Tips, Forum, Market, Crypto, & more!

in

Dankrupt VRF v.0.0.1

Dankrupt VRF v.0.0.1 thumbnail
Dankrupt VRF v.0.0.1 thumbnail

EYO DANKRUPT!

I am here today to share the first in what will hopefully be a nice, long, di....roll out of new services built by Dankrupt to contribute to the Loopring Ecosystem (and beyond)!

TL;DR: We use IPFS to host a function that can compute results locally in any browser with minimal dependencies and no reliance on a webserver or API. This uses inputs which can be verified using on chain data. The function will provide provable randomness for any NFT mint/distribute sequence, will be verifiable by any observer, and can be used to automate other processes. We intend to extend off of this in both directions: easier verifiability and more front end development utilization.

ELI5: You can use your own computer to process an NFT collection and the people who participating in redeeming the mints, and you can PROVE that the results where random and respected. There's no need to blindly trust anybody to make sure the distribution is "fair"!

Dafuq is a VRF!?

First, let's talk about some basics: When you mint an NFT through a smart contract, it is possible (but not always the case) for the smart contract to make sure that the NFT you get is entirely random. So, there's no concern about insiders getting the good shit and you being handed some weak af common. We might call this "trustless randomness" since the contract executes the random function no matter what, you don't have to count on anybody to do it correctly. Currently, we can't do this in Loopring. We don't have the ability to create whatever smart contract we want, so, most NFT projects are handling their own randomness in house. But what if we had a way to Verify the Randomness?

Introducing: Verifiable Random Functions

What we want is a way to prove, beyond any shadow of a doubt, that who got what was random, and that there is no possible way to cheat the game. We're going to use some classic crypto tricks to accomplish this, and at the end, we're going to have a clear path to victory. Now, we could pretty easily run our own RNG and then just send out NFTs based on what the RNG tells us....but, we might not always use the same RNG, or we might lie about how we used it. We might disregard the RNG entirely when we get to our homie's name on the list and just send him the maximum dankness. This is no bueno. So, let's start off with a method to create a function that is known and cannot be modified:

IPFS is a KILLER solution for this. Once a file is loaded into IPFS, it is assigned a CID that that points to that file, and that file only. You cannot change the contents of the file. If we plop a bit of script into this file, then that script will always run the same way every time no matter what, and there's no way to lie. If that script executes in the browser, then there's no server or API or secrets, at all, everything is right there in front of the user. Anybody can check any implementation of the VRF to make sure that it hasn't been interrupted, replaced, or tampered with. This gives us some added degree of "immutability" and "trustlessness" that is fairly similar to a smart contract in Ethereum's L1. We don't necessarily have a swarm of Validators telling us that everything is up to spec, but every user, every participant, has the ability to check, anytime they like, to make sure things are behaving as expected.

Alright....so, that's pretty clever...but....how do we leverage that for NFT distribution:

We need two things first. We need to know what NFTs we're minting and who's competing in the mint. Now, we don't want anybody to be able to lie about these either....so....why don't we use IPFS again? Let's make a file for the NFTs and a file for the Transactions, and let's throw both of those into IPFS as well. Now, everybody knows what those files are and where they are. An NFT project only needs to publish the CIDs for these two files and say "This is what we're using." Anybody can, again, check any time they like to make sure that these files are complete, valid, and have not been replaced, modified, or interrupted in any way since the CIDs for those files were made known.

Step 1: create collectionData.JSON

This is going to be very similar to the JSON files you cook up already for your NFT metadata, and it's going to inform the function of a few important details about your mint process. Here's an example of the JSON I created while testing this function:

{"title": "Classic Game GIFs","series": "1","artist": "poesch","perMintCost": 
"40","maxMintPerPerson": "2","dankruptVRF": "0.0.1","metaCids": {"cid1": 
"QmfEAYGSibSKtFHS23gDRFFcSJf7cqNuPCQxz6eFVM1hYr","cid2": 
"Qmc9S4wX3VorKNd9fRKBWZDufrHBYiztnvNNsfjS8tdHb4","cid3": 
"QmTH5esb8JMzZY6R5zar68qKyQwNUuDHjqiDfPqr7Jjhj2","cid4": 
"QmVaAThvbjdqZwYHvJ8j5yni719d4PmQsmfCtCVKz7Frsj","cid5": 
"QmSYQt2F2yXhau4VQuqBaeUHGgukgM8brXGrhmQNy2Ep6D","cid6": 
"QmVroLyeHJDS5ZNrJPzbgQnSMPJVmig6zjS5M43y85Jj9F","cid7": 
"QmQL8ZiYfNDNPUGa54Rwi9bGhxJ1nYEaGgFjmRRfNvg6rg","cid8": 
"QmTiEt16EaXbvDopaHoq5Ki5ciSAxkUQbjznjyPSnVfXy9","cid9": 
"QmchrSixxNXhFT9KK4MuBuBuW1Txuq16oY3NgiXf3YnYSA","cid10": 
"QmXHoDmz5Tskc14TZMLEDGAYDaQ81ZeSoPzByKTmxLVvjJ","cid11": 
"QmbzhAmw85VDefzsNW9EqHff5SU5wD2JGSNR8ZPB2xqXJy","cid12": 
"QmSQr7gwRG48Ea3cFqnTktZN9kLgiAzANyVxGqrPJwFKU3","cid13": 
"QmUqWontGSRyeiqCxXftXHmttDnpKi4B9AcK3NxurYvUQb"}}

Now, we actually aren't going to use "Title" "Series" or "Artists" in this v.0.0.1 iteration, but I wanted to make it clear that it's fine for your JSON to include additional details. There are a lot of things I already have in mind to add to this VRF, and a lot of ways you can use the VRF in your own website design process. I'll dig much deeper into both of those towards the end of this post. For now, let's keep things simple and we'll make our way through things.

Notice that the "cidXX" title increments in each new entry. This is required for the current version of the VRF, so do make sure you follow that bit. Here soon we might even have a handy tool that will throw this together for you ;)

Some minters might scoff at this. They might say "but I don't want to publish my NFT data prior to the mint." And that is totally fine. It is actually quite easy to pre-calculate your IPFS CIDs before you actually upload anything. We'll go into that further more in a bit, and if you have questions about it, don't hesitate to ask.

Alright, so Step 2: create transactions.JSON

We need a list of everybody who participated in your mint (the people you owe NFTs to). So, lets throw together another JSON file:

{"transaction1": {"ethAddress": 
"0x5c67732f63323dabf70ebdded102bff210d086ca","value": "40"},"transaction2": 
{"ethAddress": "0x5bdb878c6dcb352699a4500cd21797950a46b7ba","value": 
"80"},"transaction3": {"ethAddress": 
"0x08950ea47bc614cef701adaf214273dc1278ff7f","value": "40"},"transaction4": 
{"ethAddress": "0xd59caad715653404eeb053cabe7a7baf8a3b683d","value": 
"80"},"transaction5": {"ethAddress": 
"0xd59caad715653404eeb053cabe7a7baf8a3b683d","value": "40"},"transaction6": 
{"ethAddress": "0x0c90ad36f195b00ff1e43d8708499004425e879d","value": 
"40"},"transaction7": {"ethAddress": 
"0xceed93150b2557cab377c138b96c00630c524066","value": "40"}}

Alright, so, now we know everyone who threw in. We have their Ethereum Address and the value they sent. Now, in the collectionData.JSON we specified how much each mint would cost and how many mints everybody was allowed to claim. But....uh....here we have an address that sent two transactions, and when we add them together, it's too much! They aren't allowed to claim that many. And, this list has more transactions that can be claimed than the mint has NFTs! Oh NoEs WuT Do!?

No sweat, the first thing our VRF is going to do is sort through these json files to evaluate a full list of the NFTs, the number of NFTs available, a full list of who sent how much (in total, even if multiple transactions), and make sure they are only able to claim as many as they are allowed, and then cut the list of transactions off based on how many NFTs there are. All this is handled for you in the VRF. We could even use the VRF to produce a list of who you might need to refund if you wanted to ;)

Now, we need to address a few things about randomness and how functions can sometimes be cheated:

  1. The first person rewarded an NFT in the function has the highest certain odds of getting a common NFT (assuming the collection has rarities). This means that, if you want better odds at a Legendary, you probably want to come later in the stack of transactions. Somebody might wait to "snipe" a spot further down the list.
  2. If the target value to get a particular NFT is known, then you could potentially manipulate the transaction to get a certain RNG output as well. So, if I know I need to roll a 69 to get the triple epic holographic funko ape frog mutation NFT, then I might do some math on my end to figure out if maybe using a certain Ethereum address would give me better odds or something.

In short: We don't want people playing the game to know shit until after they have sent their transaction in for the mint. So, we're going to create a seedHash that only exists for this event, and CANNOT BE KNOWN before window for new transactions has closed. We use the same encryption algorithm that helps secure BTC and ETH for this: SHA256!!! We take alllllll the transactions that are included, we combine them into one long string, and then we hash that string to a value. Ta-Da! Uber secret hash that no participant could ever possibly guess.

Now, let's use that hash to solve 1) and 2):

  1. For each mint rewarded, we're going to take the Ethereum Address, add the number of the roll (if you ordered two NFTs, you would get Ethereum Address + 0 for the first roll and Ethereum Address + 1 for the second roll), and then slap the seedHash on the end of it. Aaannndddd SHA256 again. A nice big crazy random ass value that again, couldn't possibly be known. We are going to do some math tricks to use this hash to get a random number between 1-100m. This number will be the Score/Strength/Roll of that entry.
  2. For each NFT available, we're going to take the image CID or file path (which we track down automatically based on the metadata CID) and we're going to slap our seedHash on the end of it again....aaaannnnddddd more SHA256. Same thing: math trick, evaluate this to a random number between 1-100m

Why 100m? Because I thought it would be a funny inside joke for those of us who were around for the January panic fiasco. That's really all that is. It is sort of nice to have a very large range for randomness, as it reduces the likelihood for collisions...but, collisions are technically fine in our function. If they do occur, they won't wreak any havoc.

So now, we sort the transactions from the lowest roll to the highest, and we process them in that order (this prevents anybody from being able to game the order of the transactions) and for each transaction, we locate the closest score for an NFT. Boom, match made. That entry wins that NFT!

EZPZ, right?

So, let's cover implementation. How the fuck do YOU use this thing???

The only two dependancies for this function are jquery and the sha256 magic. Now, you can build a website and people can run the function in your site....OR...you can actually just throw this together yourself and run it locally (the ability to do this was a massive priority for me, because I wanted it to be HIGHLY VERIFIABLE). If you are familiar with HTML, this is going to be SUPER straight forward. In the of your .html, just slap in:


That's the two dependencies taken care of. Now, we want to set up the first two variables for our function to operate, which are the two JSON files we cooked up:

At the end of those https: paths, you're going to add the CID for your two JSONs (which you uploaded into IPFS and you also published for all your participants to see).

Then we import the DankruptVRF v.0.0.1:

So, that IPFS hash always is and always will forever be the DankruptVRF v.0.0.1

Once this is all running in the browser, check the console and you'll see the output:

You might even notice that in this test, I used NFTs from different collections. This means a collector could do a raffle/competition for a set of NFTs they have picked up over time.

Anybody can run your JSONs against that function, anybody can check to make sure the transactions are honest. Anybody can check to make sure the NFT collection is complete, anybody can check to make sure the winners were dolled out correctly. This is MUCH closer to "trustless" than we currently have in Loopring. I do want to give a big shout out to the NFTers who use the marble race as their VRF. I totally love that, and this isn't throwing any shade on anybody, but I wanted to make something that I hope really adds big value to the market. This function is (ofc) completely free and open source, everybody is welcome to make use of it. If you would like to partner up with us and have us help you with implementation, use, anything really, door is always open. Feel free to hit me up here, or in DMs (you can find me in the DankruptDAO discord at https://discord.gg/ApFvUW8k )

So....let's talk about moving forward:

This is pretty extensible. I've kept everything in order matched arrays as much as is convenient, so scripting into it to generate HTML to display the NFTs, show who got what, should all be pretty straight forward. I plan to build a DankruptUI Helper to do just this, actually. Once the UI Helper does it's thing, a developer would only need to throw together a style sheet to make it all look nice in their implementation.

I will probably go back through this and have it build objects with all the relevant details in them (instead of using separate arrays). If you notice, in the collectionData.JSON we specified the version of the VRF. This can be used to make sure that a single, common implementation is able to make sure it's calling the correct version of the VRF for that particular mint. This frees me up to be able to restructure this as needed. This version actually has quite a few compromises I made in the interest of time, but it still works great!

The sorting function to determine winners is extremely inefficient. That'll definitely get re-worked. It's unlikely to cause any real issues, unless it's just a HUGE collection...but, I'd like to improve on it.

The Dankrupt team also has some plans for how to add ancillary services that all sort of base themselves off this...more on that once we're ready to start promoting solutions.

I DEFINITELY plan on incorporating u/fudgebucket27 's Rarity Generator as well. A reality of statistics is just that if the first round of winners doesn't claim a full collection, they are more likely to get lower rarities, and later rounds wind up with a higher % of the good shit. Some NFT creators bake this into their set up by charging more in later rounds (which I think is a great solution, and can help them generate more revenue from the mint, I don't want to take that away from them). But, by pulling the rarity scores, we could easily give the collectionData.JSON a key for "insureEqualOdds" or something like that, and have it a boolean value of "yes" or "no" For mints that choose yes, we could have the number of NFTs in the availableMintMetas bounded to the number of transactions, and we could have the VRF randomly sort which ones go in, but with some preference to rarity that makes sure that each round comes out balanced in terms of what is possible to win.

Anyways....I plan on working on this a bunch. If you have any feedback, ideas, questions, etc, don't hesitate to hit me up :)

HAPPY MINTING!!!!

***EDIT****

Reddit wants to screw up some of my code snippets here. I'll be making this all available in our discord as well, but for the time being, the CID for the DankruptVRF v.0.0.1 is QmTvPv1fzuyBmNkSNwtgUpt8qqCjxREeGWGsXVaJTXiGpT

The biggest glaring weaknesses in this are the Minter's ability to lie in the JSON files. This is something I plan to engineer out, but, since it's verifiable (any participant can check to see if the information is complete, valid, and honest) then it's "sufficient" as a verifiable random function, imo.

If you love this idea, but you hate having your content in IPFS prior to mint, check out:

https://github.com/alanshaw/ipfs-only-hash

You can pre-calculate all your image CIDs, then cook up your metadata files, then pre-calc those as well. This means there's no need to actually upload anything (expose it to the public network) before you are ready. If you would like help with this, happy to show you around :)

What do you think?

🎉Upvote & Drop your wallet 🎉 Win our Anniversary NFT 🎉 The Art of Crypto thumbnail

🎉Upvote & Drop your wallet 🎉 Win our Anniversary NFT 🎉 The Art of Crypto

🎉Upvote & Drop your wallet 🎉 Win our Anniversary NFT 🎉 The Art of Crypto thumbnail

🎉Upvote & Drop your wallet 🎉 Win our Anniversary NFT 🎉 The Art of Crypto