Chainlink – Is Using Modulo to Get Range from VRF Number a Good Idea for Randomness?

chainlinkrandomnessvrf

I'm building a lottery game contract and I need to get a range of values from chainlink VRF's number. The range is the length of the players list. For simplicity, I've made a simple contract that demonstrates my idea of how to get a ranged random number from Chainlink's VRF number. To do this I have decided to take the modulo N of Chainlink's number, where N is the length of the players list.

My worry is that this process makes the number less random, more biased and therefore not fair. Am I right to worry? If so, what's a better approach for this problem?

pragma solidity ^0.8.0;

contract GetRandomNumber{
    string[] playersList = ["bob", "alice", "lux", "ahri", "nunu", "amumu", "jax", "olaf", "jinx", "vayne", "twitch", "alistar", "annie", "leona", "warwick"];
    uint256 public randomNumber;

//actual random number from Chainlink VRF
    uint256[] chainlinkVRFNumberList = [64062631830175213092191689838209884690462398265195175129745934432936884152163];
    uint256 public chainlinkVRFNumber = chainlinkVRFNumberList[0];

    constructor(){
        getNumber(chainlinkVRFNumber);
    }

    function getNumber(uint256 x) internal {
        uint256 value = (x % playersList.length) + 1;
        randomNumber = value;
    }


}```

Best Answer

Since the number returned by Chainlink VRF is verifiably random, that's the important source of randomness. The N is not really important for randomness as the N may or may not hold a constant value over the lifetime of calls.

but since the VRF-returned uint is random, the result of applying modulo N to that number will be random too.
as a simple thought experiment, randomly pick numbers in your head between 0 and 20 and apply modulo 4 (or another number). The results will be different and "random" based on how randomly you picked your numbers.

This is assuming you discard the VRF-returned number each time and use a new one. Re-using a random number for several calculations may drift towards less randomness.

Your approach is fine and is consistent with best practices for getting a random number within a range.