How to Generate Random Numbers in Solidity

Leon Do
Coinmonks

--

The many ways of generating random numbers on chain.

Overview

Smart contracts are deterministic, meaning anyone with the code and input can predict the output. Smart contracts are also public. Given public code, how can we make this non-deterministic?

Below are a few techniques

  • Pseudorandom Number by Hashing
  • On-chain Verifiable Random Function (VRF)
  • Off-chain Verifiable Random Function (VRF)
  • Commit-Reveal Randomness

Pseudorandom Number by Hashing

Pros

  • Easy to implement on all EVMs

Cons

  • Least secure

The idea is to generate random number by hashing the blockhash, timestampand transaction origin. This is pseudorandom because miners can theoretically generate these values before submitting the blocks.

Don’t use this technique if a lot of money relies on this number.

function random() internal view returns (uint256) {
return uint256(keccak256(abi.encodePacked(
tx.origin,
blockhash(block.number - 1),
block.timestamp
)));
}

Source

On-Chain Verifiable Random Function

Pros

  • On chain security

Cons

  • Limited to certain blockchains

Overview

Some chains have VRF built directly into their protocol. For example Harmony uses their Poof of Stake and BLS signatures to sign off on blocks which can produce can produce a signature. Each signature can be hashed to generate a random number. In short, certain blockchains can produce a random number per block.

Demo

Source

Off-Chain Verifiable Random Function

Pros

  • More secure than pseudorandom numbers
  • Can work on multiple blockchains

Cons

  • May require holding and spending their native token.

Overview

Chainlink is a solution that generates it’s randomness using off-chain using oracles. This technique is used in dApps such as PoolTogether. Winners are randomly chosen to win a prize. Since randomness equates to large amounts of money, it’s important to have true (not pseudo) randomness.

Commit Reveal Randomness

Pros

  • Works on all EVMs and is secure

Cons

  • Request two transactions

Another technique is to use commit reveal to generate a random number.

Steps

  1. User generates a pre-image (number) off-chain and commits the hash
  2. Smart contract saves the hash on-chain
  3. User waits at least one block
  4. User reveals the pre-image. If the hash of the pre-image matches the saved hash (in step 2), then generate a random number on chain
  5. Generating a random number: hash the pre-image+ blockhash

Steps (Simplified)

The idea is to commit data in the present with data in the future. Since no one can know the future, it’s not possible determine the random number.

  1. User saves the number 111on chain. This cannot be changed.
  2. User waits one block
  3. The block now generates a blockhash 222
  4. The new random number is 111 + 222 = 333

If there’s no waiting for future blocks, then the technique will be similar to: Pseudorandom Number by Hashing.

If there’s no commit, the user can wait for the blockhash then input their number to get the desired “random” number: myInput + 222 = myDesiredNumber

Demo

Source

New to trading? Try crypto trading bots or copy trading

--

--