WEB3DEV

Cover image for Testes de Contrato Inteligente usando Hardhat 👷 e Chai 🍵
Adriano P. Araujo
Adriano P. Araujo

Posted on

Testes de Contrato Inteligente usando Hardhat 👷 e Chai 🍵

A maioria dos contratos inteligentes que estão sendo implantados na cadeia já passaram por uma série de testes e verificações para detectar possíveis vulnerabilidades e bugs no funcionamento do código. Todo desenvolvedor de contrato inteligente deve ter conhecimento em testes de contrato inteligente. Neste blog, vou orientá-lo em várias etapas, começando pela criação de um contrato inteligente, testando-o e implantando-o em uma rede de blockchain de teste.

Pré-requisitos:

  • Conhecimento básico de JavaScript e Solidity

  • Compreensão de como contratos inteligentes e blockchains funcionam

  • BÔNUS - ter escrito contratos inteligentes anteriormente no Remix.

Configurando o ambiente:

Primeiro, precisamos configurar o projeto Hardhat para começar a trabalhar em nosso contrato inteligente.

Abra o Visual Studio Code e no terminal digite 'npx hardhat init'

Isso configurará o ambiente Node.js e a estrutura de pastas para nosso projeto Hardhat. Por enquanto, estaremos trabalhando em um projeto JavaScript do Hardhat.

Leve o seu tempo, e explore todos os arquivos e configurações deste projeto.

Antes de começarmos a trabalhar em nosso contrato inteligente e começarmos a escrever os testes e scripts de implantação para ele, precisamos garantir que nosso arquivo 'hardhat.config.js' esteja configurado de acordo com nossos objetivos. Isso envolve configurar a rede e as definições do compilador Solidity.

Em nosso arquivo de configuração, o campo de rede tem um campo de entrada de chave privada do usuário. Certifique-se de colocar a chave privada dentro de uma variável de ambiente, pois essa chave pode ser usada para desbloquear fundos e outros ativos da respectiva conta.

Neste artigo, vou demonstrar como escrever testes básicos para um contrato inteligente que consiste em funções essenciais. Escreveremos o código para o contrato inteligente e discutiremos como criar testes correspondentes para garantir sua funcionalidade.

O código para o contrato inteligente é o seguinte:

Primeiro, definimos duas variáveis int256, var1 e var2, para armazenar nossos dois números inteiros que podem ser usados posteriormente para realizar operações de adição e subtração.

A função storeVals recebe dois valores inteiros (x e y) e os armazena na var1 e na var2.

Declaramos e definimos a função addOperation, que tem visibilidade pública e a palavra-chave view é atribuída a ela para que a função possa ler as variáveis de estado, mas não modificá-las. Ela retorna a soma da var1 e var2. Da mesma forma, podemos fazer o mesmo para nossa função subtractOperation, que retorna o valor da diferença com sinal entre var1 e var2.

OK! Agora que temos o contrato escrito, é hora de compilá-lo.

Abra o seu terminal e digite "npx hardhat compile", o que gerará a pasta "artifacts" contendo a ABI (interface binária de aplicação) do contrato e outros arquivos de construção para o contrato inteligente.

NOTA: Certifique-se de ter a chave privada da sua carteira web3 presente no arquivo de configuração do hardhat, caso contrário, ocorrerá um erro. (Use o arquivo .env para salvar e usar com segurança sua chave privada ou qualquer outra informação confidencial em seu código).

Após a compilação, podemos começar a escrever os scripts de teste para nosso contrato inteligente. Embora os testes manuais usando ferramentas GUI como o Remix IDE sejam uma opção, seria mais eficiente e gratificante para um engenheiro de contratos inteligentes escrever scripts de teste personalizados.

Vamos escrever algum código de teste para nosso primeiro contrato inteligente.

Usaremos o framework de testes JavaScript chamado 'chai', que possui métodos e recursos que podem ser usados para escrever os scripts de teste para nosso contrato inteligente. O Chai é uma biblioteca versátil que não é apenas usada para testar contratos inteligentes, mas também é usada na aplicação de escrita de scripts de teste para vários outros projetos Node.js. Uma dessas aplicações é a criação de cenários de casos de teste para exercícios de resolução de problemas em um ambiente de desenvolvimento JavaScript.

Além do Chai, também faremos uso da biblioteca Ethers.js. Para usar o Ethers.js em nosso arquivo de teste, basta importá-lo ou chamá-lo antes de escrever nossos testes. Isso nos permite aproveitar as funcionalidades fornecidas pelo Ethers.js para interagir com redes Ethereum e contratos inteligentes.

