Provably Fair

Implementation of Provable Fairness at Gamba

At Gamba, we've taken a unique approach to the implementation of provable fairness in our online gaming platform. Recognizing the complexities and potential intimidation new players might face with traditional methods, we have innovated our process to be more user-friendly and transparent.

Traditional Server Seed Generation

Typically, online casinos generate an unhashed server seed as a 64-character hex string. While this method is secure, it presents a seed that appears as a complex string of characters, which can be difficult for players to interpret and verify.

Example of a Traditional Server Seed

ade416be64b9174243a7cc47f03e7418c165d00fe816bdfae3f301128810064e

Gamba's Innovative Server Seed Generation

To make the server seed more accessible and understandable, we've adopted a 12-word mnemonic seed phrase system. This approach not only simplifies the appearance of the server seed but also makes it more familiar to those used to cryptocurrency wallets.

Example of Gamba's Server Seed

powder entry search sport naive hover earth swap broken cupboard man basket

Generating the 12-Word Mnemonic Phrase

Our process for generating the server seed begins with creating a 12-word mnemonic phrase. This involves encoding entropy in multiples of 32 bits and then generating a checksum from the SHA256 hash of this entropy. The combined entropy and checksum bits are then used to form the mnemonic phrase.

Entropy and Checksum Calculation

CS = ENT / 32
MS = (ENT + CS) / 11

| ENT | CS | ENT+CS | MS |
+-------+----+--------+------+
| 128 | 4 | 132 | 12 |
| 160 | 5 | 165 | 15 |
| 192 | 6 | 198 | 18 |
| 224 | 7 | 231 | 21 |
| 256 | 8 | 264 | 24 |

JS Fairness Model for Float and Integer Generation

const generateFloats = async ({
cursor = 0,
count = 1,
range = [0, 1],
clientSeed,
serverSeed,
nonce = 0,
intOnly = false,
checkScaledResult = true,
}: Props) => {
// Random number generator function
const rng = byteGenerator(cursor, clientSeed, serverSeed, nonce);
// Declare bytes as empty array
const bytes = [];

// Populate bytes array with sets of 4 from RNG output
while (bytes.length < count * 4) {
const item = await rng.next();
bytes.push(item?.value);
}
// Return bytes as floats
const floats: number[] = [];
const byteChunks = chunkArray(bytes, 4);
for (const bytesChunk of byteChunks) {
let result = 0;
for (let i = 0; i < bytesChunk.length; i++) {
const divider = Math.pow(256, i + 1);
const partialResult = bytesChunk[i] / divider;
result += partialResult;
}
if (checkScaledResult) {
// Scale the result to the desired range
const scaledResult = result * (range[1] - range[0]) + range[0];
let validResult = intOnly ? Math.floor(scaledResult) : scaledResult;
while (floats.includes(validResult)) {
validResult++;
if (validResult > range[1]) {
validResult = range[0];
}
}
floats.push(validResult);
} else {
floats.push(result);
}
}

return floats;
};

const generateIntegers = async ({
cursor = 0,
count = 1,
minRange = 0,
maxRange = 100,
clientSeed,
serverSeed,
nonce = 0,
additionalIndex = false
}: IntegerProps) => {
let countFloats = maxRange - minRange;
if (additionalIndex) {
countFloats = (maxRange - minRange) + 1;
}
const floats: number[] = await generateFloats({ cursor, count: countFloats, clientSeed, serverSeed, nonce, checkScaledResult: false });
const positions = [...Array(countFloats).keys()].map(i => i + minRange);

for (let i = 0; i < positions.length; i++) {
let j = i + Math.floor(floats[i] * (positions.length - i));
j = Math.min(j, positions.length - 1);
const temp = positions[i];
positions[i] = positions[j];
positions[j] = temp;
}
return positions.slice(0, count);
};

Converting the Mnemonic Phrase to a Binary Seed

To generate the binary seed from the mnemonic phrase, we use the PBKDF2 function with HMAC-SHA512. The phrase is used as a password, and the salt is the string "mnemonic".

Final Conversion to a 64-Character Hex String

We further process the 128-character string to conform to the traditional 64-character hex string format used in result generation.

Rotating Your Seed Pair

When a player sets a new client seed, our system automatically rotates the server seed as well. This process, referred to as "rotating your seed pair," ensures that both the server and client seeds remain synchronized and fresh for each game, enhancing the integrity of our randomness generation.

Nonce

The nonce, incrementing with each bet, works in tandem with the client and server seeds to generate unique outcomes for each game. This ensures the fairness and unpredictability of each bet.

Conclusion

This innovative approach to server seed generation enhances the user experience by making the process of result verification more approachable and understandable. It maintains high entropy and cryptographic security, mirroring the methods used in cryptocurrency wallet generation. This not only ensures the integrity of our games but also strengthens player confidence in the fairness and transparency of our gaming platform.

CasinoSports