---
title: "Como a memória funciona em Yul?"
description: "Aprenda como a memória funciona na linguagem de programação de smart contracts Yul"
---

# Como a memória funciona em Yul?

[Yul](http://www.alchemy.com/overviews/what-is-yul) é uma linguagem de programação intermediária que pode ser usada para escrever uma forma de linguagem assembly dentro de [contratos inteligentes](https://www.alchemy.com/overviews/solidity-smart-contract). Depois de aprender sobre o storage do Yul e como ler e escrever variáveis de storage compactadas (packed), é importante aprender como a memória funciona em smart contracts com Yul.

## **Como a memória funciona em yul?**

A memória se comporta de forma diferente do [storage](http://www.alchemy.com/overviews/yul-storage). A memória não é persistente, o que significa que, assim que a função termina de executar, todas as variáveis são limpas.

A memória é comparável ao heap em outras linguagens, mas não há garbage collector.

A memória é bem mais barata que o storage. O custo das primeiras 22 words de memória é calculado de forma linear, mas cuidado, pois depois disso o custo de memória se torna quadrático.

A memória é organizada em sequências de 32 bytes. Vamos entender melhor isso mais adiante, mas por enquanto entenda que 0x00 - 0x20 é uma sequência (pode pensar nisso como um slot, se ajudar, mas são coisas diferentes).

O [Solidity](https://www.alchemy.com/overviews/solidity) reserva 0x00 - 0x40 como scratch space. Não há garantia de que essa área de memória esteja vazia, e ela é usada em certas operações.

0x40 - 0x60 armazena a localização do chamado free memory pointer, usado para escrever algo novo na memória.

0x60 - 0x80 é deixado vazio como um espaço (gap).

0x80 é onde começamos nossas operações.

A memória não compacta valores. Valores recuperados do storage são armazenados em sua própria sequência de 32 bytes (ex: 0x80-0xa0).

### **Quais operações usam memória em yul?**

A memória é usada nas seguintes operações:

- Valores de retorno para chamadas externas
- Definir valores de função para chamadas externas
- Obter valores de chamadas externas
- Reverter com uma mensagem de erro
- Registrar mensagens (log)
- Fazer hash com keccak256\(\)
- Criar outros smart contracts

**Aqui estão algumas instruções úteis de Yul para memória:**

<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 to sload(), but we are saying load the next 32 bytes after p</p>", tooltip: "", icon: "" },
        id: 0,
      },
      {
        "1": { title: "<p>mstore(p, v)</p>", tooltip: "", icon: "" },
        "2": { title: "<p>Similar to sstore(), but we are saying store value v in p plus 32 bytes</p>", tooltip: "", icon: "" },
        id: 1,
      },
      {
        "1": { title: "<p>mstore8(p, v)</p>", tooltip: "", icon: "" },
        "2": { title: "<p>Similar to mstore(), but only for a single byte</p>", tooltip: "", icon: "" },
        id: 2,
      },
      {
        "1": { title: "<p>msize()</p>", tooltip: "", icon: "" },
        "2": { title: "<p>Returns the largest accessed memory index</p>", tooltip: "", icon: "" },
        id: 3,
      },
      {
        "1": { title: "<p>pop(x)</p>", tooltip: "", icon: "" },
        "2": { title: "<p>Discard value x</p>", tooltip: "", icon: "" },
        id: 4,
      },
      {
        "1": { title: "<p>return(p, s)</p>", tooltip: "", icon: "" },
        "2": { title: "<p>End execution, and return data from memory locations p - v</p>", tooltip: "", icon: "" },
        id: 5,
      },
      {
        "1": { title: "<p>revert(p, s)</p>", tooltip: "", icon: "" },
        "2": { title: "<p>End execution without saving state changes, and return data from memory locations p - v</p>", tooltip: "", icon: "" },
        id: 6,
      },
    ],
  }}
/>

Vamos ver mais algumas data structures!

### **Como usar structs e memória em yul**

Structs e arrays fixos se comportam da mesma forma, mas como já vimos arrays fixos na seção de storage, vamos ver structs aqui. Observe a seguinte struct.

Nada de incomum aqui, apenas uma struct simples.

Agora vamos ver algum código!

Aqui estamos definindo s.subVar1 na localização de memória 0x80 - 0xa0 e s.subVar2 na localização de memória 0xa0 - 0xc0. É por isso que estamos retornando 0x80 - 0xc0. Aqui está uma tabela do layout de memória logo antes do fim da transação.

<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 in decimal)</p>", tooltip: "", icon: "" },
        id: 4,
      },
      {
        "1": { title: "<p>0xa0</p>", tooltip: "", icon: "" },
        "2": { title: "<p>s.subVar1: 0x40 (64 in decimal)</p>", tooltip: "", icon: "" },
        id: 5,
      },
      {
        "1": { title: "<p>0xc0</p>", tooltip: "", icon: "" },
        "2": { title: "<p>New Free Memory Pointer. This is what msize() would return. (Empty)</p>", tooltip: "", icon: "" },
        id: 6,
      },
    ],
  }}
/>

**O que aprender com isso:**

- 0x00 - 0x40 fica vazio para scratch space
- 0x40 nos dá o free memory pointer
- O Solidity deixa um gap para 0x60
- 0x80 e 0xa0 são usados para armazenar os valores da struct
- 0xc0 é o novo free memory pointer

Nesta última parte da seção de memória, quero mostrar como arrays dinâmicos funcionam em memória. Vamos passar \[0, 1, 2, 3\] como o parâmetro arr para este exemplo. Como um bônus extra para este exemplo, vamos adicionar um elemento a mais ao array. Tenha cuidado ao fazer isso em produção, pois você pode sobrescrever uma variável de memória diferente.

**Aqui está o código:**

**Aqui está o que está acontecendo:**

- Obter onde o array está armazenado na memória
- Obter o length do array, que é armazenado na primeira localização de memória do array
- Adicionar 32 bytes à localização (pular o length do array) para ver a próxima localização disponível
- Multiplicar o length do array por 32 bytes para avançar para a próxima localização de memória
- Armazenar nosso novo valor (4)
- Atualizar o length do array em um
- Atualizar o free memory pointer
- Retornar o array

Vamos ver o layout de memória mais uma vez.

<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>New length of the 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,
      },
    ],
  }}
/>

Isso conclui a seção sobre memória!

A seguir, aprenda [como chamar smart contracts usando Yul](http://www.alchemy.com/overviews/yul-contract-calls) ou volte para aprender a [ler e escrever variáveis de storage compactadas](http://www.alchemy.com/overviews/yul-packed-storage-variables)!
