WEB3DEV

Cover image for Web 3 Parte III: Introdução ao desenvolvimento de contrato inteligente com Foundry
Banana Labs
Banana Labs

Posted on

Web 3 Parte III: Introdução ao desenvolvimento de contrato inteligente com Foundry

Capa

Quanto mais desenvolvimento de contrato inteligente tivermos, maior será a necessidade de ter kits de ferramentas de desenvolvimento que possam ajudar os desenvolvedores a implementar, testar e implantar com facilidade e rapidez. No que diz respeito aos kits de ferramentas de desenvolvimento de blockchain, muitas vezes ouvimos falar de Truffle e Hardhat, no entanto, a Opensea acaba de lançar uma nova versão de seu contrato inteligente chamado seaport, que é inicializado usando o Foundry.

O que é exatamente Foundry?

Foundry é um kit de ferramentas de desenvolvimento de contrato inteligente que gerencia suas dependências, compila seu projeto, executa testes, implementa e permite que você interaja com a cadeia a partir da linha de comando.

O Foundry é rápido em comparação com outros kits de ferramentas de desenvolvimento de contratos inteligentes, pois é escrito em Rust. O recurso mais interessante do Foundry é, na verdade, sua capacidade de permitir que os desenvolvedores implementem seus testes no Solidity e é altamente personalizável.

Instalação

Se você estiver usando Linux ou macOS, execute o seguinte comando:

curl -L <https://foundry.paradigm.xyz> | bash
Enter fullscreen mode Exit fullscreen mode

Isso fará o download do foundryup. Em seguida, instale o Foundry executando:

foundryup
Enter fullscreen mode Exit fullscreen mode

Se você usa o Windows, precisa compilar a partir do código-fonte para obter o Foundry.

Baixe e execute rustup-init de rustup.rs. Ele iniciará a instalação em um console.

Depois disso, execute o seguinte para criar o Foundry a partir da fonte:

cargo install --git <https://github.com/foundry-rs/foundry> foundry-cli anvil --bins --locked
Enter fullscreen mode Exit fullscreen mode

Inicialização do projeto

Com o Foundry instalado, podemos criar nosso projeto executando este comando no diretório preferencial onde precisamos manter o projeto:

forge init foundry-project
Enter fullscreen mode Exit fullscreen mode

Após rodar o comando acima, deverá gerar um projeto com a seguinte estrutura:

  foundry-project
   ├─ lib
   │  └─ forge.std
   ├─ src
   │  └─ Contract.sol
   ├─ script
   │  └─ Contract.s.sol
   ├─ test
   │  └─ Contrat.t.sol
   └─ foundry.toml
Enter fullscreen mode Exit fullscreen mode

Como podemos ver, o projeto é gerado com alguns diretórios, o diretório lib contém todas as dependências necessárias para o projeto, é semelhante a um node_modules. O diretório src mantém a implementação do contrato inteligente, o script armazena scripts de solidity que podem ser usados para a implantação, o diretório test contém todos os arquivos de teste e, por último, o arquivo foundry.toml é usado para manter a configuração do projeto.

Implementação do projeto

Vamos implementar um contrato inteligente básico, pois este tutorial se trata de uma introdução. Então vamos criar o arquivo Counter.sol dentro da pasta src e adicionar os seguintes códigos:

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

contract Counter {

    address owner;
    int private count;

    constructor (int _count){
        owner = msg.sender;
        count = _count;
    }

    function getCount () public view returns (int) {
        return count;
    }

    function incrementCount () public {
        require(msg.sender == owner, "Unauthorized");
        count++;
    }

    function decrementCount () public {
        require(msg.sender == owner, "Unauthorized");
        count--;
    }
}
Enter fullscreen mode Exit fullscreen mode

Neste trecho de código, basicamente implementamos o contrato de contador que contém um construtor que inicializa owner & count e também possui três funções para obter, incrementar e decrementar o contador, no qual apenas o proprietário pode incrementar ou decrementar.

O projeto pode ser construído para gerar a ABI usando o seguinte comando:

forge build

Implementação do teste

