So funktioniert Provably Fair bei Dice
So spielst du Dice auf Cloudbet, und so überprüfst du, dass jeder Wurf provably fair ist.
So spielst du Dice
Dice ist ein rasantes Spiel, bei dem du darauf wettest, ob eine zufällig generierte Zahl über oder unter einem von dir gewählten Zielwert landet. Wähle eine Zielzahl und entscheide, ob du darauf setzt, dass das Ergebnis darüber (Roll Over) oder darunter (Roll Under) landet. Je näher dein Ziel am Rand des Bereichs liegt, desto geringer ist deine Gewinnchance — aber desto größer dein Gewinn, falls du triffst. Sobald du deine Wette platzierst, wird das Ergebnis sofort angezeigt.
Cloudbet Originals Dice
Cloudbets eigenes Originals Dice nutzt einen Zielbereich von 0,00 bis 100,00, einen RTP von 99 %, einen maximalen Multiplikator von x9.800 und akzeptiert Einsätze von 0,01 $ bis 10.000 $. Auto Bet steht zur Verfügung, um eine Reihe von Runden zu automatisieren.
Diese Seite behandelt, wie Dice eine verifizierte Zufallszahl in deinen Wurf umwandelt. Wie der zugrunde liegende Zufall selbst generiert und abgesichert wird — Server-Seed, Client-Seed, Nonce, Hashing —, erfährst du auf unserer Provably-Fair-Seite. Spielst du Dice: Golden Ticket? Der Würfelwert wird dort auf dieselbe Weise ermittelt wie hier beschrieben, nur kommen zusätzlich ein Golden-Ticket-Wert und -Multiplikator hinzu.
Zufallszahlen werden zu einem Dice-Ergebnis
Das Ergebnis von Dice muss nachweislich an dieselbe verifizierbare Zufälligkeit gebunden sein wie jedes andere Cloudbet Original. Sobald die Zufallszahlenfolge einer Runde generiert ist (über SHAKE256 — siehe den Provably-Fair-Prozess für diesen Ablauf), verwendet Dice sie so:
Eine ganze Zahl zwischen 0 und 10.000 (einschließlich) wird aus der Folge gezogen und dann durch 100 geteilt — das ergibt einen Wert zwischen 0 und 100 mit zwei Nachkommastellen. Das ist dein Dice-Ergebnis.
So funktioniert die Zufallsauswahl
Dice hat 10.001 mögliche Ergebnisse (0,00 bis 100,00 in Schritten von 0,01), daher gilt für dieses Spiel P = 10.001.
Um fair unter diesen 10.001 Ergebnissen auszuwählen, verwendet Dice dieselbe Rejection-Sampling-Methode, die in unserem Provably-Fair-Leitfaden beschrieben wird — eine zufällige 32-Bit-Zahl wird generiert und anschließend verworfen und neu gezogen, falls sie das Ergebnis verzerren würde, bis eine faire Zahl gefunden ist. Diese Zahl wird dann per Modulo-Operation gegen 10.001 auf einen Wert zwischen 0 und 10.000 abgebildet, der für das Endergebnis durch 100 geteilt wird.

