I am creating an NFT that on-chain generates random body parts which off-chain is being combined and made into images and such. I am doing it on-chain to keep it true to the purpose of NFTs, but also because I have another function where I can combine tokens and choose which parts to keep on a new one.

Anyways, this minting of NFTs costs way too much eth atm, I am benchmarking it by minting 5 at a time, which with this current setup costs about 0.26 eth with a gas price of 150, so it uses about 1 151 894 gas. This won't really work since that almost equals the cost I've been thinking of charging for one NFT. I was wondering if anyone might have a good idea of how I could optimize my code to make it cost less, or another method to do this entirely.

These are the relevant functions:

//Generate random large number
function randomNumber() private view returns(uint) {
    return uint(keccak256(abi.encodePacked(block.difficulty, block.timestamp, nonce)));

//Generate a random biased category
function generateRandomCategory() private returns(uint8) {
    uint randNumber = randomNumber();
    //Each rarity has their own chance of being picked, common has 20/36, uncommon has 10/36, rare 6/36 etc 
    //After choosing a rarity it will pick which category of that rarity by doing % the amount of categories 
    //of that rarity + the combined amount of all previous rarities, this will give the id of that category
    uint rarityChoice = randNumber % 32;
    if(rarityChoice <= 15) { return uint8(randNumber%2);     }   //Common has 2 categories, ids start at 0
    if(rarityChoice <= 28) { return uint8(randNumber%2)+2;   }   //Uncommon has 2 categories, ids start at 2
    return uint8(randNumber%2)+4;  //Rare has 2 categories, ids start at 4

event NewBot(uint16 indexed _id, uint8 level, uint8 head, uint8 body, uint8 l_arm, uint8 r_arm, uint8 l_leg, uint8 r_leg);

//Mint new bot
function mintBot(uint amount) public payable {
    require(amount > 0, "You must mint atleast one bot.");
    //require((totalSupply() + amount) < maxAmount, "Not enough inventory to fulfill your request.");
    //require(msg.value == (50000000000000000 * amount), "Wrong ether amount!");
    for(uint i = 0; i < amount; i++) {
        uint8 head = generateRandomCategory();
        uint8 body = generateRandomCategory();
        uint8 l_arm = generateRandomCategory();
        uint8 r_arm = generateRandomCategory();
        uint8 l_leg = generateRandomCategory();
        uint8 r_leg = generateRandomCategory();
        uint16 _id = uint16(mint(msg.sender));
        bitsMapping[_id] = [head, body, l_arm, r_arm, l_leg, r_leg, uint8(1)];
        emit NewBot(_id, uint8(1), head, body, l_arm, r_arm, l_leg, r_leg);

ALSO: I did some tests to find out what was actually using up the most gas when calling the mint function (all passing the number 5 to mint 5 bots).

  • Current code used: 1 151 894 gas
  • Commenting out all the generateRandomCategory() used: 1 016 806 gas
  • Commenting out generateRandomCategory() AND bitsMapping[_id] used: 633 817 gas

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.