Volver a la página principal
lunes 9 diciembre 2024
4

Cómo usar mappings en Solidity para almacenar pares clave-valor de manera eficiente

Un mapping es una estructura de datos que actúa como una tabla de hash. Permite asociar una clave con un valor y, a diferencia de otras estructuras como arrays, las claves no se recorren ni se enumeran. Esto hace que los mappings sean ideales para casos en los que se requiere un acceso rápido a datos pero no una iteración sobre ellos.

Características principales:

  • Eficiencia: Ofrecen acceso constante (O(1)) a los valores asociados con las claves.
  • No iterables: No se pueden recorrer directamente; las claves deben conocerse de antemano para acceder a los valores.
  • Inicialización predeterminada: Todas las claves están asociadas inicialmente con el valor predeterminado de su tipo (e.g., 0 para enteros, false para booleanos).

Sintaxis básica de mappings

mapping(tipoClave => tipoValor) public nombreMapping;
  • tipoClave: Tipo de dato usado como clave (comúnmente address o uint).
  • tipoValor: Tipo de dato asociado a la clave (puede ser un valor simple, una estructura o incluso otro mapping).

Ejemplo básico

pragma solidity ^0.8.0;

contract EjemploMapping {
    // Mapping de direcciones a enteros
    mapping(address => uint) public balances;

    // Asignar un valor a una clave
    function setBalance(uint _balance) public {
        balances[msg.sender] = _balance;
    }

    // Consultar el balance de una dirección
    function getBalance(address _address) public view returns (uint) {
        return balances[_address];
    }
}

Ejemplos prácticos de mappings

1. Registro de saldos

Un ejemplo clásico es almacenar los saldos de usuarios.

contract RegistroSaldos {
    mapping(address => uint) public balances;

    // Depositar saldo
    function depositar() public payable {
        balances[msg.sender] += msg.value;
    }

    // Consultar saldo
    function consultarSaldo(address _usuario) public view returns (uint) {
        return balances[_usuario];
    }

    // Retirar saldo
    function retirar(uint _cantidad) public {
        require(balances[msg.sender] >= _cantidad, "Saldo insuficiente");
        balances[msg.sender] -= _cantidad;
        payable(msg.sender).transfer(_cantidad);
    }
}

2. Control de permisos

Puedes usar mappings para administrar roles o permisos.

contract Permisos {
    mapping(address => bool) public esAdministrador;

    // Asignar permisos de administrador
    function asignarAdmin(address _usuario) public {
        esAdministrador[_usuario] = true;
    }

    // Revocar permisos de administrador
    function revocarAdmin(address _usuario) public {
        esAdministrador[_usuario] = false;
    }

    // Verificar si un usuario es administrador
    function verificarAdmin(address _usuario) public view returns (bool) {
        return esAdministrador[_usuario];
    }
}

3. Nested mappings (Mappings anidados)

Puedes anidar mappings para gestionar relaciones complejas.

contract NestedMapping {
    mapping(address => mapping(uint => bool)) public permisos;

    // Asignar permiso a un usuario para un recurso específico
    function asignarPermiso(address _usuario, uint _recurso) public {
        permisos[_usuario][_recurso] = true;
    }

    // Verificar si un usuario tiene permiso para un recurso
    function verificarPermiso(address _usuario, uint _recurso) public view returns (bool) {
        return permisos[_usuario][_recurso];
    }
}

Ventajas de usar mappings

1. Eficiencia: Ofrecen acceso rápido a los valores asociados con una clave.

2. Flexibilidad: Soportan claves y valores de tipos variados.

3. Inicialización automática: Todas las claves tienen un valor predeterminado sin necesidad de inicializarlas explícitamente.

Limitaciones de los mappings

1. No iterables: No puedes recorrer las claves ni obtener una lista de las claves almacenadas.

2. Uso limitado en interfaces externas: Los mappings no pueden ser devueltos directamente como respuesta de una función pública.

3. Alto costo en gas al iterar: Si necesitas recorrer datos, deberás gestionarlos fuera del mapping o usar estructuras adicionales como arrays.

Consideraciones importantes

  • Usa mappings únicamente cuando no sea necesario recorrer las claves.
  • Si necesitas iterar, combina mappings con arrays que actúen como índices.
  • Protege los mappings sensibles con modificadores como private o acceso controlado.

Referencias oficiales

Para más detalles sobre los mappings en Solidity, consulta la documentación oficial de Solidity.

Etiquetas:
solidity
Compartir:
Creado por:
Author photo

Jorge García

Fullstack developer