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