1

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.

binkie
  • 865
  • 6
  • 9

0 Answers0