does anyone know how I can fill an array with numbers 1 - 10,000 efficiently? For example, in our constructor we have the following but it doesn't work due to gas costs; too many items to push to a dynamic array. If I do, let's say 100, it works fine.
constructor() ERC721("Contract", "C") {
for (uint i = 1; i < 10001; i++) {
tokens.push(i);
}
}
Any ideas?
For context, in my smart contract we want to randomly choose an id to mint to avoid sequential minting, so we use a Chainlink VRF to get a random number less than the tokens array length, choose an id randomly from the array, then remove the last index to shrink the array using roughly this code:
uint[] tokens;
uint randomNumber = RandomNumberContract.randomResult();
function handleGetTokenId(uint _tokenOffset) public onlyOwner returns(uint) {
require(tokens.length > 0, "No more tokens left");
// random number based on number of tokens left
uint randomIndex = uint(keccak256(abi.encode(randomNumber, _tokenOffset))) % tokens.length;
// random id at index in array
uint randomId = tokens[randomIndex];
require(!_exists(randomId), "token already minted");
// at position randomIndex, replace with last id
tokens[randomIndex] = tokens[tokens.length - 1];
// remove last index; shortens length and ensures no double minting
tokens.pop();
return randomId;
}
The issue is, we have 10,000 ids to choose from and we cannot efficiently fill the dynamic array at initialization. Is there a better way to randomly choose an id to mint, or to keep track of what's been minted or not? Also we tried using a fixed size array which is cheaper with gas, but couldn't find a solution to effectively choose a random number within the range of 0 to numberOfTokensMinted
because we do not have the arrays length.