---
title: "¿Cómo funciona la memoria en Yul?"
description: "Aprende cómo funciona la memoria en el lenguaje de programación de smart contracts Yul"
---

# ¿Cómo funciona la memoria en Yul?

[Yul](http://www.alchemy.com/overviews/what-is-yul) es un lenguaje de programación intermedio que se puede usar para escribir una forma de lenguaje ensamblador dentro de [smart contracts](https://www.alchemy.com/overviews/solidity-smart-contract). Una vez que hayas aprendido sobre el storage de Yul y cómo leer y escribir variables de storage empaquetadas, es importante aprender cómo funciona la memoria en los smart contracts de Yul.

## **¿Cómo funciona la memoria en yul?**

La memoria se comporta de manera distinta al [storage](http://www.alchemy.com/overviews/yul-storage). La memoria no es persistente, lo que significa que una vez que la función termina de ejecutarse, todas las variables se borran.

La memoria es comparable al heap en otros lenguajes, pero no hay un garbage collector.

La memoria es mucho más barata que el storage. El costo de las primeras 22 palabras de memoria se calcula de forma lineal, pero ten cuidado porque después de eso el costo de la memoria se vuelve cuadrático.

La memoria se organiza en secuencias de 32 bytes. Vamos a entender esto mejor más adelante, pero por ahora ten en cuenta que 0x00 - 0x20 es una secuencia (puedes pensarlo como un slot si te ayuda, pero son cosas diferentes).

[Solidity](https://www.alchemy.com/overviews/solidity) asigna 0x00 - 0x40 como scratch space. No hay garantía de que esta área de memoria esté vacía, y se usa para ciertas operaciones.

0x40 - 0x60 almacena la ubicación de lo que se conoce como el free memory pointer, que se usa para escribir algo nuevo en memoria.

0x60 - 0x80 se deja vacío como un espacio en blanco.

0x80 es donde empezamos nuestras operaciones.

La memoria no empaqueta valores. Los valores obtenidos del storage se almacenan en su propia secuencia de 32 bytes (es decir, 0x80-0xa0).

### **¿Qué operaciones usan memoria en yul?**

La memoria se usa para las siguientes operaciones:

- Valores de retorno de llamadas externas
- Establecer valores de función para llamadas externas
- Obtener valores de llamadas externas
- Revertir con un mensaje de error
- Registrar mensajes (log)
- Hashear con keccak256()
- Crear otros smart contracts

**Aquí hay algunas instrucciones de Yul útiles para la memoria:**

<EmbeddedTable
  table={{
    columns: [
      { key: "1", width: 200, title: "Instruction", dataType: "object" },
      { key: "2", width: 200, title: "Explanation", dataType: "object" },
    ],
    data: [
      {
        "1": { title: "<p>mload(p)</p>", tooltip: "", icon: "" },
        "2": { title: "<p>Similar a sload(), pero aquí decimos que cargue los siguientes 32 bytes después de p</p>", tooltip: "", icon: "" },
        id: 0,
      },
      {
        "1": { title: "<p>mstore(p, v)</p>", tooltip: "", icon: "" },
        "2": { title: "<p>Similar a sstore(), pero aquí decimos que almacene el valor v en p más 32 bytes</p>", tooltip: "", icon: "" },
        id: 1,
      },
      {
        "1": { title: "<p>mstore8(p, v)</p>", tooltip: "", icon: "" },
        "2": { title: "<p>Similar a mstore(), pero solo para un único byte</p>", tooltip: "", icon: "" },
        id: 2,
      },
      {
        "1": { title: "<p>msize()</p>", tooltip: "", icon: "" },
        "2": { title: "<p>Devuelve el índice de memoria más grande accedido</p>", tooltip: "", icon: "" },
        id: 3,
      },
      {
        "1": { title: "<p>pop(x)</p>", tooltip: "", icon: "" },
        "2": { title: "<p>Descarta el valor x</p>", tooltip: "", icon: "" },
        id: 4,
      },
      {
        "1": { title: "<p>return(p, s)</p>", tooltip: "", icon: "" },
        "2": { title: "<p>Finaliza la ejecución y devuelve los datos de las ubicaciones de memoria p - v</p>", tooltip: "", icon: "" },
        id: 5,
      },
      {
        "1": { title: "<p>revert(p, s)</p>", tooltip: "", icon: "" },
        "2": { title: "<p>Finaliza la ejecución sin guardar los cambios de estado, y devuelve los datos de las ubicaciones de memoria p - v</p>", tooltip: "", icon: "" },
        id: 6,
      },
    ],
  }}
/>

¡Veamos algunas estructuras de datos más!

### **Cómo usar structs y memoria en yul**

Los structs y los arrays de tamaño fijo en realidad se comportan igual, pero como ya vimos los arrays de tamaño fijo en la sección de storage, ahora veremos los structs. Observa el siguiente struct.

No hay nada inusual aquí, solo un struct simple.

Ahora veamos algo de código.

Aquí estamos estableciendo s.subVar1 en la ubicación de memoria 0x80 - 0xa0 y s.subVar2 en la ubicación de memoria 0xa0 - 0xc0. Por eso estamos devolviendo 0x80 - 0xc0. Aquí hay una tabla del layout de memoria justo antes del final de la transacción.

<EmbeddedTable
  table={{
    columns: [
      { key: "1", width: 200, title: "Memory Location", dataType: "object" },
      { key: "2", width: 200, title: "Value Stored", dataType: "object" },
    ],
    data: [
      {
        "1": { title: "<p>0x00</p>", tooltip: "", icon: "" },
        "2": { title: "<p>Scratch Space (Empty)</p>", tooltip: "", icon: "" },
        id: 0,
      },
      {
        "1": { title: "<p>0x20</p>", tooltip: "", icon: "" },
        "2": { title: "<p>Scratch Space (Empty)</p>", tooltip: "", icon: "" },
        id: 1,
      },
      {
        "1": { title: "<p>0x40</p>", tooltip: "", icon: "" },
        "2": { title: "<p>0xc0 (Free Memory Pointer)</p>", tooltip: "", icon: "" },
        id: 2,
      },
      {
        "1": { title: "<p>0x60</p>", tooltip: "", icon: "" },
        "2": { title: "<p>Empty</p>", tooltip: "", icon: "" },
        id: 3,
      },
      {
        "1": { title: "<p>0x80</p>", tooltip: "", icon: "" },
        "2": { title: "<p>s.subVar1: 0x20 (32 en decimal)</p>", tooltip: "", icon: "" },
        id: 4,
      },
      {
        "1": { title: "<p>0xa0</p>", tooltip: "", icon: "" },
        "2": { title: "<p>s.subVar1: 0x40 (64 en decimal)</p>", tooltip: "", icon: "" },
        id: 5,
      },
      {
        "1": { title: "<p>0xc0</p>", tooltip: "", icon: "" },
        "2": { title: "<p>Nuevo Free Memory Pointer. Esto es lo que devolvería msize(). (Empty)</p>", tooltip: "", icon: "" },
        id: 6,
      },
    ],
  }}
/>

**Cosas a tener en cuenta:**

- 0x00 - 0x40 está vacío para el scratch space
- 0x40 nos da el free memory pointer
- Solidity deja un espacio vacío en 0x60
- 0x80 y 0xa0 se usan para almacenar los valores del struct
- 0xc0 es el nuevo free memory pointer

En esta última parte de la sección de memoria quiero mostrarte cómo funcionan los arrays dinámicos en memoria. Vamos a pasar \[0, 1, 2, 3\] como el parámetro arr en este ejemplo. Como bonus adicional para este ejemplo, vamos a agregar un elemento extra al array. Ten cuidado al hacer esto en producción, ya que podrías sobrescribir otra variable de memoria.

**Aquí está el código:**

**Esto es lo que está pasando:**

- Obtener dónde está almacenado el array en memoria
- Obtener la longitud del array, que se almacena en la primera ubicación de memoria del array
- Sumar 32 bytes a la ubicación (saltando la longitud del array) para ver la siguiente ubicación disponible
- Multiplicar la longitud del array por 32 bytes para avanzar a la siguiente ubicación de memoria
- Almacenar nuestro nuevo valor (4)
- Actualizar la longitud del array en uno
- Actualizar el free memory pointer
- Devolver el array

Veamos de nuevo el layout de memoria.

<EmbeddedTable
  table={{
    columns: [
      { key: "1", width: 200, title: "Memory Location", dataType: "object" },
      { key: "2", width: 200, title: "Value Stored", dataType: "object" },
    ],
    data: [
      {
        "1": { title: "<p>0x00</p>", tooltip: "", icon: "" },
        "2": { title: "<p>Scratch Space (Empty)</p>", tooltip: "", icon: "" },
        id: 0,
      },
      {
        "1": { title: "<p>0x20</p>", tooltip: "", icon: "" },
        "2": { title: "<p>Scratch Space (Empty)</p>", tooltip: "", icon: "" },
        id: 1,
      },
      {
        "1": { title: "<p>0x40</p>", tooltip: "", icon: "" },
        "2": { title: "<p>0x140 (Free Memory Pointer)</p>", tooltip: "", icon: "" },
        id: 2,
      },
      {
        "1": { title: "<p>0x60</p>", tooltip: "", icon: "" },
        "2": { title: "<p>Empty</p>", tooltip: "", icon: "" },
        id: 3,
      },
      {
        "1": { title: "<p>0x80</p>", tooltip: "", icon: "" },
        "2": { title: "<p>Nueva longitud del array (6)</p>", tooltip: "", icon: "" },
        id: 4,
      },
      {
        "1": { title: "<p>0xa0</p>", tooltip: "", icon: "" },
        "2": { title: "<p>arr[0] (0)</p>", tooltip: "", icon: "" },
        id: 5,
      },
      {
        "1": { title: "<p>0xc0</p>", tooltip: "", icon: "" },
        "2": { title: "<p>arr[1] (1)</p>", tooltip: "", icon: "" },
        id: 6,
      },
      {
        "1": { title: "<p>0xe0</p>", tooltip: "", icon: "" },
        "2": { title: "<p>arr[2] (2)</p>", tooltip: "", icon: "" },
        id: 7,
      },
      {
        "1": { title: "<p>0x100</p>", tooltip: "", icon: "" },
        "2": { title: "<p>arr[3] (3)</p>", tooltip: "", icon: "" },
        id: 8,
      },
      {
        "1": { title: "<p>0x120</p>", tooltip: "", icon: "" },
        "2": { title: "<p>arr[4] (4)</p>", tooltip: "", icon: "" },
        id: 9,
      },
      {
        "1": { title: "<p>0x140</p>", tooltip: "", icon: "" },
        "2": { title: "<p>Free Memory Pointer (Empty)</p>", tooltip: "", icon: "" },
        id: 10,
      },
    ],
  }}
/>

¡Con esto concluye la sección sobre memoria!

A continuación, aprende [cómo llamar smart contracts usando Yul](http://www.alchemy.com/overviews/yul-contract-calls) o vuelve a aprender cómo [leer y escribir variables de storage empaquetadas](http://www.alchemy.com/overviews/yul-packed-storage-variables).
