Storing array of random numbers from Chainlink VRFv2 for later use

I have a scenario in which I need to generate some on-chain random attribute for an NFT after it's minted with the max supply being 10k tokens. In the testing I've done on Rinkeby, if I call Chainlink VRFv2 to request one new random number for each mint it's costing around .35 LINK (so ~$2.50 at time of writing), meaning after all 10k are minted I would have spent $25k in gas.

Instead of calling Chainlink during each mint, couldn't I pre-request the random numbers (e.g before the mint starts) and do something like the following?:

// Array to store all random numbers
uint256[] private allRandomNums;

// Call this before minting begins
function requestAllRandomNumbers() public onlyOwner {
            10, // confirmations
            250000, // callback gas limit
            10000 // numwords

function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal virtual override {
      allRandomNums = randomWords;

function mint() public {
    uint256 tokenId = totalSupply();

    uint256 randomNum = allRandomNums[tokenId];
    // Set some attribute randomly using randomNum

Would this leave the door open for a reroll attack since the minting and attribute setting are all done within mint() (ala Meebits)? Is there anything else I am overlooking?

Tagging you @PatrickAlphaC since you seem to be the go-to for Chainlink questions! Any insight would be greatly appreciated.

Yep, this leaves the door open for a reroll attack :frowning:

Someone could easily see all the random numbers and try to compute for whatever number they want. Who is minting the NFTs here? Is it the users?

1 Like

@PatrickAlphaC Yeah they would be user-minted. Would a valid workaround be to have the random attribute set in a separate transaction, such as a "reveal" function (although obviously, this would incur additional gas on the part of the person minting)?

Yes... but depending on how you do the reveal it could be "un-randomized".