1

I am creating a simple crypto trading card program on remix/solidity. Currently, I am storing each trading card as a uint256 in an array of length 99,999,999 indexes.

Each card has its own rarity, which is calculated using its uint256 ID. I want to make my program as gas-efficient as possible. When finding the rarity of a card, would it be cheaper to repeatedly calculate the cards' rarity like this:

uint[99999999] private cards;

// card id calculation etc. //

function findCardRarity(uint _randNum) internal returns (string memory) {

            uint cardRemainder = findCardRemainder(_randNum);
            
            if (cardRemainder < 10) {
                return "unique";
            } else if (10 <= cardRemainder < 10010) {
                return "legendary";
            } else if (10010 <= cardRemainder < 1010010) {
                return "rare";
            } else if (1010010 <= cardRemainder < 11010010) {
                return "uncommon";
            } else {
                return "common";
            }

or to store it once as an attribute of a struct like this:

struct Card{
    uint cardNumber;
    string rarity;
} 

Card[] public cards;

function assignRarity(_cardId) internal {
    uint cardRemainder = findCardRemainder(_randNum);
            
    if (cardRemainder < 10) {
        cards[_cardId].rarity = "unique";
    } else if (10 <= cardRemainder < 10010) {
        cards[_cardId].rarity = "legendary";
    } else if (10010 <= cardRemainder < 1010010) {
        cards[_cardId].rarity = "rare";
    } else if (1010010 <= cardRemainder < 11010010) {
        cards[_cardId].rarity = "uncommon";
    } else {
        cards[_cardId].rarity = "common";
        }
    }

// then create cards and assign rarity //

I ask this as I'm not sure if it's cheaper to store data on the blockchain as part of a struct or to execute calculations on the blockchain repeatedly, on each instance of a function call. This is my first smart contract.

bguiz
  • 27,371
  • 47
  • 154
  • 243
airza
  • 11
  • 2

2 Answers2

0

Generally speaking, storage is much more expensive than computational costs. So my gut feel answer is that your set of if-else statements would be more gas efficient than switching from using uint256[] to Card[] where each Card is a uint256 and a string.

Details:

But I'll end with a disclaimer:

It is super hard to work out what the actual EVM opcodes your solidity code will actually generate, so the best way top know for sure is to write both variants, compile, deploy, run tests, and measure the before and after balances to work out the aggregate gas costs.

Another thing worth considering is that you should consider smart contract deployment gas fees separately from smart contract function invocation gas fees. For deployment, the length of the bytecode generated is what matters. So in your example, the variant with many if-else statements is likely to generate more verbose bytecode, and therefore cost more gas to deploy. Whereas the variant with the structs is likely to cost less gas to deploy. Which is, in effect, the reverse of the function invocation gas costs.

bguiz
  • 27,371
  • 47
  • 154
  • 243
0

I think it should not be much of a concern because the data is not changing it's just calling, So there will be no gas fees at all on calling some variables in to your function.

  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jun 27 '23 at 22:39