Quest is Incognito’s first pApp, and happily, it has received a great deal of attention. As it’s a game of skill and luck, we thought it’d be helpful to share some details pertaining to how Quest defines ‘luck’.
Briefly, there are 2 rounds to Quest. The 1st round invites players to seek out hidden QR codes in order to unlock the token QUEST, which allows them to spin a lucky wheel and win prizes. One of those prizes is a Bitcoin LOTTO token, which gives the holder access to the 2nd round – a draw to win 1 BTC.
Here’s how winners are selected, how likely they are to be selected, and how it all works.
I. Verifiable random function (VRF):
A verifiable random function (VRF) is used to generate a pseudo-random value on the server-side from the input of users. Based on the property of VRF, a non-interactive verifiable proof is also provided to verify the correctness of the computation. The VRF consists of the following algorithms:
-
KeyGen: Server generates key pairs (
private_key
,public_key
). Server will keepprivate_key
secret and publishpublic_key
. -
Comp: Players submit their input. Server computes and returns
(rand, proof) ← Comp(private_key, player_input).
To guarantee the uniqueness and unpredictability of player_input
, we require players to spend QUEST to the server address each time they spin the lucky wheel. The transaction ID is player_input
.
-
Verify: Anyone can verify the correctness of
(rand, proof)
by checking thatYes/No ← Verify(public_key, player_input, rand, proof).
We will make public the source code and provide a verification feature that allows players to check correctness.
We implement the VRF algorithms described in this paper.
II. Rules (1st round – lucky wheel):
After generating the pseudo-random value rand
as the lottery ticket, the next task is to determine the winning prize.
Due to the uniform distribution property of pseudo-random value rand
, we define prize ranges based on the total numbers of distributed QUEST tokens and the total prizes. The following figure shows how the winning prize is determined after the ticket is received.
For this example, let’s assume that the total of 404,500 QUEST tokens distributed to players are spent on the wheel. The prize ranges are defined as follows:
Prize type | No. of prizes | Percentage | Range Li |
---|---|---|---|
0.01 PRV | 379,835.00 | 93.9023% | [L10:L) |
1 BTC LOTTO | 21,000.00 | 5.1916% | [L9:L10) |
1 PRV | 2,000.00 | 0.4944% | [L8:L9) |
2 PRV | 500.00 | 0.1236% | [L7:L8) |
3 PRV | 300.00 | 0.0742% | [L6:L7) |
0.01 XMR | 500.00 | 0.1236% | [L5:L6) |
0.1 XMR | 100.00 | 0.0247% | [L4:L5) |
10 PRV | 100.00 | 0.0247% | [L3:L4) |
0.001 BTC | 100.00 | 0.0247% | [L2:L3) |
1 PNODE | 40.00 | 0.0099% | [L1:L2) |
1VPN | 25.00 | 0.0062% | [0:L1) |
The domain of rand from [0; L-1]
with
L = 7237005577332262213973186563042994240857116359379907606001950938285454250989
The list of range prize Li
is computed as follows:
L1 = 447280938030424117056439218976699273229735250888745834734360379374873563
L2 = 1162930438879102704346741969339418110397311652310739170309336986374671264
L3 = 2952054191000799172572498845246215203316252655865722509246778503874165516
L4 = 4741177943122495640798255721153012296235193659420705848184220021373659768
L5 = 8319425447365888577249769472966606482073075666530672526059103056372648273
L6 = 17265044207974370918378553852500591946667780684305589220746310643870119535
L7 = 35156281729191335600636122611568562875857190719855422610120725818865062059
L8 = 70938756771625264965151260129704504734236010790955089388869556168854947107
L9 = 124612469335276159011923966406908417521804240897604589556992801693839774680
L10 = 500328457280832417339332910347335807034781851644151090733855520368733567685
Each rand value that is returned to the player each time they spin the wheel is mapped to one of the ranges above to definitively determine the prize.
III. Process (1st round – lucky wheel):
-
The server runs VRF_KeyGen to generate key pairs (private_key, public_key) and make public the public_key.
-
Finalize the prizes and the total number of QUEST tokens to be sent out. Define the prize ranges. Publish all source code and params.
-
Assume that some QUEST tokens have been distributed during the prelaunch, prior to this implementation. Each time a player spends a QUEST token to the server’s address, the server will verify the correctness of the transaction and call VRF_Comp to compute a random value and proof (rand, proof). Finally, use the prize ranges to map the prize for rand value.
The player must submit their payment address or public key in each transaction (memo) to receive the prize.
- Anyone can use the proof value, VRF_Verify function, and the prize ranges to verify the correctness of the result.
IV. Process (2nd round – BTC lottery)
This is conducted similarly to the first round. The only difference is that the prize ranges are not used to determine the winner and the prize.
Each LOTTO transaction spent will receive the pair (rand, proof). At the end of the game, we are able to choose a solution to determine the winner. For example, by using the block hash of the bitcoin chain at height xxx as the input to VRF_Comp to get (rand_b, proof_b). The player that has the random value nearest to rand_b is the winner.
V. Test result
Prize type | No. of prizes | Percentage | Range Li | Test result |
---|---|---|---|---|
0.01 PRV | 379,835.00 | 93.9023% | [L10:L) | 379924 |
1 BTC LOTTO | 21,000.00 | 5.1916% | [L9:L10) | 20855 |
1 PRV | 2,000.00 | 0.4944% | [L8:L9) | 2070 |
2 PRV | 500.00 | 0.1236% | [L7:L8) | 523 |
3 PRV | 300.00 | 0.0742% | [L6:L7) | 280 |
0.01 XMR | 500.00 | 0.1236% | [L5:L6) | 496 |
0.1 XMR | 100.00 | 0.0247% | [L4:L5) | 91 |
10 PRV | 100.00 | 0.0247% | [L3:L4) | 95 |
0.001 BTC | 100.00 | 0.0247% | [L2:L3) | 103 |
1 PNODE | 40.00 | 0.0099% | [L1:L2) | 37 |
1VPN | 25.00 | 0.0062% | [0:L1) | 26 |
May the odds fall in your favor Happy Questing!