SKALE RNG Endpoint

Each SKALE Chain supports a special random number generator (RNG) precompiled. This RNG is generated for every block and is based on the current block’s threshold signature shares of at least SKALE nodes supporting any given SKALE Chain.

SKALE chain consensus is asynchronous and leaderless, and blocks are signed by at least nodes. Each signature is glued together such that no single node can influence the resulting signature. This process ensures that results cannot be tampered with or manipulated by a single entity.

General steps:

  1. The signatures for the current block are retrieved.

  2. The BLAKE3 hash of the signatures is created.

  3. The resulting hex RNG is presented.

To use the RNG precompiled, you can use the following code example to access the getBlockRandom precompiled at address 0x18:

pragma solidity ^0.8.13;

contract A {

    function getRandom() public view returns (bytes32 addr) {
        assembly {
            let freemem := mload(0x40)
            let start_addr := add(freemem, 0)
            if iszero(staticcall(gas(), 0x18, 0, 0, start_addr, 32)) {
              invalid()
            }
            addr := mload(freemem)
        }
    }
}

Running getRandom() from Remix several times will return the following example output for each new block:

0:bytes32: addr 0xb01da4532b80108eee3d00d48d6c617869eabfa39acbb58b7fd44e8369331501
0:bytes32: addr 0x48e4af915a9cf211474c11fec16dd40164a1d6d82dec93a646b4b776261a9fe5
0:bytes32: addr 0x7d95dd4d341e6bf27ce37e1dc531319daa1dfd75efe4a5f1b1de1f3062425155
0:bytes32: addr 0x80494d5289618a28ca5ed57803404a4c3b379699d81ae1badf408fb8341c8ef7
0:bytes32: addr 0xfd66a3c359c1c73f285f881105bb8ef5185cc04d5c8c7360c4386f0673ecc98b
0:bytes32: addr 0xb95f1c2be3b13371115b8e6431461a24e960f0bb9881420993528ce68b019f75

Frequently Asked Questions

How do I generate different random numbers within the same block?

There are a few ways to do this.

  • Concatenate a counter: in your dApp you may create a counter i then do:

    NEW_RANDOM = KECCACK_HASH(OLD_RANDOM | i)
    i++
  • Iterate through each byte of the resulting hash.

How do I generate an integer from the result?

There are a few ways to do this:

getRandom()%10    // integer between 0 - 9
getRandom()%100   // integer between 0 - 99
getRandom()%1000  // integer between 0 - 999
Can I see example projects that use this?

Here is an example from a Hacker submission to EthPortland. This example uses getRandom to finalize any unsettled simple majority DAO vote.