Vamos criar o arquivo de teste chamado Counter.t.sol no diretório test com os seguintes casos de teste:

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import "forge-std/Test.sol";
import "src/Counter.sol";

contract CounterTest is Test {

    Counter counter;
    function setUp() public {
        counter = new Counter(2);
    }

    function testGetCount() public {
        int value = counter.getCount();
        assertEq(value, 2);
    }


    function testIncrementCount() public {
        counter.incrementCount();
        int value = counter.getCount();
        assertEq(value, 3);
    }

    function testIncrementCountFail() public {
        vm.prank(address(0));
        vm.expectRevert("Unauthorized");
        counter.incrementCount();
    }

    function testDecrementCount() public {
        counter.decrementCount();
        int value = counter.getCount();
        assertEq(value, 1);
    }

    function testDecrementCountFail() public {
        vm.prank(address(0));
        vm.expectRevert("Unauthorized");
        counter.decrementCount();
    }
}
Enter fullscreen mode Exit fullscreen mode

Antes de tudo estamos importando o forge-std.Test.sol que encapsula um conjunto de funções utilitárias necessárias para escrever o teste e fizemos o mesmo com o Counter.sol que é o contrato inteligente que está sendo testado.

Em seguida, estamos configurando nosso teste inicializando nosso contrato inteligente de contador com 2 como valor padrão. Estamos aproveitando a função AssertEq vinda do forge-std.Test.sol para comparar se o valor retornado após a chamada da função getCount é igual ao passado durante a inicialização.

Você pode ver no cenário de falha do teste, estamos usando novas palavras-chave como vm.prank e vm.expectRevert, essas funções referem-se a códigos de trapaça no Foundry, eles são usados para manipular o ambiente de teste para obter situações da vida real.

A função vm.prank() é usada para definir msg.sender para o endereço especificado para a próxima chamada. Estamos literalmente usando isso aqui para mudar o proprietário. E a vm.expectRevert ajuda a interceptar uma situação de falha, passando a mensagem de erro exata.

Depois de executar o comando forge test, você poderá obter o seguinte resultado:

resultado

Implantação do Projeto

Para implantar nosso contrato inteligente, precisamos renomear Contract.s.sol para Counter.s.sol e adicionar o conteúdo abaixo:

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import "forge-std/Script.sol";
import { Counter } from "src/Counter.sol";

contract CounterScript is Script {

    function run() public {
        vm.startBroadcast();
        new Counter(2);
        vm.stopBroadcast();
    }
}
Enter fullscreen mode Exit fullscreen mode

O script possui a função run que será chamada para executar a implantação. A vm.startBroadcast cria transações que podem ser assinadas e enviadas posteriormente na cadeia e a vm.stopBroadcast interrompe a coleta de transações para transmissão posterior na cadeia.

Antes de executar o script que irá implantar nosso contrato inteligente na testnet BSC, vamos adicionar o arquivo .env no diretório raiz do projeto, contendo as seguintes chaves:

BSC_RPC=https://data-seed-prebsc-1-s2.binance.org:8545
PRIVATE_KEY=A chave privada de sua carteira
Enter fullscreen mode Exit fullscreen mode

Agora podemos executar o seguinte comando para dar acesso shell às nossas variáveis env:

Em seguida, executamos o comando de implantação

forge create --rpc-url $BSC_RPC --private-key $PRIVATE_KEY script/Counter.s.sol:CounterScript
Enter fullscreen mode Exit fullscreen mode

Em caso de implantação bem-sucedida, você deve obter a seguinte saída no terminal:

saída no terminal

Conclusão

O framework Foundry ainda pode ser uma novidade no espaço web 3, porém já chamou a atenção de grandes empresas como a Opensea por todas as vantagens que oferece, a começar pela velocidade, customização e capacidade de escrever testes em Solidity. Será exagero afirmar que superará outras ferramentas de desenvolvimento de contatos inteligentes, mas vale a pena ficar de olho no seu desenvolvimento.

Este tutorial cobre apenas os fundamentos. Para saber mais sobre o Foundry, acesse a documentação oficial.


Esse artigo é uma tradução feita por @bananlabs. Você pode encontrar o artigo original aqui

Latest comments (0)