I'm working on a Game into Solidity and I want to be able to populate metadata into my smart contract to be able to access them directly from game-play functions.
So I have a basic ERC721 to start:
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract GameEngine is ERC721Enumerable, Ownable {
string baseURI;
uint256 public maxSupply = 10000;
bool isPopulated = false;
struct Character {
uint8 race;
uint8 strength;
uint8 agility;
uint8 hp;
uint8 xp;
/*..*/
}
mapping(uint => Character) characters;
constructor(
string memory _initBaseURI
) ERC721("GameCharacters", "GC") {
_baseURI = _initBaseURI;
}
/* All basic functions for ERC721: mint, tokenURI, ...*/
}
Now... I want to be able to pre-fill all Character struct in the characters
mapping.
I can implement 2 ways:
A function to add a single one
Problem: But I'll have to call it 10.000 times (or more) !! And it'll cost way to much in fees..
function populateOne(uint8 race, uint8 strength, uint8 agility, uint8 hp, /*...*/ ) external onlyOwner {
require(!isPopulated, "Already Populated");
characters[characters.length] = Character(race, strength, agility, hp, 0, /*...*/ );
}
function setPopulated() external onlyOwner {
isPopulated = true;
}
All in one function
Problem: Not sure I'll be able to call this function with 10,20 or 50 arrays of 10k, 20k or 100k items..
// All array must be the same size (maxSupply)
function populateAll(uint8[] races, uint8[] strengths, uint8[] agilities, uint8[] hps, /*...*/ ) external onlyOwner {
require(!isPopulated, "Already Populated");
for (uint256 i = 0; i < type.length; i++) {
characters[i] = Character(races[i], strengths[i], agilities[i], hps[i], 0, /*...*/ );
}
isPopulated = true;
}
Did I miss something ? What's the solution to do it ? Thank for help, articles, codes, .. I'm taking everything :p