¿Probar si un elemento del mapa ha sido eliminado o no existe?

Tengo un mapa de ID de juegos para estructuras de juegos en mi contrato de Solidity. Quiero probar si una estructura de juego para una ID determinada no existe o se ha eliminado. Estoy usando el siguiente código:

// 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.");
    _;
}

Desafortunadamente, Solidity me está dando el siguiente error para verificar la existencia en la estructura del juego:

./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.");
            ^-----------------------------^

¿Cómo puedo hacer que mi verificación/prueba de existencia funcione?

Respuestas (1)

En Solidity el valor predeterminado es siempre cero o falso. El valor de uint no inicializado es cero, bool será falso y si hace referencia a la estructura, simplemente se comportará como si todos sus valores fueran cero o falsos. Por lo tanto, debe verificar si algún parámetro de su estructura es cero.

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

Puedes consultar este ejemplo en Remix. GetGame siempre devolverá valor incluso antes de agregar structGame al mapeo o después de eliminar el juego. GetGameVerified solo devolverá valor si structGame se agregó (existe) al mapeo.

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);
}


}
Entonces, a diferencia de otros idiomas, Solidity no arroja un error de "referencia incorrecta" porque está accediendo a un desplazamiento que se encuentra en una parte "mala" de la memoria porque está accediendo a un elemento inexistente o eliminado. En mi opinión, eso significa que Solidity debe devolver una estructura "vacía" cuando accede a un elemento inexistente o eliminado, en lugar de quejarse de algo similar a una "violación de acceso", lo que me parece un poco extraño.
Puede obtener un error cuando usa una matriz e intenta acceder al índice que no se agregó o si elimina toda la matriz. Pero si agrega algo al primer índice de la matriz y luego lo elimina, el comportamiento será similar. Pienso en el mapeo un poco como pienso en los punteros en C. Está apuntando a alguna ubicación en la memoria y siempre hay algo allí. En el caso de Solidity está vacío (cero) por defecto.