2

I am constructing some nft metadat on-chain, and need to grab pseudo random number for each of the traits, these numbers need to be different.

So far best I came up with is following

  function getRandomNumbers(string memory seed) private view returns (uint256[8] memory) {
    return [
      randomise(string(abi.encodePacked("property 1", seed)), property1Arr.length),
      randomise(string(abi.encodePacked("property 2", seed)), property2Arr.length),
      randomise(string(abi.encodePacked("property 3", seed)), property3Arr.length),
      randomise(string(abi.encodePacked("property 4", seed)), property4Arr.length)
    ];
  }

  function randomise(string memory seed, uint256 range) private view returns (uint256) {
    return uint256(keccak256(abi.encodePacked(seed, block.difficulty, block.timestamp, block.number))) % range;
  }

So brief explanation, getRandomNumbers takes in "seed" from client and combines it with property string, this is repeated multiple times for each property. Then resulting combined string is used as "seed" for randomise that returns random integer by further randomising it using some block data and returning number that is in range for the array of properties.

This does decent job, but doesn't scale well, so I am wondering if there is a better approach here that I might be missing.

2 Answers 2

2

Maybe the following approach will work for you. The basic idea is that instead of "throwing away" most of the random number after doing "% range", you continue using it.

function getRandomNumbers(string memory seed) public view returns (uint256[4] memory) {
    (uint a, uint b, uint c, uint d) = (5,5,10,20);
    uint256 randomKeccak = uint256(keccak256(abi.encodePacked(seed, block.difficulty, block.timestamp, block.number)));
    return [
      randomKeccak % a,
      randomKeccak / a % b,
      randomKeccak / a / b % c,
      randomKeccak / a / b / c % d
    ];
}

Here a,b,c,d are the lengths of the various propertyArrs.

This is just a proof of concept. You can perhaps also use bit operations for this.

1
  • 1
    Super interesting approach!
    – Ilja
    Oct 28, 2021 at 16:02
0

Have you check Chainlink's Keepers?

1
  • 1
    Do you mean chainlink vrf for random numbers? Yeh, I considered it, however for my needs it is too expensive, plus getting 1 random number from it and then making more random numbers for each of my properties actually results in even more gas cost to the end user compared to what I do above.
    – Ilja
    Oct 27, 2021 at 14:04

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.