Spielablauf
Das Ergebnis wird auf dem Server generiert und festgelegt, bevor du deine Wette platzierst — es kann nach Rundenbeginn nicht unbemerkt geändert oder verändert werden. Nach deiner Wette wird dein gewählter Schwellenwert mit dieser vorab generierten Zahl verglichen, um zu bestimmen, ob du richtig lagst.
Code zur unabhängigen Verifizierung der Provable Fairness von Dice
Dieses Programm entspricht exakt Cloudbets Dice-Implementierung. Gib deinen Server-Seed, Client-Seed und Nonce ein, um deine eigenen Ergebnisse zu verifizieren. Hinweis: Um den Server-Seed einer Runde auf Cloudbet offenzulegen, musst du zunächst zu einem neuen Server-Seed rotieren.
Abhängigkeiten:
npm install js-sha3
Der Code:
// If you are running this yourself, then you can input your own data here
// You can then compare:
// 1) Cloudbet's provided Commitment to the Commitment outputted here. This proves that the Server Seed was not altered during gameplay.
// 2) Cloudbet's provided game outcome to the game outcome outputted here. This proves that your game's outcome was determined solely by the pre-game seeds and was not altered afterwards.
let myServerSeed = 'your_server_seed'; // ✍️YOUR_INPUT✍️: Enter your (unhashed) Server Seed here
let myClientSeed = 'your_client_seed'; // ✍️YOUR_INPUT✍️: Enter your Client Seed here
let myNonce = 1; // ✍️YOUR_INPUT✍️: Enter your Nonce here
const usingCustomData = false; // Change this to true if you are using your own data
// Load libraries
const crypto = require('crypto');
const { sha3_256, shake256 } = require('js-sha3');
// Step 1: Generate a Server Seed and Commitment
// And generate a Client Seed - either by player input or by the player's browser
function generateServerSeed() {
let seed = crypto.randomBytes(32).toString('hex');
if (usingCustomData) { seed = myServerSeed; }
const commitment = sha3_256(seed);
return { 'serverSeed': seed, 'commitment': commitment };
}
function getClientSeed() {
let seed = crypto.randomBytes(32).toString('hex');
if (usingCustomData) { seed = myClientSeed; }
return seed;
}
// Step 2: Create a Round Signature with SHA3 using a Server Seed, Client Seed and Nonce
function createRoundSignature(serverSeed, clientSeed, nonce) {
return sha3_256(`${serverSeed}:${clientSeed}:${nonce}`);
}
// Step 3: Create a SHAKE256 stream generator from a Round Signature.
// To simplify this example program, this function doesn't create a stream, but instead a sequence of custom length.
function* createRandomNumberSequence(numbersToGenerate, roundSignature) {
const numOfBytes = 4 * numbersToGenerate; // 4 bytes (32 bits) per random number we generate
const byteStream = shake256.create(8 * numOfBytes); // shake takes bits as input
byteStream.update(roundSignature); // Use the Round Signature to seed the generator
const buf = Buffer.from(byteStream.digest()); // The Buffer class lets us package every 4 bytes into one 32-bit integer
for (let i = 0; i < numbersToGenerate; i++) {
yield buf.readUInt32BE(i * 4); // Read buf in 4-byte steps
}
throw new Error("No more numbers in the random number sequence! Fix: make 'numbersToGenerate' larger.");
}
// Step 4: Draw from the random number sequence to calculate the game result
function getDiceResult(rng) {
const diceMinValue = 0;
const diceMaxValue = 10000;
let number = sampleFromRange(diceMinValue, diceMaxValue, rng);
number = number / 100; // So that the dice's value ranges from 0 to 100
return number;
}
// Sample a number between 'min' to 'max' (inclusive) using Rejection Sampling
function sampleFromRange(min, max, rng) {
const P = max - min + 1
const maxAcceptable = Math.floor(0x100000000 / P) * P;
// Rejection sampling
let rand;
do {
rand = rng.next().value;
} while (rand >= maxAcceptable);
// Modulo operation
const sampled_number = rand % P;
return sampled_number + min;
}
// Example usage
(function main() {
let nonce = 1;
if (usingCustomData) { nonce = myNonce; }
const { serverSeed, commitment } = generateServerSeed();
const clientSeed = getClientSeed();
const roundSignature = createRoundSignature(serverSeed, clientSeed, nonce);
const numbersToGenerate = 1 * 2; // We need 1 random number, however due to rejection sampling we may need more
const rng = createRandomNumberSequence(numbersToGenerate, roundSignature);
const diceValue = getDiceResult(rng);
console.log('📝 Commitment (shown before the game):', commitment);
console.log('🔒 Server Seed (revealed after the game):', serverSeed);
console.log('🎲 Client Seed:', clientSeed);
console.log('🔢 Nonce:', nonce);
console.log('🔁 Round Signature (can be verified after the game):', roundSignature);
console.log('🎯 Dice landed on:', diceValue);
})();


