# Randomness for NFT packs on Flow

**URL:** <https://forum.flow.com/t/randomness-for-nft-packs-on-flow/1830>\
**Category:** 🏄🏻‍♀️ Cadence\
**Created:** [April 28, 2021, 7:00pm UTC](https://forum.flow.com/t/randomness-for-nft-packs-on-flow/1830 "2021-04-28T19:00:45Z")\
**Posts on this page:** 7\
**Page:** 1

<div class="post-metadata">

**Author:** ![zach8302](https://avatars.discourse-cdn.com/v4/letter/z/6f9a4e/32.png) [@zach8302](https://forum.flow.com/u/zach8302)\
**Post date:** [April 28, 2021, 7:00pm UTC](https://forum.flow.com/t/randomness-for-nft-packs-on-flow/1830/1 "2021-04-28T19:00:45Z")

</div>

Hi all,

I’m currently working on an NFT Marketplace on the flow blockchain. I am hoping to find a way to implement a pack that returns a random NFT (similar to NBA Topshot). I have seen the Cadence documentation for unsafeRandom() but I am not sure how to implement it (also the playground doesn’t support it).

I would appreciate any input.

Thanks!

---

<div class="post-metadata">

**Author:** ![flowjosh](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.flow.com/flowjosh/32/362_2.png) [@flowjosh](https://forum.flow.com/u/flowjosh)\
**Post date:** [April 29, 2021, 7:39pm UTC](https://forum.flow.com/t/randomness-for-nft-packs-on-flow/1830/2 "2021-04-29T19:39:54Z")

</div>

It isn’t safe because a user could revert the transaction and retry as many times as they want until they get the random number that they want.

Check out the docs for how to use it: [Built-in Functions - Flow Documentation](https://docs.onflow.org/cadence/language/built-in-functions/)

---

<div class="post-metadata">

**Author:** ![bluesign](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.flow.com/bluesign/32/1359_2.png) [@bluesign](https://forum.flow.com/u/bluesign)\
**Post date:** [May 27, 2021, 5:55pm UTC](https://forum.flow.com/t/randomness-for-nft-packs-on-flow/1830/3 "2021-05-27T17:55:34Z")

</div>

It is called “unsafeRandom”, from these two words, only “unsafe” is correct, unfortunately.  
Because it is not random for sure. It is not uniform, you have better luck with xkcd random. [1]

Even if you sign the transaction yourself it is not safe. Don’t use in any condition.

[1]  
 ![](https://us1.discourse-cdn.com/flex022/uploads/flow/original/1X/408b5bbf692caaa0c738cf6dcf7b22820b040813.png)

---

<div class="post-metadata">

**Author:** ![qvvg](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.flow.com/qvvg/32/78_2.png) [@qvvg](https://forum.flow.com/u/qvvg)\
**Post date:** [May 28, 2021, 12:51am UTC](https://forum.flow.com/t/randomness-for-nft-packs-on-flow/1830/4 "2021-05-28T00:51:53Z")

</div>

`unsafeRandom` isn’t flagged as unsafe for the reasons you are stating. It is probably easier to explain with an example.

It is very easy and very likely for a contract writer to write a contract where the randomness is generated in the same transaction where the value is delivered. Say in a pack situation if what was in the pack was decided at random during the purchase, I could in theory write a transaction that buys the pack, opens it, and only completes the transaction if the delivered nft serial numbers are to my liking. I could then run that transaction say 10 or even 100 times at once, so that I am more likely to receive a valuable pack and guarantee a bag of valuable nfts at the small additional cost of gas for transactions that weren’t up to my get rich quick standards.

You can then say, well just make it so the randomness is decided in a different transaction to the delivery of the value, so that the sale can’t be stopped if the purchaser doesn’t like the outcome. Which is correct, and I believe the answer to the question @zach8302 asked.

Be super super super careful with randomness and blockchains.

---

<div class="post-metadata">

**Author:** ![bluesign](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.flow.com/bluesign/32/1359_2.png) [@bluesign](https://forum.flow.com/u/bluesign)\
**Post date:** [May 28, 2021, 8:21am UTC](https://forum.flow.com/t/randomness-for-nft-packs-on-flow/1830/5 "2021-05-28T08:21:52Z")

</div>

I understand the transaction cancel and retry part. It is the obvious probable attack.

> [@qvvg](#):
>
> You can then say, well just make it so the randomness is decided in a different transaction to the delivery of the value, so that the sale can’t be stopped if the purchaser doesn’t like the outcome. Which is correct, and I believe the answer to the question @zach8302 asked.

This is also unsafe imo, consider this:

- Imagine I am distributing TS packs with single moment inside (let’s say 100k packs), and in each pack you have chance to get 1/100k odds Lebron Moment

- I am making lets say 100 transactions per block to speed up delivery.

Problems:

- all those 100 transactions (in the same block which blockID is the seed), will have the same pack content. So instead of different packs, you will give 100x same pack

- if one of the packs (1/1000) has Lebron, 1/100 chance, you will give away 100 Lebron. So instead of expected value of 1 Lebron in 100k packs, you will either have 100 Lebron with 1% chance, or No Lebron at all 99%

This variance is usually not good from a business perspective too.

Also, I didn’t check how blockID is calculated, but potentially I am guessing, the malicious users can also affect that part.

---

<div class="post-metadata">

**Author:** ![taylor](https://avatars.discourse-cdn.com/v4/letter/t/c2a13f/32.png) [@taylor](https://forum.flow.com/u/taylor)\
**Post date:** [October 3, 2022, 4:09pm UTC](https://forum.flow.com/t/randomness-for-nft-packs-on-flow/1830/6 "2022-10-03T16:09:48Z")

</div>

Have there been any new developments of randomness on Flow?

> [@qvvg](#):
>
> You can then say, well just make it so the randomness is decided in a different transaction to the delivery of the value, so that the sale can’t be stopped if the purchaser doesn’t like the outcome. Which is correct, and I believe the answer to the question @zach8302 asked.

I am curious about your idea here about generating the random in a different transaction than delivery. My understanding is you are saying 1 transaction would pay for and request a pack. Then a second transaction would ask for the pack to be delivered? Couldn’t I just cancel either transaction once the randomness is revealed but before it is sealed?

Would a verifiable random oracle work on Flow? A service will generate crypto-random values ahead of time, hash the value, and publicly publish the upcoming hashes and times they will be published - ideally 1 for every block. The service will continuously publish transactions wherein the next random number is set in the contract. There could be a consumer function that mutates the number after each use so that each transaction in the block gets a different number. Auditors can use the hash history with the published numbers to ensure the oracle is fair.

I suppose this is still susceptible to someone repeatedly making transactions and cancelling until they get their desired outcome but with try-and-panic until you get your desired outcome you could theoretically never get your outcome and be beaten by another user.

---

<div class="post-metadata">

**Author:** ![j00lz](https://sea2.discourse-cdn.com/flex022/user_avatar/forum.flow.com/j00lz/32/1940_2.png) [@j00lz](https://forum.flow.com/u/j00lz)\
**Post date:** [October 6, 2022, 7:02am UTC](https://forum.flow.com/t/randomness-for-nft-packs-on-flow/1830/7 "2022-10-06T07:02:21Z")

</div>

Yes, there has 😃

You can check this thread out in the discord:

> **[Discord - A New Way to Chat with Friends & Communities](https://discord.com/channels/613813861610684416/621847426201944074/1020227067754844260)**
>
> Discord is the easiest way to communicate over voice, video, and text. Chat, hang out, and stay close with your friends and communities.

> <https://github.com/justjoolz/PRNG/blob/master/cadence/contracts/PRNG.cdc>

Rather than requiring a second transaction it just uses a future block hash for the seed…  
which avoids the panic if unhappy problem.

It uses an LCG instead of unsaferandom for the reasons @bluesign described
