fbpx

How to generate a random number in smart contract?

Julien Klepatch

Generating a random number in a smart contract is very useful, especially for games.

Can we do this in Solidity? Yes!

Here is the code:

pragma solidity ^0.6.0;

contract MyContract {
    function _randModulus(uint mod) internal returns(uint) {
        return uint(keccak256(abi.encodePacked(
            now, 
            block.difficulty, 
            msg.sender)
        )) % mod;
        nonce++;
        return rand;
    }
}

Let’s unpack everything!

First, we need a source of randomness, so we use

now, block.difficulty, msg.sender

Then we compute a hash of this – will be a bytes32 string like 0x89irwIRWOoo...:

keccak256(abi.encodePacked(
  now, 
  block.difficulty, 
  msg.sender
));

Then we cast this into an integer – this could be any (positive) integer, very small or very big:

uint(keccak256(abi.encodePacked(
  now, 
  block.difficulty, 
  msg.sender
)));

The final step is to use the modulo (%) operator to force this integer in a range:

uint(keccak256(abi.encodePacked(
  now, 
  block.difficulty, 
  msg.sender
))) % mod;

However, we have a problem…miners can manipulate now … Our random number is not safe to use…

We can fix this by importing a source of randomness outside of the control of the miner, by using an oracle (presumably controlled by someone we trust):

pragma solidity ^0.6.0;

contract Oracle {
    address admin;
    uint public rand;

    constructor() public {
        admin = msg.sender;
    }

    function feedRandomness(uint _rand) external {
        require(msg.sender == admin);
        rand = _rand;
    }
}

contract MyContract {
    Oracle oracle;
    uint nonce; //not strictly necessary

    constructor(address oracleAddress) public {
        oracle = Oracle(oracleAddress);
    }

    function foo() external {
        uint rand = _randModulus(10);
        //use rand however you want
    }

    function _randModulus(uint mod) internal returns(uint) {
        uint rand = uint(keccak256(abi.encodePacked(
            nonce,
            oracle.rand(),
            now, 
            block.difficulty, 
            msg.sender)
        )) % mod;
        nonce++;
        return rand;
    }
}

0 Comments

Leave a Reply

More great articles

Alternatives to web3.js

Web3.js is the leading client library for Ethereum. Personally, I am fine with it, but I know that some developers…

Read Story

Solana explained in 2 mins

Solana has been described as the next Ethereum killer.

 In 2021, the price of Solana skyrocketed. 

Even Celebrities are jumping…

Read Story
Read Blockchain Data

How to Read data from the Blockchain

In this article I will show you how to read data from the Blockchain. We will use short scripts written…

Read Story

Never miss a minute

Get great content to your inbox every week. No spam.
[contact-form-7 id="6" title="Footer CTA Subscribe Form"]
Arrow-up