WEB3DEV

Cover image for Armazenamento e segredos de memória em solidity
Rafael Ojeda
Rafael Ojeda

Posted on • Atualizado em

Armazenamento e segredos de memória em solidity

Armazenamento e segredos de memória em solidity

Queremos que os dados persistam na chamada do contrato inteligente ou que sejam salvos localmente enquanto executamos a função?

Image description

Foto de Lia Trevarthen em Unsplash.

Desta vez, falaremos sobre os locais de armazenamento em linguagem de programação Solidity, especificamente sobre os locais de armazenamento e memória. Não saber o que eles representam e como eles funcionam pode causar problemas em nossos contratos inteligentes.


Sumário

1 - Armazenamento

2 - Variáveis de funções locais

3 - Memória

4 - Problema usando memória e armazenamento

5 - Pra Resumir


Armazenamento

O armazenamento em contratos inteligentes mantém dados entre chamadas de função. Podemos imaginar que o armazenamento seria como um disco rígido no computador. Mesmo que o desliguemos, os dados permanecem e não são apagados. Na blockchain, o que escrevemos no armazenamento é armazenado.

Armazenamento por padrão

Variáveis de estado

Por padrão, a Solidity manterá em armazenamento as variáveis de estado do contrato inteligente.

contract StorageContract {
  struct LuckyNumber {
    uint256 number;
    string reason;
  }
  mapping(address => LuckyNumber) luckyNumbers;
}
Enter fullscreen mode Exit fullscreen mode

Neste exemplo, as variáveis de estado do contrato inteligente LuckyNumbers são mantidas em armazenamento, e os dados persistirão entre chamadas de função.

Quando adicionamos e obtemos o número da sorte, temos um resultado previsível.

function addLuckyNumber(LuckyNumber memory luckyNumber) external {
  require(luckyNumber.number != 0, "O número da sorte não pode ser 0!");
  require(luckyNumbers[msg.sender].number == 0, "Você já definiu o número da sorte. Edite-o se você tiver outro.");
  luckyNumbers[msg.sender] = luckyNumber;
}
function getMyLuckyNumber() external view returns(uint256) {
  require(luckyNumbers[msg.sender].number != 0, "Você ainda não tem um número de sorte definido.");
  LuckyNumber memory luckyNumber = luckyNumbers[msg.sender];
  return luckyNumber.number;
}
Enter fullscreen mode Exit fullscreen mode

Variáveis de funções locais

Variáveis de funções locais de estrutura, matriz ou mapeamento são salvas no armazenamento por padrão. Isso significa que se declararmos esses valores em nossas funções, eles são mantidos em armazenamento, o que pode causar problemas inesperados que são difíceis de rastrear.

Se adicionarmos uma função edit LuckyNumber ao nosso exemplo de código e marcarmos uma cópia local como armazenamento, ela irá editar a variável de estado que esperamos.

function editLuckyNumber(uint256 luckyNumber) external {
  require(luckyNumber != 0, "O número da sorte não pode ser 0!");
  require(luckyNumbers[msg.sender].number != 0, "Você ainda não tem um número de sorte definido.");
  LuckyNumber storage _luckyNumber = luckyNumbers[msg.sender];
  _luckyNumber.number = luckyNumber;
}
Enter fullscreen mode Exit fullscreen mode

Memória

Na memória, Solidity mantém todos os tipos de valores definidos localmente, que podem ser uint, string, etc., mas não uma matriz, uma estrutura ou um mapeamento. Os argumentos de função também são mantidos na memória. Lembre-se de que a memória não pode ser usada no nível de contrato inteligente, apenas localmente em funções

function multiplyByItself(uint256 number) external pure returns(uint256) {
  uint256 result = number * number;
  return result;
}
Enter fullscreen mode Exit fullscreen mode

Neste exemplo, o argumento da função número` que passamos em nossa função é armazenado na memória. Além disso, a variável definida localmente doresultado`` é armazenada na memória e será liberada assim que a execução da função terminar.

Problema usando memória e armazenamento

Uma das maiores armadilhas do uso errado das palavras-chave de armazenamento e memória na linguagem de programação Solidity é que declaramos uma variável de armazenamento ou memória sem pensar bem nisso. Primeiro, manter os dados em armazenamento consumirá mais gas porque precisamos pagar pelo espaço do bloco. Em segundo lugar, devemos nos perguntar se precisamos acessar os dados que mantemos entre as chamadas de função. Pelas chamadas de função, pode haver até duas funções diferentes.

Se definirmos o _luckyNumber na função editLuckyNumber usando a palavra-chave memória, ele editará esta função apenas localmente, e as mudanças não serão escritas na blockchain.

`
function editLuckyNumber(uint256 luckyNumber) external {
require(luckyNumber != 0, "O número da sorte não pode ser 0!");
require(luckyNumbers[msg.sender].number != 0, "Você ainda não tem um número de sorte definido.");
LuckyNumber memory _luckyNumber = luckyNumbers[msg.sender];
_luckyNumber.number = luckyNumber;
}
`

O resultado desta função resultará na edição do número da sorte não funcionando, porque o atualizamos apenas localmente.

Pra Resumir

O armazenamento de dados usando a linguagem Solidity em nossos contratos inteligentes é uma coisa crucial. A vida é mais fácil com tipos de valores, mas com matrizes, estruturas e mapeamentos, é mais complicada. É por isso que é essencial perguntar sempre que quisermos salvar estas variáveis. Queremos que os dados persistam na chamada do contrato inteligente ou que sejam salvos localmente enquanto executamos a função?

Artigo escrito por Kristaps Grinbergs e traduzido para o português por Rafael Ojeda

Você pode encontrar o texto original aqui.

Top comments (0)