3

I have a map of game IDs to game structs in my Solidity contract. I want to test if a game struct for a given ID does not exist or has been deleted. I am using the code below:

// The map that maps a game ID to a specific game.
mapping(uint256 => structGame) public s_mapGameIdToGame;

/// Make sure the game ID has been explicitly set and does not belong to a deleted game.
/// @param _gameId - a valid game ID.
modifier onlyIfValidGameId(uint256 _gameId) {
    // Make sure the game ID has been explicitly set.
    require(_gameId != id_invalid, "The game ID  is invalid.");
    // Make sure the game has not been deleted.
    require(s_mapGameIdToGame[_gameId] != 0, "The ID given belongs to a deleted game.");
    _;
}

Unfortunately Solidity is giving me the following error for the existence check on the game struct:

./contracts/GameFactory.sol:178:17: TypeError: Operator == not 
compatible with types struct EtherBandBattlesManager.structGame 
storage ref and int_const 0
    require(s_mapGameIdToGame[_gameId] == 0, "The ID given belongs to 
a deleted game.");
            ^-----------------------------^

How can I make my existence check/test work?

1 Answer 1

2

In Solidity default value is always zero or false. Value of uninitialized uint is zero, bool will be false and if you refer to struct it simply behave like all its values are zero or false. So you have to check if any parameter of your struct is zero.

modifier gameExist(uint id)
{
    require (mapGame[id].active);
    _;
}

You can check this example in Remix. GetGame will always return value even before you add structGame to the mapping or after you delete game. GetGameVerified will only return value if structGame was added (exist) to mapping.

pragma solidity ^0.4.19;


contract Test{

struct structGame
{
    uint256 value;
    string name;
    bool active;
}

mapping(uint256=>structGame) public mapGame;

function AddGame(uint id,uint value,string name){
    structGame memory game = structGame(value,name,true);
    mapGame[id] = game;
}

function GetGame(uint id) view returns (uint value,string name, bool active)
{
    return (mapGame[id].value,mapGame[id].name,mapGame[id].active);
}

function deleteGame(uint id){
    delete mapGame[id];
}

modifier gameExist(uint id)
{
    require (mapGame[id].active);
    _;
}

function GetGameVerified(uint id) view gameExist(id) returns (uint value,string name, bool active)
{
     return (mapGame[id].value,mapGame[id].name,mapGame[id].active);
}


}
2
  • 1
    So unlike other languages Solidity doesn't throw some "bad reference" error because you are accessing an offset that into some "bad" part of memory because you are accessing a non-existent or deleted element? In my mind that means Solidity must return an "empty" struct when you access a non-existent or deleted element, instead of complaining about something akin to an "access violation", which feels kind of weird to me. Commented Jul 3, 2018 at 16:35
  • 1
    You can get an error when you use array and you try to access index which wasn't added or you if delete the whole array. But if you add something to first index of array and then you delete it then behavior will be similar. I think about mapping a bit like I think about pointers in C. It is pointing to some location in memory and there is always something there. In case of Solidity it empty (zero) by default.
    – Rob Magier
    Commented Jul 3, 2018 at 21:45

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.