🎲Provably Fair
Our platform uses a provably fair system to generate random numbers for bets, ensuring transparency and fairness. We leverage the EOS blockchain, a public, immutable ledger, to source unpredictable block hashes that cannot be manipulated by our platform or users. This allows anyone to independently verify the randomness of the generated numbers.
How it works
Fetching the current block
When a bet is placed we query the EOS blockchain to retrieve the current block number using the
get_infoAPI endpoint fromeos.greymass.comWe add 3 blocks to the current block number to determine a target block, this delay ensures that the block hash is not known at the time the bet is placed, making it impossible to predict or manipulate the outcome.
Waiting for the target block
We wait for the target block to be created on the EOS blockchain (a few seconds)
Once the target block is available we retrieve its block hash using the
get_blockapi endpoint
Generate the random number
The block hash (64 char hexadecimal string) is used as the source of randomness
We take the first 8 characters of the hash and convert them to a 32 bit integer
The integer is scaled to fit within the desired range (2 for coinflip, 6 for diceroll, 1000 for Guess the number)
If the generated number exceeds the range then we reshash the value using sha256 and repeat the process until a valid number is produced.
Displaying results
Approx. 5 seconds after the bet is played we display the following verifiable data:
Initial Block Number: The block number at the time the bet was placed
Target Block Number: The block number used to generate the random number (initialBlock + 3)
Block hash: The hash of the target block
Random number: The final number generated scaled to the range 0 to max

Verifying the Randomness
Users can independently verify the random number by:
Visiting the public EOS blockchain explorer (Bloks.io) and entering the target block number to retrieve the corresponding block hash
Using the provided python code (below) to replicate the random number generation process
Comparing the generated random number to the one displayed by the platform
A verify randomness button in the UI
Python Code for Verification
Below is Python code that demonstrates how the random number is generated from the block hash
import requests
import hashlib
import time
async def get_current_block():
try:
response = requests.get("https://eos.greymass.com/v1/chain/get_info")
response.raise_for_status() # Raise an error for bad status codes
data = response.json()
return data.get("head_block_num")
except Exception as e:
print(f"Error fetching current block: {e}")
return None
async def get_block_hash(block_num):
try:
response = requests.post(
"https://eos.greymass.com/v1/chain/get_block",
headers={"Content-Type": "application/json"},
json={"block_num_or_id": block_num}
)
response.raise_for_status()
data = response.json()
return data.get("id")
except Exception as e:
print(f"Error fetching block hash: {e}")
return None
def hash_to_number_with_max(hash_str, max_value):
# Take first 8 characters of the hash and convert to integer
seed = hash_str[:8]
seed_int = int(seed, 16)
# Calculate scaling factor to ensure fair distribution
max_int = 2**32 - 1
scale_factor = max_int // max_value
random_number = seed_int
while random_number >= scale_factor * max_value:
# Rehash if number is out of range
hash_obj = hashlib.sha256(str(random_number).encode()).hexdigest()
random_number = int(hash_obj[:8], 16)
return random_number // scale_factor
async def get_provable_random_number(max_value):
# Get current block number
current_block = await get_current_block()
if not current_block:
raise Exception("Unable to fetch current block")
# Calculate target block (current + 3)
target_block = current_block + 3
block_hash = None
# Wait for target block to be created
while not block_hash:
block_hash = await get_block_hash(target_block)
if not block_hash:
time.sleep(1) # Wait 1 second before retrying
# Generate random number from block hash
random_number = hash_to_number_with_max(block_hash, max_value)
return {
"randomNumber": random_number,
"initialBlock": current_block,
"blockNum": target_block,
"blockHash": block_hash
}
# Example usage
import asyncio
max_value = 100 # Example max value for the random number
result = asyncio.run(get_provable_random_number(max_value))
print(result)Notes
Dependencies: Install the requests library using pip install requests
Verification: use the blockNum and blockHash from the result to check the block hash on bloks.io and run the hash_to_number_with_max function with the same max_value to confirm the randomNumber
Edge cases: If the api is unavailable or the target block is not yet created, the code retries every second until successful
Last updated