Tech Explained

The Algorithm

We have built the equivalent of Chainlink VRF on Stacks, and started working on top of it. Every block has a unique random number stored in the block-info as vrf-seed.

(get-block-info? vrf-seed u0) 
;; Returns (some 0xf490de2920c8a35fabeb13208852aa28c76f9be9b03a4dd2b3c075f7a26923b4)

Because multiple lootboxes can be minted on the block, it is not enough to use the vrf-seed. That would result in minting the same item for all the users. So it has to be combined with something else to keep the distribution uniform while also making the numbers different from one another and impossible to know how to do it prior to the open of the lootbox.

This is where we decided to integrate the id of the lootbox into play. The lootbox could be, theoretically, minted in any of the blocks, so it has an equal chance to influence any of the vrf-seeds, not known on the moment of minting.

The distribution values match uniform random function values with all possibilities applied. The big unique value is created by putting together the vrf-seed and id of the lobby, converted to byte. This is the equivalent of the encoding step in Chainlink implementation.

Because this would result in values like 0xaaab...cd01, 0xaaab...cd02 ,0xaaab...cd03 if three values are minted in the same block, a hashing function is applied to make them totally different. The same hashing is used on chainlink, keccak256.

From the resulting value, the first byte is picked, out of convenience. Any byte would have been as good.

The rarity pick is done based on the backgrounds of the miami-degens and nyc-degens. It is equivalated to 255 from 200 because that is the size of one byte in terms of uint. Then it gets recalculated to have uints for clear distribution rules.

ItemOld DistributionEquivalent for 255New Distribution

NYC Goldie




Miami DarkPurple




NYC Emerald




Miami Orange




Miami Sunset




NYC Purple








Conditions picked to select a specific component based on byte value (converted to int):

  • Goldie < 51

  • DarkPurple < 102

  • Emerald < 153

  • Orange < 192

  • Sunset < 231

  • Purple < 256

In the items smart contract there is the function mint-name which will mint the specific type of background based on the name argument. Based on the value resulted, a name is picked and minted by calling the other contract. Lootbox contract can mint in the items smart contract because he also is admin of that smart contract. This keeps the items safe from exploits that would call directly the mint there for whatever background they want.

Flow Manager - Lootbox - Item

If the user has a valid number of mints available in the Lootbox Manager he can claim that number of lootboxes.

The lootbox is burnt and the item for the specific rarity is minted directly to the user wallet.

How Lootboxes Interact

Lootbox Flow Detailed

Lootboxes are capable of running completely on-chain. This is thanks to vrf-seed and all operations happening directly on the contract ( hashing, concatenate, conversions etc. ).

Because the lootbox contract can act as admin in the item contract, the exchange of the lootbox for the item happens completely in a decentralized manner, directly on chain, in a function call that burns the lootbox and mints the item.

Functions were created for an easy reading off the data off-chain. Through(define-read-only (item-for-value (value uint)) applications can display the lootbox result of the lootbox, when the vrf-seed is known, without any costs. From a front end APP, in combination with the blockchain calls, any function call can be done and if an admin entity is needed for a specific use case, the Lootbox Manager can be used.


Resources Used

Last updated