No Solidity, várias funções importantes para codificação e decodificação de dados são abi.encode
, encodePacked
, decode
, string.concat
, bytes.concat
e, finalmente, conversão de tipo usando bytes ou strings.
Essas funções permitem converter tipos de dados do Solidity, como strings, inteiros, endereços, etc., em uma representação binária compacta e vice-versa.
Compreender como codificar e decodificar dados adequadamente é essencial ao construir contratos inteligentes que precisam emitir eventos, retornar dados aos clientes ou interagir com contratos e protocolos externos.
Não ter uma boa ideia de como fazer isso pode levar a bugs, comportamento não intencional ou desperdício de taxas de gás.
Neste artigo, daremos uma olhada de baixo nível em como essas funções de codificação do Solidity funcionam sob o capô. Exploraremos as principais diferenças entre encode e encodePacked e quando usar cada um. Também abordaremos algumas armadilhas e problemas comuns que podem surgir ao codificar e decodificar dados em seus contratos.
Como diria Patrick, vamos mergulhar na toca do coelho. Espero te ver do outro lado.
Pré-requisito
- Conhecimento básico de Solidity ou qualquer linguagem de programação
- Remix IDE
abi.encode
abi.encode
é uma função do Solidity que faz parte do mecanismo de codificação da Application Binary Interface (ABI) ou interface binária de aplicação. Ela codifica principalmente múltiplos valores em um formato binário bem compactado.
function encodeValue() public pure returns (bytes memory){
bytes memory vals = abi.encode("Scofield course", "is easy to grasp");
return vals;
}
Por exemplo, queremos codificar "scofield course"
e "is easy to grasp"
. Criamos nossa função e definimos a memória como memória de bytes, lembrando que qualquer coisa armazenada na memória não é retida, ao contrário do armazenamento que guarda valor.
Criamos uma variável de bytes, codificamos nosso valor nela e em seguida, retornamos o valor em vals, enquanto abi.encode
agrupa todos os valores.
Existem muitos preenchimentos, e é por isso que a função abi.encodePacked
é necessária.
abi.encodePacked
A seguir esta função abi.encodePacked
, que foi projetada especificamente para compactar múltiplos valores sem adicionar qualquer preenchimento. Ela concatena os dados binários brutos de cada parâmetro.
Um exemplo:
function encodeValue2() public pure returns (bytes memory){
bytes memory vals = abi.encodePacked("Scofield course", "is easy to grasp");
return vals;
}
O mesmo exemplo que o anterior, apenas alteramos a forma como ele é compactado. Aqui está o resultado:
A versão compactada remove todo o preenchimento enquanto obtemos apenas o valor em retorno, economizando gás e nos permitindo ainda usar o valor do byte recuperado.
TypeCasting
Typecasting refere-se à conversão explícita de uma variável de um tipo de dados para outro.
Se você sabe um pouco sobre typecasting, pode argumentar: por que não simplesmente fazemos typecasting e obtemos o mesmo resultado? Se você for iniciante, consulte este artigo para saber mais sobre typecasting.
function encodeB() public pure returns(bytes memory) {
bytes memory value = bytes("Scofield course", "is easy to grasp");
return value;
}
Testamos isso e obtivemos esse erro.
TypeError: Exactly one argument expected for explicit type conversion.
--> encode.sol:18:30:
|
18 | bytes memory value = bytes("Scofield course", "is easy to grasp");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Só poderíamos receber um argumento por vez, o que, se ainda continuássemos usando esse método, talvez nos fizesse ter que definir mais bytes de memória, da seguinte forma:
function encodeB() public pure returns(bytes memory, bytes memory) {
bytes memory value1 = bytes("Scofield course");
bytes memory value2 = bytes("is easy to grasp");
return (value1, value2);
Observe que ainda temos que separá-los e também separar o resultado. Mesmo que sejam iguais, estão em uma memória separada, o que não é o que buscamos.
bytes.concat
bytes.concat é especializada em concatenar arrays de bytes brutos, garantindo que o resultado seja um array de bytes devidamente alinhado. Falta a versatilidade do abi.encodePacked para lidar com múltiplos tipos de dados.
function encodB() public pure returns(bytes memory) {
bytes memory value = bytes.concat("my name is ", "scofield");
return value;
}
bytes.concat
junta arrays de bytes de ponta a ponta, preservando o alinhamento. Funciona apenas em arrays de bytes.
Lembre-se de que só pode funcionar para determinados tipos de dados e não para todos, como encode.
string.concat
A função string.concat
no Solidity permite unir várias strings em uma nova string única. Isso evita a necessidade de adicioná-las manualmente com a adição básica de strings.
function encodB() public pure returns(string memory) {
string memory value = string.concat("my name is ", "scofield");
return value;
}
Aqui, adicionamos “my name is” a “scofield” e o resultado é o que está abaixo.
abi.decode
Se você está se perguntando se conseguiremos recuperar nosso valor convertido após a conversão, você está certo; podemos, com a função abi.decode
.
abi.decode
permite decodificar parâmetros codificados de chamadas de contrato externos. Ele descompacta os dados codificados para que seu contrato do Solidity possa trabalhar novamente com os valores originais.
A decodificação de parâmetros de dados com abi.decode
é essencial para trabalhar com valores de retorno de chamadas de função de contrato externos. Também permite que seu contrato aceite e processe parâmetros de entrada codificados de usuários e outros contratos.
Por exemplo:
function decodeValue() public pure returns (string memory){
string memory vals = abi.decode(encodeValue() , (string));
return vals;
}
Temos que mudar a memória de bytes para strings à medida que convertemos de volta para strings e então copiamos a função encodeValue()
mais a (string)
, que gera isto.
OH NÃO!!!!
Recebemos apenas metade do nosso valor codificado. O que aconteceu com a outra metade? Se você conseguir descobrir, deixe um comentário abaixo para que eu possa saber.
Fontes
- Getting Started with Foundry for Beginners in 2024
- What are Smart Contracts?
- Create a Raffle Draw Smart Contract Using Foundry 2024 (Part 1)
- Create an NFT as a Developer: Deep Dive into Smart Contracts
Presenteie-nos com uma xícara de café se você for gentil.
Este artigo foi escrito por Scofield O. Idehen, e traduzido por Isabela Curado Nehme. Seu original pode ser lido aqui.
Latest comments (0)