1

I'm working on a solidity contract that leverages random numbers through the use of Oracles. (ChainLink). Obviously given the price and the time it takes to get a random number I'm looking for the best ways to reuse that seed to generate more than 1 random number.

I have the following code which is supposed to generate 2 random numbers per loop 1 between 0 and 99 and the other one between 0 and 2. So a total of 20 random numbers in this example.

uint256 randomness = 78076127350936886139585537764964110448646985064549445555744769369952641998556;
for (uint256 i = 0; i < 10; i++) {
  uint8 random1 = SafeCast.toUint8((randomness % (100 + i)) % 100)
  uint8 random2 = SafeCast.toUint8((randomness % (100 + i)) % 3)
}

Seems to work okay but wanted to make sure if that made sense math wise or if there was a better way of doing this.

Paté
  • 1,914
  • 2
  • 22
  • 33
  • Your approach to randomness reminds me of this: https://xkcd.com/221/ – John Coleman Nov 29 '21 at 19:07
  • @JohnColeman to be clear the randomness seed is fed by chainlink oracle. I've hardcoded it here for clarity. – Paté Nov 29 '21 at 19:10
  • 2
    It seems possible that using modular arithmetic like that will create [modulo bias](https://stackoverflow.com/a/10984975/4996248) (especially with the %3) and perhaps introduce correlations between successive numbers as well. Perhaps you could add the `random` tag to get the attention of someone with expertise in RNGs. – John Coleman Nov 29 '21 at 19:19
  • You could do worse than reading the excellent [*Fast Random Integer Generation in an Interval*](https://arxiv.org/abs/1805.10941) research paper by Daniel Lemire on the subject. It was published in 2018 so is reasonably current. – jpmarinier Nov 29 '21 at 20:30
  • I have seen a lot of recommendations of `keccak256(abi.encodePacked(randomness,i))` and then use that to generate the random number, i'm not sure if it is a better solution but maybe could help – jhonny Nov 29 '21 at 22:35
  • 1
    Could you please help to understand why you cannot use the 256-bit randomness to seed a prng? If you need to create 8-bit random numbers, you can split up your 256-bit random number into 256/8=32 pieces, and all pieces will be still random. – DanielTuzes Nov 29 '21 at 23:58
  • @DanielTuzes, I need more than 32 random numbers unfortunately. I need a couple hundreds roughly. I could ask the oracle for more than 1 but it cost about 3$ a pop so a mathematical solution is prefered. – Paté Nov 30 '21 at 15:56

1 Answers1

0

Found the documentation on how to do this.

https://docs.chain.link/docs/chainlink-vrf-best-practices/#getting-multiple-random-numbers

function expand(uint256 randomValue, uint256 n) public pure returns (uint256[] memory expandedValues) {
    expandedValues = new uint256[](n);
    for (uint256 i = 0; i < n; i++) {
        expandedValues[i] = uint256(keccak256(abi.encode(randomValue, i)));
    }
    return expandedValues;
}
Paté
  • 1,914
  • 2
  • 22
  • 33