How to Generate Pseudo-Random Numbers in Ink! Smart Contract
Generating random numbers is an essential feature of many decentralized applications, but generating truly random numbers in a trustless, decentralized environment is a challenging problem. In this article, we will show you how to implement a simple pseudo-random function in your Ink! smart contract and generate pseudo-random numbers within a specified range.
Implementation
First, create a new Ink! smart contract and modify the PseudoRandom
struct to include the salt
variable. The salt
will be incremented by 1 each time the get_pseudo_random
function is called.
#[ink(storage)]
pub struct PseudoRandom {
salt: u64,
}
Then, update the get_pseudo_random
function to take an input parameter for the maximum value in the range, and to return a number between 0 and the maximum value in the range using the following code:
use ink::env::hash;
#[ink(message)]
pub fn get_pseudo_random(&mut self, max_value: u8) -> u8 {
let seed = self.env().block_timestamp();
let mut input: Vec<u8> = Vec::new();
input.extend_from_slice(&seed.to_be_bytes());
input.extend_from_slice(&self.salt.to_be_bytes());
let mut output = <hash::Keccak256 as hash::HashOutput>::Type::default();
ink::env::hash_bytes::<hash::Keccak256>(&input, &mut output);
self.salt += 1;
let number = output[0] % (max_value + 1);
number
}
This function generates a hash value that is based on the block timestamp and the incremented salt
value. The max_value
parameter is used to determine the maximum value in the range. The modulo operator % (max_value + 1)
is then used to return a number between 0 and the maximum value in the range.
Usage
To generate a pseudo-random number within a specified range, simply call the get_pseudo_random
function with the maximum value in the range as the input parameter. For example, to generate a number between 0 and 99, you would call the function with a max_value
of 99:
let mut my_contract = PseudoRandom::new();
let random_number = my_contract.get_pseudo_random(99);