Explorando Mappings en Solidity

En Solidity, los mappings son estructuras de datos esenciales que permiten almacenar pares clave-valor, similares a los hashmaps o mapas en otros lenguajes. Aunque son simples de usar, tienen características únicas y algunas restricciones que debemos entender. ¡Vamos a ello!
Introducción a los Mappings
Un mapping en Solidity asocia una clave de un tipo específico con un valor de otro tipo específico. Aquí un ejemplo básico:
contract Mappings01 {
mapping(uint256 => uint256) public myMapping;
function setMapping(uint256 key, uint256 value) public {
myMapping[key] = value;
}
function getValue(uint256 key) public view returns (uint256) {
return myMapping[key];
}
}
En este contrato:
setMappingalmacena un valor asociado con una clave.getValuerecupera el valor asociado con una clave.
Valor Predeterminado
Si accedes a un mapping con una clave que no ha sido definida, no obtendrás un error. En su lugar, el mapping retornará el valor predeterminado del tipo de datos del valor:
Para
uint256:0.Para
bool:false.Para
address:0x0000000000000000000000000000000000000000.
Ejemplo:
contract Mappings02 {
mapping(uint256 => bool) public mapToBool;
mapping(uint256 => uint256) public mapToUint;
mapping(uint256 => address) public mapToAddress;
function getDefaultValues(uint256 key) public view returns (bool, uint256, address) {
return (mapToBool[key], mapToUint[key], mapToAddress[key]);
}
}
Casos de Uso Comunes
Uso en Tokens ERC-20
Los tokens ERC-20 utilizan mappings para almacenar balances de usuarios. Por ejemplo:
contract ERC20Token {
mapping(address => uint256) public balances;
function setBalance(address owner, uint256 amount) public {
balances[owner] = amount;
}
function transfer(address sender, address receiver, uint256 amount) public {
balances[sender] -= amount;
balances[receiver] += amount;
}
}
En este caso:
balancesmapea una dirección a un saldo.La función
transfer()permite ajustar los saldos de los usuarios.
Nota: Esta implementación carece de restricciones de seguridad; cualquiera puede transferir tokens. Esto es solo un ejemplo simplificado.
Restricciones de los Mappings
1. Solo Pueden Declararse en Storage
Los mappings deben ser declarados como variables de estado (en storage). No puedes declararlos dentro de funciones o como parámetros:
contract BrokenContract {
function wontWork() public view {
mapping(uint256 => uint256) someMap; // Esto no compilará
}
}
2. No Pueden Ser Iterados
No hay manera de iterar sobre las claves de un mapping porque técnicamente todas las claves posibles son válidas y simplemente retornan el valor predeterminado si no han sido definidas.
Esto significa que si necesitas iterar sobre datos, deberías usar un array en combinación con el mapping.
3. No Pueden Ser Retornados
Los mappings no son un tipo de datos válido para ser retornado por funciones públicas o externas:
contract BrokenContract {
mapping(uint256 => uint256) public someMap;
function wontWork() public view returns (mapping(uint256 => uint256)) {
return someMap; // Esto no compilará
}
}
Buenas Prácticas con Mappings
Combínalos con Arrays: Si necesitas iterar sobre datos, guarda las claves en un array separado.
Define Acceso Público Cuidadosamente: Aunque puedes declarar un mapping como
public, ten cuidado al permitir acceso público para evitar exponer datos sensibles.Usa Valores Predeterminados con Precaución: Asegúrate de manejar correctamente los valores predeterminados para evitar errores lógicos.
Ejemplo Completo: Pop and Swap con Mappings y Arrays
contract ExampleWithMappingAndArray {
mapping(address => uint256) public balances;
address[] public users;
function addUser(address user, uint256 balance) public {
balances[user] = balance;
users.push(user);
}
function removeUser(address user) public {
uint256 index = findUserIndex(user);
balances[user] = 0;
users[index] = users[users.length - 1];
users.pop();
}
function findUserIndex(address user) internal view returns (uint256) {
for (uint256 i = 0; i < users.length; i++) {
if (users[i] == user) {
return i;
}
}
revert("User not found");
}
}
Este contrato:
Usa un array para almacenar las claves del mapping.
Permite iterar indirectamente sobre los usuarios.
Conclusión
Los mappings son herramientas poderosas para almacenar y acceder a datos en Solidity, especialmente cuando no necesitas iterar sobre ellos. Aunque tienen restricciones, su simplicidad y eficiencia los hacen esenciales para muchos casos de uso, incluidos los tokens ERC-20.
¡Prueba estos ejemplos en Remix para familiarizarte con sus conceptos y limitaciones! 🚀




