0

I'm quite new to Solidity and want to fill an array with 240 structs.

I have a struct:

    struct Country {
      string name;
      uint level;
      uint attackPower;
      uint defensePower;
      uint price;
   }

And an array:

    Country[] public countries;

I want to fill the array with Countries on deployment but when I try to do that as such my gas runs out and the contract can't even be deployed (even when not calling the function). What is the correct way of achieving my goal?

function createCountries() public{
    countries[0] = Country("AW",1, 100, 100, 1);
    countries[1] = Country("AF",1, 100, 100, 1);
    countries[2] = Country("AO",1, 100, 100, 1);
    countries[3] = Country("AI",1, 100, 100, 1);
    countries[4] = Country("AL",1, 100, 100, 1);
    countries[5] = Country("AX",1, 100, 100, 1);
    countries[6] = Country("AD",1, 100, 100, 1);
    countries[7] = Country("AE",1, 100, 100, 1);
    countries[8] = Country("AR",1, 100, 100, 1);
    countries[9] = Country("AM",1, 100, 100, 1);
    countries[10] = Country("AS",1, 100, 100, 1);
    countries[11] = Country("AQ",1, 100, 100, 1);
    countries[13] = Country("TF",1, 100, 100, 1);
    countries[14] = Country("AG",1, 100, 100, 1);
    countries[15] = Country("AU",1, 100, 100, 1);
    countries[16] = Country("AT",1, 100, 100, 1);
    countries[17] = Country("AZ",1, 100, 100, 1);
    countries[18] = Country("BI",1, 100, 100, 1);
    countries[19] = Country("BE",1, 100, 100, 1);
    countries[20] = Country("BJ",1, 100, 100, 1);
    countries[21] = Country("BF",1, 100, 100, 1);
    countries[22] = Country("BD",1, 100, 100, 1);
    countries[23] = Country("BG",1, 100, 100, 1);
    countries[24] = Country("BH",1, 100, 100, 1);
    countries[25] = Country("BS",1, 100, 100, 1);
    countries[26] = Country("BA",1, 100, 100, 1);
    countries[27] = Country("BL",1, 100, 100, 1);
    countries[28] = Country("BY",1, 100, 100, 1);
    countries[29] = Country("BZ",1, 100, 100, 1);
    countries[30] = Country("BM",1, 100, 100, 1);
    ... 210 more of these...
}

1 Answer 1

1

You should do it in batches, and make use of the fact that every instantiation of a Country is almost the same.

I created this contract as an example:

pragma solidity 0.4.23;

contract CountryStore {
    bool public finishedCreating = false;

    mapping(bytes2 => Country) public createCountries;

    struct Country {
      string name;
      uint level;
      uint attackPower;
      uint defensePower;
      uint price;
      bool created;
    }

    Country[] public countries;

    function createCountries(string names) public onlyWhileCreating {
       for(uint256 i = 0; i < bytes(names).length; i+=2){
           // Get the next two characters and store them in `name`
           bytes memory name = new bytes(2);
           name[0] = bytes(names)[i];
           name[1] = bytes(names)[i+1];

           if(!createCountries(bytes2(name)).created)
               countries.push(Country({
                   name: string(name),
                   level: 1,
                   attackPower: 100,
                   defensePower: 100,
                   price: 1,
                   created: true
               }));
       }
    }

    function finishCreating() public {
        finishedCreating = true;
    }

    modifier onlyWhileCreating(){
       require(!finishedCreating, "This method can only be called when creating countries");
       _;
    }
}

It keeps track of every country created, so you avoid duplicates. Also, when you're done, you can call setFinished to disable createCountries.

Now, when you fill the countries array, call createCountries with the countrycodes concatenated. In Web3.js:

await countryStore.createCountries("AWAFAOAIALAXADAEAR") ....
2
  • This is an answer for this situation! But i would want my other Struct attributes to be variable as well this wouldnt work anymore right?
    – jasper
    May 11, 2018 at 14:34
  • That's true, it won't work for every situation. Still, the gist of it is that you should instantiate countries in batches, not all at once.
    – Henk
    May 11, 2018 at 14:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.