¿Cómo funciona el storage en Yul?
Escrito por Mark Jonathas
Yul es un lenguaje de programación intermedio que se puede usar para escribir una forma de lenguaje ensamblador dentro de contratos inteligentes. Entender Yul puede llevar tus contratos inteligentes a otro nivel y ayudarte a ahorrar en costos de gas para el usuario. Para empezar a escribir contratos inteligentes con Yul, es importante entender cómo funciona el storage.
¿Cómo funciona el storage en Yul?
Antes de profundizar en cómo funciona Yul, necesitamos entender bien cómo funciona el storage en los contratos inteligentes. El storage está compuesto por una serie de slots. Hay 2²⁵⁶ slots para un contrato inteligente.
Al declarar variables, empezamos con el slot 0 y vamos incrementando desde ahí. Cada slot tiene una longitud de 256 bits (32 bytes), de ahí viene el nombre de uint256 y bytes32. Todas las variables se convierten a hexadecimal.
Si se usa una variable, como un uint128, no se ocupa un slot entero para almacenarla. En su lugar, se rellena con 0's del lado izquierdo. Veamos un ejemplo para entenderlo mejor.
var1: Dado que las variables uint256 equivalen a 32 bytes, var1 ocupa la totalidad del slot 0.
Esto es lo que se almacena en el slot 0:
0x0000000000000000000000000000000000000000000000000000000000000100
var2: Las direcciones son un poco más complejas. Como solo ocupan 20 bytes de storage, las direcciones se rellenan con 0's del lado izquierdo.
Esto es lo que se almacena en el slot 1:
0x0000000000000000000000009acc1d6aa9b846083e8a497a661853aae07f0f00.
var3: Este puede parecer simple, el slot 2 es consumido por completo por la variable bytes32.
var4 y var5: ¿Recuerdas cuando mencioné que los uint128 se rellenan con 0's? Bueno, si ordenamos nuestras variables de manera que la suma de su storage sea menor a 32 bytes, ¡podemos hacer que quepan juntas en un solo slot! Esto se llama empaquetado de variables (variable packing), y puede ahorrarte gas.
Veamos qué se almacena en el slot 3:
0x0000000000000000000000000000000200000000000000000000000000000001.
Nota que 0x000000000000000000000000000002 y 0x000000000000000000000000000001 encajan perfectamente juntas en el mismo slot. Esto se debe a que ambas ocupan 16 bytes (la mitad de un slot).
¡Veamos otro ejemplo!
x = 3. Esto tiene sentido ya que sabemos que var5 está empaquetada en el slot 3.
y = 16. Esto también debería tener sentido ya que sabemos que var4 ocupa la mitad del slot 3. Como las variables se empaquetan de derecha a izquierda, obtenemos el byte 16 como índice de inicio de var5.
z = 1. El sstore() asigna al slot 0 el valor 1. Luego, asignamos a z el valor del slot 0 con el sload().
Antes de continuar, deberías agregar esta función a tu archivo de Remix. Te ayudará a ver qué se almacena en cada slot de storage.
¡Ahora veamos algunas estructuras de datos más complejas!
Al trabajar con arrays estáticos, la EVM sabe cuántos slots asignar para nuestros datos. Con este array en particular, estamos empaquetando 2 elementos por slot.
Entonces, si llamas a getValInHex\(4\), devolverá 0x0000000000000000000000000000000100000000000000000000000000000000.
Como es de esperar, leyendo de derecha a izquierda, vemos el valor 0 y el valor 1.
El slot 5 contiene 0x0000000000000000000000000000000300000000000000000000000000000002.
A continuación, vamos a ver los arrays dinámicos.
Intenta llamar a getValInHex\(6\). Verás que devuelve 0x00. Como la EVM no sabe cuántos slots de storage se necesitan asignar, no podemos almacenar el array aquí.
En su lugar, se usa el hash keccak256 del slot de storage actual (slot 6) como índice de inicio del array. Desde ahí, todo lo que necesitamos hacer es sumar el índice del elemento deseado para obtener su valor.
Aquí hay un ejemplo de código que muestra cómo encontrar un elemento de un array dinámico:
Aquí obtenemos el slot del array, luego realizamos una operación add() junto con un sload() para obtener el valor del elemento del array que buscamos.
Quizás te preguntes qué evita que tengamos una colisión con el slot de otra variable.
Esto es totalmente posible, sin embargo, es extremadamente improbable ya que 2²⁵⁶ es un número muy grande.
Los mappings se comportan de forma similar a los arrays dinámicos, excepto que hacemos el hash del slot junto con la key.
Para esta demostración, establecí el valor del mapping var8[1] = 2. Ahora veamos un ejemplo de cómo obtener el valor de una key para un mapping.
Como puedes ver, el código se ve muy similar a cuando encontramos un elemento de un array dinámico. La diferencia principal es que hacemos el hash de la key y el slot juntos.
La última parte de esta sección sobre storage es aprender sobre los mappings anidados. Antes de seguir leyendo, te animo a escribir tu propia implementación de cómo leer el valor de un mapa anidado con base en lo que has aprendido hasta ahora.
Para este ejemplo, establecí el valor del mapping var9[0][1] = 2.
Aquí está el código, ¡vamos a verlo!
Esto es lo que está pasando:
- Primero obtenemos el hash de la primera key (0).
- Luego tomamos el hash de eso junto con la segunda key (1).
- Finalmente, cargamos el slot desde storage para obtener nuestro valor.
Felicidades, completaste la sección sobre storage con Yul!
Lee más sobre Yul Memory, Yul Contract Calls y Yul Packed Storage Variables.
Resúmenes relacionados
Solidity3 de diciembre de 2025
Los 6 mejores IDEs de Solidity para desarrolladores (2026)
Explora los mejores IDEs para el desarrollo en Solidity.
Solidity19 de noviembre de 2025
Optimización de gas en Solidity: 12 técnicas para hacer tus smart contracts más económicos y eficientes
¿Quieres escribir mejor código y reducir tus fees de gas?
Solidity13 de noviembre de 2025
12 mejores prácticas de seguridad para smart contracts en Solidity
Protege tus smart contracts con estos consejos y herramientas de seguridad de expertos.

Construye magia blockchain
Alchemy combina los productos y herramientas de desarrollo Web3 más potentes con recursos, comunidad y un soporte legendario.