WEB3DEV

Cover image for A Sintaxe try-catch do Solidity: Tratamento de Erros com Exemplos
Paulo Gio
Paulo Gio

Posted on

A Sintaxe try-catch do Solidity: Tratamento de Erros com Exemplos

https://miro.medium.com/v2/resize:fit:1100/0*vkSuiW3CfXQWH2JH

Introdução

Ao criar contratos inteligentes na blockchain Ethereum, lidar com erros pode ser uma parte muito importante do processo, especialmente quando não há muitas ferramentas disponíveis! A adição da sintaxe try/catch na versão 0.6.0 do Solidity foi um grande passo na direção certa para o tratamento de erros. Esses novos recursos se baseiam em recursos anteriores, como a adição de strings de razão nas declarações revert e require da versão 0.4.22.

Você pode estar se perguntando por que as habilidades de tratamento de erros são tão importantes no desenvolvimento de contratos baseados em Solidity. Em muitos casos, os contratos inteligentes representam ativos do mundo real e têm um alto valor monetário. A abordagem "tudo ou nada" do Solidity em relação às transações nem sempre tornou possível lidar com erros de maneira detalhada. Imagine colocar muito dinheiro em um contrato inteligente, apenas para que a transação falhe no último minuto, deixando você se perguntando por que não houve um tratamento de erros mais detalhado.

Com a sintaxe try/catch adicionada na versão 0.6.0, os desenvolvedores agora têm as ferramentas necessárias para lidar com falhas complexas em chamadas externas sem precisar reverter toda a transação. Embora as alterações de estado na função chamada ainda sejam revertidas, o tratamento de erros em uma base por transação oferece melhor alinhamento de comportamento prático.

Neste artigo, exploraremos em detalhes a sintaxe try/catch do Solidity, com exemplos.

Usando 'try catch' em Contratos Inteligentes

A declaração try/catch permite localizar e responder a chamadas externas com falha e chamadas com falha para criar um contrato. Isso dá mais controle sobre como os erros são tratados em contratos Solidity. No entanto, é importante saber que a declaração try/catch não pode ser usada para chamadas de função internas.

Veja este exemplo simples para ver como usar a declaração try/catch. Temos dois contratos: HelloWorld e HelloWorldFactory.

O contrato HelloWorld possui uma função muito simples que retorna uma string de mensagem:

O contrato HelloWorldFactory cria e gerencia instâncias de HelloWorld. A função createHelloWorld cria uma nova instância de HelloWorld e a armazena no mapeamento de contratos. Se a transação falhar, o bloco try/catch detecta o erro e o adiciona à variável errorCount.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract HelloWorld {
    function showMessage() public pure returns (string memory) {
        return "Hello, World!";
    }
}

