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?
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;
}
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;
}
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;
}
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;
}
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 do
resultado`` é 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)