Random Algorithm

Lucky Bot uses future on-chain block data from ETH as a foundational seed to generate reproducible random results. When a draw occurs, the program fetches the most recent block relative to the current time and extracts relevant hash data from it. This data includes:

  • Block ID
  • Block Hash
  • Miner Hash
  • Block Timestamp

Due to the decentralized nature of the blockchain, unless an attacker controls more than 51% of the entire ETH network's computing power, the seed is guaranteed to be unpredictable, enhancing the fairness of the lottery results.

Blockchain Characteristics

Block generation is a core process in a blockchain network. Taking Ethereum (ETH) as an example, blocks are packaged and generated by miners through the Proof of Work (PoW) mechanism. Whenever new transactions are broadcast to the network, miners collect these transactions and attempt to find a hash value (i.e., the block hash) that meets specific conditions by performing calculations. This process consumes a significant amount of computing power, making it difficult to predict or tamper with in advance.

Each block contains the hash of the previous block, transaction data for the current block, a timestamp, the miner's address, and other information. Because each block depends on the hash of the previous one, a chain-like structure is formed, ensuring the immutability and security of the blockchain. Only when a miner successfully finds a qualifying hash is the block added to the chain and recognized by all nodes in the network.

Precisely because of the unpredictability and decentralized nature of the block generation process, block hashes and related data on the blockchain can serve as a highly credible source of randomness, widely used in scenarios like lotteries and random number generation.

Algorithm Implementation and Verification

This is a Python implementation of the algorithm. Its logic is fundamentally the same as the original version and can produce identical results, which can be used to verify if the results have been tampered with.

LRG Open Source Code

The program requires Block ID, Block Hash, Miner Hash, and Block Timestamp as input. This data can be found in the Mini App or through the API of etherscan.io. It should look something like this:

JSON
{
    "number": "0x157acfe",
    "hash": "0x8a826e6c3cbeacc82937ad7b6a821a6a25b63383bc05eb0ddb807bb41c518d34",
    "miner": "0x4838b106fce9647bdf1e7877bf73ce8b0bad5f97",
    "time": "0x682c4633",
    "count": 1
}

count is actually an operand counter. Due to potential rollbacks, the number of operands might exceed the total number of winners. This parameter is only provided in the Mini App.

Verifying Lottery Results

The Python implementation above includes a main.py file. Please modify the following data to reproduce the lottery results:

Block Data (L3 - L9)

Python
block = {
    "number": "0x157acfe",
    "hash": "0x8a826e6c3cbeacc82937ad7b6a821a6a25b63383bc05eb0ddb807bb41c518d34",
    "miner": "0x4838b106fce9647bdf1e7877bf73ce8b0bad5f97",
    "time": "0x682c4633",
    "count": 1
}

Prize Data (L11 - L14)

The order must be identical to the original list.

Format: ["Prize Name", Quantity]

Python
prizes = [
    ["P1",  3],
    ["P2",  3],
]

Participants (L16 - L19)

The order must be identical to the participant list in the Mini App. Note that the order in the Mini App is actually a reverse chronological list of participation events, so the verification script will automatically reverse the order; no manual processing is needed.

Python
members = [
    "User1",
    "User2",
]

Run Calculation

  • Linux / macOS: python3 main.py
  • Windows: python main.py
Output
Winner: User2 - Prize: P2
Winner: User1 - Prize: P2
Total number: 2

Algorithm Implementation

  1. The program will concatenate all data into a single string and compute its SHA256 hash, which serves as the basis for the random seed.
Python
seed_input = block["number"] + block["hash"] + block["miner"] + block["time"]
seed = hashlib.sha256(seed_input.encode()).hexdigest()
  1. The program iterates through each character of the seed string, performing bitwise operations to generate a 32-bit integer as the initial random value.
Python
hash_value = 0
for char in seed:
    hash_value = (hash_value << 5) - hash_value + ord(char)
    hash_value &= 0xFFFFFFFF  # Simulate 32-bit integer overflow
  1. A simple Linear Congruential Generator (LCG) algorithm is used. Each time get_random_int(max_value) is called, it generates a new pseudo-random number based on the current hash_value and takes the modulo of the target range to ensure the result falls within the specified interval.
Python
def get_random_int(max_value: int) -> int:
    global hash_value
    hash_value = (hash_value * 9301 + 49297) % 233280
    return abs(hash_value) % max_value
  1. In each round of the draw, a prize is randomly selected first, then a member is randomly selected, and the winning information is recorded. If the quantity of a prize reaches 0 or a member has already won, they are removed from their respective lists, and the process continues to the next round until all prizes or members are exhausted.

  2. Since the randomness of the entire process depends entirely on on-chain block data and the algorithm is public and transparent, anyone can reproduce the lottery results using the same block data, ensuring the fairness and immutability of the draw.