contract HelloWorldFactory {
    mapping (address => HelloWorld) public contracts;
    uint public errorCount;

    function createHelloWorld() public {
        try new HelloWorld()
            returns (HelloWorld newContract)
        {
            contracts[msg.sender] = newContract;
        } catch {
            errorCount++;
        }
    }
Enter fullscreen mode Exit fullscreen mode

Usar a sintaxe try/catch dessa maneira torna mais fácil alinhar o comportamento nos ciclos de vida das transações e dá aos contratos Solidity um controle mais preciso sobre como lidar com erros.

Recuperando a mensagem de erro

Ao usar a sintaxe try/catch, é possível obter mais informações sobre o motivo da falha de uma transação. O Solidity oferece duas maneiras de obter mensagens de erro.

No último exemplo, criamos dois contratos: HelloWorld e HelloWorldFactory. O contrato HelloWorld tinha uma função que retornava uma string de mensagem, e o contrato HelloWorldFactory criava e gerenciava instâncias do HelloWorld.

Para ilustrar os dois métodos de recuperação de mensagens de erro, vamos modificar a função createHelloWorld no contrato HelloWorldFactory:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract HelloWorld {
    function showMessage() public pure returns (string memory) {
        return "Hello, World!";
    }
}

contract HelloWorldFactory {
    mapping (address => HelloWorld) public contracts;
    string public errorMessage;
    bytes public errorData;

    function createHelloWorld() public {
        try new HelloWorld()
            returns (HelloWorld newContract)
        {
            contracts[msg.sender] = newContract;
        } catch Error(string memory reason) {
            errorMessage = reason;
        } catch (bytes memory data) {
            errorData = data;
Enter fullscreen mode Exit fullscreen mode

Neste exemplo, modificamos a função createHelloWorld para incluir duas declarações catch. A primeira declaração catch, catch Error(string memory reason), captura o erro e passa a mensagem de erro com a variável reason, que armazenamos na string errorMessage.

A segunda declaração catch, catch (bytes memory data), recupera um buffer de memória de byte se ocorrer um erro. Nesse caso, armazenamos o buffer de memória de byte na variável de bytes errorData.

O uso de mensagens de erro em contratos Solidity pode ser uma ferramenta de depuração eficaz para desenvolvedores, pois oferece um controle mais preciso sobre o tratamento de erros em contratos Solidity.

https://miro.medium.com/v2/resize:fit:720/0*aAvlKk-3A0wgpWU-

Vantagens e desvantagens de cada método

Vantagens de catch Error(string memory reason)

Uma vantagem de usar a declaração catch Error(string memory reason) é que ela fornece uma mensagem de erro legível por humanos, o que é mais fácil de interpretar e depurar para desenvolvedores. A variável de string também permite uma filtragem e categorização mais fácil dos erros.

Desvantagens de catch Error(string memory reason)

A principal desvantagem de usar catch Error(string memory reason) é que pode ser mais caro em termos de uso de gás. Isso ocorre porque, em Solidity, as variáveis de string são armazenadas após o código do contrato, o que requer mais gás.

Vantagens de catch (bytes memory reason)

Uma vantagem de usar a declaração catch (bytes memory reason) é que ela recupera um buffer de memória de byte que pode conter dados arbitrários, incluindo vários tipos de dados. Isso pode ser útil para depurar erros mais complexos e diversos.

Outra vantagem é que o uso de variáveis de bytes é mais barato em termos de uso de gás. Isso ocorre porque as variáveis de bytes são armazenadas nos primeiros 32 bytes de memória, o que requer menos gás.

Desvantagens de catch (bytes memory reason)

A principal desvantagem de usar catch (bytes memory reason) é que a mensagem de erro não é legível por humanos, o que dificulta a depuração e a compreensão do erro pelos desenvolvedores. Além disso, como a variável de bytes pode conter dados arbitrários, pode ser mais difícil filtrar e categorizar os erros.

Conclusão

A sintaxe try/catch no Solidity é uma ferramenta importante para lidar com erros no desenvolvimento de contratos inteligentes. Ao usar a declaração try/catch, os desenvolvedores podem capturar erros em chamadas externas e recuperar mensagens de erro usando a declaração catch Error(string memory reason) ou a declaração catch (bytes memory reason).

Cada método tem suas próprias vantagens e desvantagens, dependendo do contexto do tratamento de erros. A declaração catch Error(string memory reason) fornece mensagens de erro legíveis por humanos, enquanto a declaração catch (bytes memory reason) é mais barata em termos de uso de gás e suporta tipos de dados arbitrários.

Além disso, a versão 0.8.0 do Solidity introduziu o tipo Error, que permite aos desenvolvedores definir seus próprios tipos de erro e fornecer mensagens de erro mais específicas e detalhadas aos usuários. Leia mais sobre erros personalizados aqui.

Obrigado por ler! Se você achou este artigo útil, sinta-se à vontade para seguir minhas redes sociais para obter mais atualizações sobre o desenvolvimento com o Solidity e as melhores práticas de contratos inteligentes.

PS: Além disso, recentemente escrevi um novo livro, "Proof-of-Stake para iniciantes: um guia para entender o funcionamento interno do protocolo Proof-of-Stake da Ethereum", que você pode acessar neste link. Ele abrange tudo o que você precisa saber sobre a transição da Ethereum, do Proof-of-Work (prova de trabalho) para o Proof-of-Stake (prova de participação), incluindo conceitos básicos, staking, recompensas e muito mais. Espero que possa ajudá-lo a entender as mudanças revolucionárias que estão chegando ao ecossistema Ethereum!

Novamente, obrigado pelo seu interesse no desenvolvimento com o Solidity, e espero compartilhar mais com você no futuro.

Artigo original publicado por Ashwin Yardi. Traduzido por Paulinho Giovannini.

Top comments (0)