Generating random numbers in Solidity easily
Published
Random numbers are commonly used in programming. Imagine you want to create a game in which users can roll a dice, or receive cards that have been shuffled. In all those cases you're going to need an algorithm that generates randomness.
Pure random numbers are not possible to create in Solidity due to the deterministic aspect of smart contracts, but that doesn't mean we cannot generate semi random numbers without using an oracle, which can be useful in a lot of cases 😉
In order to generate a semi-random number in Solidity, we're going to leverage the keccak256()
hash function, which transforms an input into a 256-bit hexadecimal number.
This function accepts a single parameter so, in order to add some randomness we're going to use abi.encodePacked
to contatenate three different parameters into a long one:
- the
now
alias, which will return the specific number of seconds since the epoch. - the
msg.sender
, which will be different depending on the user that sent the transaction. - a
seed
that we'll increase every time the function is invoked.
You can read more about how to concatenate strings in solidity here.
We'll cast the hash result from our concatenated string to uint
and then use the modulus operator %
to return the rest.
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
contract MyContract {
uint seed = 0;
function generateRandomNumber(uint _modulus) internal returns(uint){
seed++;
return uint(keccak256(abi.encodePacked(now, msg.sender,seed))) % _modulus;
}
}
For example if we want to generate a random number between 0 and 100, we'll call the generateRandomNumber()
function with a 100 modulus.
Keep in mind that this numbers are not 100% random but this is a very good approach that can be used in different scenarios. For pure random numbers we'd probably have to use an oracle to import external data into our contract.
TAGS