storage persisten en la blockchain.
storage son costosas debido al almacenamiento permanente.
memory existen solo mientras se ejecuta la función y se eliminan después.
storage.
La ubicación de los datos debe especificarse explícitamente para los tipos complejos como arrays y structs cuando se utilizan en funciones.
function miFuncion(uint[] memory array) public {
// Lógica de la función
}
storage
storage se utiliza para manipular variables de estado del contrato.
contract EjemploStorage {
uint[] public numeros;
function agregarNumero(uint _numero) public {
numeros.push(_numero);
}
function actualizarNumero(uint indice, uint nuevoValor) public {
uint[] storage referencia = numeros; // Referencia directa a storage
referencia[indice] = nuevoValor;
}
}
En este ejemplo:
numeros es una variable de estado almacenada en storage.
referencia apunta directamente a numeros y modifica su contenido en la blockchain.
memory
memory es útil para manejar datos temporales y evitar modificar variables de estado.
contract EjemploMemory {
function duplicarArray(uint[] memory array) public pure returns (uint[] memory) {
uint[] memory nuevoArray = new uint[](array.length);
for (uint i = 0; i < array.length; i++) {
nuevoArray[i] = array[i] * 2;
}
return nuevoArray;
}
}
En este caso:
array es un parámetro temporal en memory.
nuevoArray se crea en memory y se devuelve sin afectar el estado del contrato.
calldata
calldata es ideal para datos de solo lectura en funciones públicas y externas.
contract EjemploCalldata {
function concatenarStrings(string calldata a, string calldata b) public pure returns (string memory) {
return string(abi.encodePacked(a, b));
}
}
En este ejemplo:
a y b son parámetros de solo lectura almacenados en calldata.
a o b.
storage, memory y calldata
| Atributo |
storage
|
memory
|
calldata
|
|---|---|---|---|
| Ubicación | Blockchain (permanente) | Memoria temporal (RAM del EVM) | Datos de entrada de solo lectura |
| Costo | Alto (operaciones en blockchain) |
Medio (temporal, más barato que storage)
|
Bajo (eficiente en gas) |
| Mutabilidad | Sí | Sí | No |
| Duración | Persiste entre transacciones | Solo durante la ejecución | Solo durante la ejecución |
storage para:
uint[] public listaPersistente; // Se almacena en storage
memory para:
function procesarTemporalmente(uint[] memory datos) public pure {}
calldata para:
function procesarDatos(string calldata datos) public {}
contract ManejoUbicaciones {
uint[] public lista;
// Agregar elementos a la lista
function agregar(uint valor) public {
lista.push(valor);
}
// Multiplicar valores de la lista sin modificarla
function multiplicar(uint multiplicador) public view returns (uint[] memory) {
uint[] memory copiaLista = lista; // Copia en memoria
for (uint i = 0; i < copiaLista.length; i++) {
copiaLista[i] *= multiplicador;
}
return copiaLista;
}
// Actualizar elementos directamente
function actualizar(uint indice, uint valor) public {
uint[] storage referencia = lista; // Referencia en storage
referencia[indice] = valor;
}
}
1. Especificar la ubicación explícitamente:
2. Optimización de gas:
calldata para parámetros de solo lectura en funciones externas.
storage para reducir costos.
3. Evita copiar grandes estructuras:
storage a memory puede ser costoso en términos de gas.
storage para datos persistentes que requieran modificaciones entre transacciones.
memory para operaciones temporales que no necesiten persistir.
calldata para manejar parámetros de entrada que no necesiten ser modificados.
Para más información sobre storage, memory y calldata, consulta la documentación oficial de Solidity.
Jorge García
Fullstack developer