How to Generate Random Numbers in Solidity

1/5 - (1 vote)

Creating a game of lottery where you need to generate a random number to pick a winner can be a simple task when you use the libraries of programming languages like Python or JavaScript.

But in the case of Solidity, creating a secure random number is a very complex task. Due to the deterministic character of the blockchains, it is impractical to generate multiple random numbers in Solidity. However, if we want to develop some, we must look for off-chain resources like an oracle. Otherwise, it will be easier for the miners to manipulate any number generator using the blockhash. Some naive approaches to creating a random number, where we can’t ignore the possibility of hacking, are below.

Method 1: Using block.difficulty

pragma solidity ^0.8.0;
contract RandomNumbers{
    function random(uint number) public view returns(uint){
    	return uint(keccak256(abi.encodePacked(block.timestamp,block.difficulty,  
    	msg.sender))) % number;
    }
}   

We have created a function random()” inside the contract, which takes an argument “number“. This argument defines a specific range for the random number generator. For instance, if you input 100 as a “number“, it will generate any random number ranging from 1-99.

  • We used a hash algorithm inside the return option. β€œblock.timestamp” represents the time at which we call the function, and β€œblock.difficulty” expresses the current difficulty of the blockchain.
  • β€œmsg.sender” determines the address of the sender of the transaction.
  • Then we combined all of these with the β€œabi.encodePacked” library. It is an obscured type of function that we do not often use, but It can be helpful to calculate the hash of the blockchain.
  • abi.encodePacked” transforms the hash into bytes.
  • β€œkeccak256” computes the hash of the input and takes the byte value as an argument.
  • At last, we used the β€œuint” identifier to get the integer value of the hash.
  • We used the modulo (%) operator to get the remainder after division by the β€œnumber”.

We deployed the contract on remix Ethereum and input the number range as 100 in the “random” function. It returned the value of 78. Each time we click on the random button, we will see a different outcome of a number ranging from 0-99 as the modulo operator returns the remainder of 100.

Method 2: Incrementing the Number

pragma solidity ^0.8.0;
contract RandomNumbers{
    uint initialNumber;
    function createRandom(uint number) public returns(uint){
        return uint(keccak256(abi.encodePacked(initialNumber++))) % number;
    }
}

We can add more randomness by using the similar concept explained in the first method. Instead of generating a random number based on the current difficulty of a block as we did in the first method, we can develop a random number based on an incrementing value.

We defined an initial number inside the β€œRandomNumbers” contract. Here the function “createRandom” returns a different value each time we call the function. Again, it is not actually a random number, but it is random based on an incrementing value. Now let’s deploy the code and input the value of the number as 1000. If we start the transaction, we will see 947 has come out as a decoded output. Each time we call the function by clicking the transact button, it will create a different value.

Method 3: Using Blockhash

pragma solidity ^0.8.0;
contract RandomNumbers{
    function createRandom(uint number) public view returns(uint){
        return uint(blockhash(block.number-1)) % number;
    }
}

Since the hash number of each block is different from one another, we can use the hash number directly for creating randomness. In the above code, we applied the hash number of the previous block to generate random numbers. We can not obtain the hash number of the current block as the transaction is progressing and it is not yet included in the block. That’s why we used (block.number - 1) to get the previous block’s hash.

As we deployed the contract, it returned 27. Every time we click the create random button, it will come up with new numbers.

However, this method may not work correctly in remix Ethereum if the ganache truffle suit is not installed. Due to the continuous security update of solidity, you probably have some issues while running the code. But yet it was executable in my case.

How to Generate an Array of Random Numbers

In this section we will try to create a smart contract which generates an array that shuffles the numbers each time we call the function. let’s write the code first.

pragma solidity ^0.8.0;
contract RandomNumberarray{
    function random(uint[] memory _myArray) public view returns(uint[] memory){
        uint a = _myArray.length; 
        uint b = _myArray.length;
        for(uint i = 0; i< b ; i++){
            uint randNumber =(uint(keccak256      
            (abi.encodePacked(block.timestamp,_myArray[i]))) % a)+1;
            uint interim = _myArray[randNumber - 1];
            _myArray[randNumber-1]= _myArray[a-1];
            _myArray[a-1] = interim;
            a = a-1;
        }
        uint256[] memory result;
        result = _myArray;       
        return result;        
    }
}    

The function random() inside the contract takes an array of numbers as an argument. In this case, we named this as _myArray. Then we created two variables called “a” and “b“, representing the length of _my_array.

We used a for loop to loop through the length of _myArray, and keccack256 enabled us to generate random numbers in _myArray.

The modulo operator is used again in the same way to bound the returned numbers in a particular range, as we did in the earlier methods. The function returned an array with all the random numbers generated. So, let’s deploy the contract and see if it works.

Whenever I deployed the contract, I was asked to input an array of numbers. I input an array with the numbers [48,95,7,34,23,76,56,45]. From the image above we can see it gave us [45,98,7,34,23,76,56,45] as a result. Every time we call the function, we will see an array with changed serial numbers.

I tried to give an insight into how to generate random numbers in Solidity. But none of the methods is safe to apply in real-world solidity smart contracts as the miner can dig in easily. However, we will address the oraclize implementation of randomness in the next finxter blog that represents the true implementation of randomness.

The following links may be helpful for further information:

Learn Solidity Course

Solidity is the programming language of the future.

It gives you the rare and sought-after superpower to program against the “Internet Computer”, i.e., against decentralized Blockchains such as Ethereum, Binance Smart Chain, Ethereum Classic, Tron, and Avalanche – to mention just a few Blockchain infrastructures that support Solidity.

In particular, Solidity allows you to create smart contracts, i.e., pieces of code that automatically execute on specific conditions in a completely decentralized environment. For example, smart contracts empower you to create your own decentralized autonomous organizations (DAOs) that run on Blockchains without being subject to centralized control.

NFTs, DeFi, DAOs, and Blockchain-based games are all based on smart contracts.

This course is a simple, low-friction introduction to creating your first smart contract using the Remix IDE on the Ethereum testnet – without fluff, significant upfront costs to purchase ETH, or unnecessary complexity.