Como funciona o storage em Yul?
Escrito por Mark Jonathas
Yul é uma linguagem de programação intermediária que pode ser usada para escrever uma forma de linguagem assembly dentro de smart contracts. Entender Yul pode elevar o nível dos seus smart contracts e ajudar a economizar gas dos usuários. Para começar a escrever smart contracts com Yul, é importante entender como funciona o storage.
Como funciona o storage no Yul?
Antes de nos aprofundarmos em como funciona o Yul, precisamos entender bem como funciona o storage em smart contracts. O storage é composto por uma série de slots. Existem 2²⁵⁶ slots para um smart contract.
Ao declarar variáveis, começamos no slot 0 e incrementamos a partir daí. Cada slot tem 256 bits de comprimento (32 bytes), e é daí que vêm os nomes uint256 e bytes32. Todas as variáveis são convertidas para hexadecimal.
Se uma variável, como um uint128, é usada, não ocupamos um slot inteiro para armazená-la. Em vez disso, ela é preenchida com 0's do lado esquerdo. Vamos ver um exemplo para entender melhor.
var1: Como variáveis uint256 equivalem a 32 bytes, var1 ocupa a totalidade do slot 0.
Aqui está o que é armazenado no slot 0:
0x0000000000000000000000000000000000000000000000000000000000000100
var2: Endereços são um pouco mais complexos. Como ocupam apenas 20 bytes de storage, endereços são preenchidos com 0's do lado esquerdo.
Aqui está o que é armazenado no slot 1:
0x0000000000000000000000009acc1d6aa9b846083e8a497a661853aae07f0f00.
var3: Este pode parecer simples, o slot 2 é consumido pela totalidade da variável bytes32.
var4 & var5: Lembra quando mencionei que uint128's são preenchidos com 0's? Bem, se ordenarmos nossas variáveis de forma que a soma do seu storage fique abaixo de 32 bytes, podemos encaixá-las juntas em um slot! Isso é chamado de packing de variáveis, e pode economizar gas.
Vamos ver o que é armazenado no slot 3:
0x0000000000000000000000000000000200000000000000000000000000000001.
Perceba que 0x000000000000000000000000000002 e 0x000000000000000000000000000001 se encaixam perfeitamente juntos no mesmo slot. Isso acontece porque ambos ocupam 16 bytes (metade de um slot).
Vamos ver outro exemplo!
x = 3. Isso faz sentido já que sabemos que var5 está armazenada no slot 3.
y = 16. Isso também deve fazer sentido já que sabemos que var4 ocupa metade do slot 3. Como as variáveis são organizadas da direita para a esquerda, obtemos o byte 16 como índice inicial de var5.
z = 1. O sstore() está atribuindo ao slot 0 o valor 1. Em seguida, atribuímos a z o valor do slot 0 com o sload().
Antes de continuarmos, você deve adicionar essa função ao seu arquivo do remix. Ela vai ajudar a visualizar o que está sendo armazenado em cada slot de storage.
Agora vamos olhar algumas estruturas de dados mais complexas!
Ao trabalhar com arrays estáticos, a EVM sabe quantos slots alocar para nossos dados. Neste array em particular, estamos organizando (packing) 2 elementos por slot.
Então, se você chamar getValInHex\(4\), isso retornará 0x0000000000000000000000000000000100000000000000000000000000000000.
Como era de se esperar, lendo da direita para a esquerda, vemos o valor 0 e o valor 1.
O slot 5 contém 0x0000000000000000000000000000000300000000000000000000000000000002.
A seguir, vamos olhar arrays dinâmicos.
Tente chamar getValInHex\(6\). Você verá que retorna 0x00. Como a EVM não sabe quantos slots de storage precisam ser alocados, não podemos armazenar o array aqui.
Em vez disso, o hash keccak256 do slot de storage atual (slot 6) é usado como índice inicial do array. A partir daí, tudo o que precisamos fazer é somar o índice do elemento desejado para recuperar o valor.
Aqui está um exemplo de código demonstrando como encontrar um elemento de um array dinâmico:
Aqui recuperamos o slot do array, e então realizamos uma operação add() junto com um sload() para obter o valor do elemento desejado do array.
Você pode estar se perguntando o que impede que ocorra uma colisão com o slot de outra variável?
Isso é totalmente possível, porém extremamente improvável, já que 2²⁵⁶ é um número muito grande.
Mappings se comportam de forma semelhante a arrays dinâmicos, exceto que fazemos o hash do slot junto com a chave.
Para esta demonstração, defini o valor do mapping var8[1] = 2. Agora vamos ver um exemplo de como obter o valor de uma chave de um mapping.
Como você pode ver, o código é bem parecido com quando encontramos um elemento de um array dinâmico. A principal diferença é que fazemos o hash da chave e do slot juntos.
A última parte da nossa seção sobre storage é aprender sobre mappings aninhados (nested). Antes de continuar a leitura, encorajo você a escrever sua própria implementação de como ler um valor de um mapa aninhado com base no que aprendeu até agora.
Para este exemplo, defini o valor do mapping var9[0][1] = 2.
Aqui está o código, vamos direto ao ponto!
Aqui está o que está acontecendo:
- Primeiro obtemos o hash da primeira chave (0).
- Em seguida, pegamos o hash disso com a segunda chave (1).
- Por fim, carregamos o slot do storage para obter nosso valor.
Parabéns, você concluiu a seção sobre storage com Yul!
Leia mais sobre Yul Memory, Yul Contract Calls, e Yul Packed Storage Variables.
Visões gerais relacionadas
Solidity3 de dezembro de 2025
As 6 melhores IDEs de Solidity para desenvolvedores (2026)
Conheça as melhores IDEs para desenvolvimento em Solidity.
Solidity19 de novembro de 2025
Otimização de gas em Solidity: 12 técnicas para deixar seus smart contracts mais baratos e eficientes
Quer escrever código melhor e reduzir suas taxas de gas?
Solidity13 de novembro de 2025
12 boas práticas de segurança para smart contracts em Solidity
Proteja seus smart contracts com essas dicas e ferramentas de segurança de especialistas.

Construa magia blockchain
A Alchemy combina os produtos e ferramentas de desenvolvimento Web3 mais poderosos com recursos, comunidade e suporte lendário.