How PackDraw Ensures Fairness

At PackDraw, the safety and confidence of our customers is our top priority. We've implemented rigorous measures to ensure every aspect of our website is secure and meets or surpasses industry standards. Our commitment to provable fairness guarantees that every outcome is random, impervious to tampering, and open to validation by anyone.

For single-pack opens and deal purchases, we combine a random server seed, your client seed, and a nonce into a long string. This string is converted into a very large integer, securely hashed, and then normalized to a ticket number between 1 and 1 million. This method of randomness can easily be verified by passing the client seed, server seed, and nonce into our getTicketNumber function (shown below). For battles, we use the same ticket number generation function but instead of your custom client seed, we use the hash of a future EOS block. This ensures that the outcome of a battle is not known until the block is mined and that other players (or bots) are not able to manipulate the outcome.

In our Draw game, each result is generated using your client seed, our hashed server seed, and a unique nonce based on the round and line position: nonce = roundIndex × lineCount + lineIndex. This combination produces a ticket number between 1 and 1,000,000. A card flip is considered a win if the ticket number is less than or equal to the survival probability multiplied by 1,000,000. After the game ends, we reveal the unhashed server seed so you can independently confirm each result using the original inputs.

Terms & Definitions

Ticket Number: An integer value between 1 and 1,000,000 that is the result of combining the random inputs of client seed, server seed, and nonce. This ticket number is then used to look up the resulting product based on that product's ticket number range, which is visible in the pack details.

Client Seed: A client seed is any string of characters that is known to you before a random result is generated. In single-pack opens, the client seed is provided by you and when combined with the server seed and nonce, used as the source of randomness in our VRF procedure. In battles, the client seed is always a future EOS block hash.

Server Seed: A server seed is randomly generated by our servers and is super secret. A hash of this value is provided to you before any purchase. To verify randomness, note your server seed hash before purchase, found in your PackDraw account profile. After your purchase, we expose the unhashed server seed to you. Taking the sha512 hash of your newly exposed (unhashed) server seed, you will get the server seed hash you noted before your purchase. Additionally, combining your server seed, nonce, and client seed (which may be an EOS block hash depending on the game you are playing) and passing it to our getTicketNumber function, you can verify the result.

Nonce: A nonce is simply an auto-incrementing number that is used by our getTicketNumber function to provide a unique random result when server seeds and client seeds remain unchanged, as is the case when opening multiple packs in a single purchase. e.g. battles or multi-pack opens.

EOS Block Hash: EOS is a decentralized block chain that typically produces a new block every half a second. By taking the hash of a future EOS block, we can ensure that neither the players nor PackDraw can know about or influence the outcome once a battle starts. This system guarantees that the result is fair and cannot be tampered with, as the outcome is calculated based on factors that are not alterable or predictable by either party.

Verifying Randomness

To maintain transparency, we provide a set of functions that can be used to verify the fairness of your outcomes. You can use these functions to verify the resulting ticket number you received after purchase. The client seed, server seed, and nonce used for any pack opening or battle can be found in your pack purchase history or battle history, located within your PackDraw account profile.

import crypto from 'crypto'

export const sha512 = (value: string) => {
  crypto.createHash('sha512').update(value).digest('hex')
}

export const combineSeeds = (clientSeed: string, serverSeed: string, nonce: number) => {
  return sha512(`${clientSeed}:${serverSeed}:${nonce}`)
}

export const getTicketNumber = (hash: string) => {
  const hashInt = BigInt('0x' + hash)
  const maxInt = BigInt(1_000_000)
  return Number((hashInt % maxInt) + BigInt(1))
}