How to generate a random number in smart contract?

jklepatch

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;
    }
}

More great articles

Ethereum Tokens explained to Developers – Full Guide (9 tokens covered)

ERC this, ERC that... so many token standards... If you want to become good in Solidity, you HAVE to understand…

Read Story

Graph of memory locations in Solidity: storage, calldata, etc…

In Solidity smart contracts, there are 4 memory locations: storage memory stack calldata They all have different lifetimes and it's…

Read Story

Overview of solutions for querying Ethereum with GraphQL

Have you heard of GraphQL? That's an alternative to REST apis that was created by Facebook. With GraphQL, clients specify…

Read Story

Never miss a minute

Get great content to your inbox every week. No spam.

    Only great content, we don’t share your email with third parties.
    Arrow-up