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

List of Blockchain where Solidity can be used

Most people people know that Solidity can be used to develop Ethereum smart contracts. However, very few people also know…

Read Story

Geth source code explained in 2 mins


In this article, we will dive into the source code of Ethereum. 

Most Blockchain app developers will not go this…

Read Story

Hardhat in 2 mins


In this article I will introduce Hardhat, a framework for smart contracts.

 With Hardhat you can compile, deploy, test, and…

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