Começamos com o método 'describe' para descrever ou declarar nossa suíte de testes ou grupo de testes. Ele recebe dois parâmetros - o nome da suíte de testes e uma função de retorno de chamada assíncrona que chamará os casos de teste individuais dentro do grupo de testes.

Dentro da chamada de retorno do 'describe', definimos uma função 'beforeEach' que é executada antes de cada teste individual que será definido usando os métodos 'it'.

Dentro da função 'beforeEach', primeiro obtemos a ABI do contrato usando o método 'getContractFactory' da biblioteca 'ethers'. Isso basicamente carrega a ABI do contrato inteligente da pasta de artefatos que foi criada após a compilação do contrato inteligente. O caminho para os artefatos pode ser configurado a partir do arquivo de configuração do hardhat (se você estiver trabalhando em um aplicativo web3 de stack completa e quiser organizar todas as pastas e arquivos ou algo assim).

Em seguida, implantamos o contrato e criamos uma instância do contrato inteligente, para que possamos usá-lo para chamar os métodos e as variáveis de estado públicas do contrato. 'MyContract.deploy()' é usado para implantar o contrato em algum tipo de cadeia simulada ou virtual do hardhat sendo executado localmente. E então usamos myContract.deployed() para criar a instância do contrato.

Agora escrevemos um teste para verificar se os valores passados para nossa função storeVals do nosso contrato inteligente estão armazenando os valores ou não.

Armazene os valores 1 e 2 nas variáveis 'a' e 'b'. Chame o método storeVals(a, b) usando a instância do contrato e passe os valores 'a' e 'b' para ele. Certifique-se de usar 'await' para essa chamada, pois é uma função de retorno de chamada assíncrona. Agora, use o método 'expect' do 'chai', que é usado para operações relacionadas a afirmações. Aqui, verificamos se 'var1' armazenou o valor 1 e 'var2' armazenou o valor 2.

Esperamos que o valor de 'var1' (no expect) seja igual ao valor de 'a'. Se for verdadeiro, ele verifica a próxima condição 'expect' e, finalmente, se ambas as condições 'expect' forem válidas e verdadeiras, o teste do 'it' passa.

Agora, testemos nossa operação de adição e subtração.

Ambos têm o código semelhante, exceto que chamamos o método addOperation() quando verificamos o teste de adição e subtractOperation() para o teste de subtração.

Os testes acima são mais do que suficientes para testar nosso primeiro contrato inteligente, talvez também possamos escrever um teste para verificar a condição de overflow do inteiro. Antes de escrever isso, vamos testar o contrato com esses 3 casos de teste básicos. Abra seu terminal e digite 'npx hardhat test' para executar seu script de teste.

Aqui podemos ver que todos os nossos casos de teste estão passando. Se você também vir isso, UAU, você escreveu e testou com sucesso seu contrato inteligente com seus scripts de teste personalizados. Se você enfrentar algum problema ao fazer isso, sinta-se à vontade para me informar na seção de comentários.

Agora, vamos incluir aquele último  script de teste em que verificaremos a condição de overflow de inteiro.

Para isso, criamos duas funções em nosso contrato inteligente - performOverflowOperation, que recebe um valor e adiciona 1, e performUnderflowOperation, que retorna o valor com 1 subtraído dele.

Compile novamente o contrato inteligente usando o comando 'npx hardhat compile' ou 'hh compile'.

Se o bloco try não receber nenhum erro de 'revert' do lado do contrato, ele irá gerar uma mensagem de falha informando que uma chamada de 'revert' esperada não foi fornecida pelas funções performOverflowOperation ou performUnderflowOperation, uma vez que estávamos verificando erros de overflow/underflow.

Agora, execute o arquivo de teste. Até agora, escrevemos 5 instâncias de teste - uma para armazenar valores de exemplo, uma para operação de adição, outra para operação de subtração e, por fim, para verificar condições de overflow e underflow.

Abra seu terminal e digite "npx hardhat test" para executar o script de teste.

Isso é tudo para a parte de testes. Agora você pode prosseguir com os procedimentos de implantação. Além disso, podemos realizar testes adicionais com base no número de funções presentes em nosso contrato, com o objetivo de identificar possíveis vulnerabilidades.

Para implantar seu contrato, vá para o arquivo 'scripts/deploy.js'. Por padrão, o hardhat terá o código de implantação salvo lá para o contrato 'Lock.sol' padrão. Faça algumas alterações nele, como segue:

Execute o script de implantação usando o seguinte comando:

Supondo que todo o código esteja escrito corretamente, seu contrato será implantado na rede de testes Polygon Mumbai.


Este artigo foi escrito por  Gautham Krishna e traduzido por Adriano P. de Araujo. O original em inglês pode ser encontrado aqui.

Top comments (0)