GitHub Repo:- https://github.com/PradhumnaPancholi/Figbot
Ei pessoal! Há pouco tempo, estava aprendendo o Dapp Tools , pois possui ferramentas fantásticas para desenvolver e auditar contratos inteligentes. E embora tenha adorado a experiência, logo soube que está em fase clandestina de desenvolvimento. Isso significa que usuários casuais/individuais não podem depender de mantenedores para suporte e atualizações.
Então me deparei com o Foundry . Ele tem tudo o que o Dapp Tools oferece além da execução simbólica integrada (o que não é um problema para mim, pois uso o Manticor e da Trail of Bits ). E isso está relacionado à auditoria, portanto, não é um obstáculo no desenvolvimento de contratos inteligentes por qualquer trecho da imaginação.
Depois de trabalhar um pouco com o Foundry, gostei da experiência e quis compartilhar isso com outras pessoas. Por isso, este artigo.
Este artigo abordará os benefícios do Foundry, o processo de instalação, o desenvolvimento de um NFT (porque todos estão interessados nisso), o teste do contrato e a implantação com o Figment Datahub .
O Foundry é um kit de ferramentas incrivelmente rápido, portátil e modular para o desenvolvimento de aplicativos Ethereum escrito em Rust.
A fundição é composta por três componentes:
O foco de hoje será em Forge. Mas estarei postando artigos detalhados sobre Casta e Bigorna nas próximas semanas.
Existem muitas ferramentas de desenvolvimento de contratos inteligentes, como Truffle, Hardhat e Brownie. Mas uma das minhas principais razões para procurar ferramentas Dapp em primeiro lugar foram os testes nativos de Solidity. Escrever contratos inteligentes não é difícil ao alternar entre estruturas como Hardhat e Brownie. E são ferramentas incríveis com plugins, mas é preciso ser bem versado em JavaScript/TypeScript e Python para realizar testes.
O Foundry nos permite escrever nossos testes nativamente no Solidity. Isso economiza muito tempo na integração de novos desenvolvedores e torna o processo mais tranquilo. Em minha experiência em ajudar as pessoas a navegar no desenvolvimento de contratos inteligentes, aprendi que a melhor e mais eficiente maneira de os desenvolvedores juniores se envolverem com projetos DAO/mantidos pela comunidade é escrevendo testes e aprendendo sobre a própria base de código. Lembro que Scupy Trooples mencionou uma vez que eles usaram a mesma abordagem ao desenvolver o Alchemix Finance no Bankless .
Além disso, fuzzing integrado, códigos de trapaça, Cast e Anvil o tornam um conjunto sólido para testar contratos inteligentes. Haverá artigos mais detalhados sobre esses componentes em breve. [Fácil de integrar analisador estático]
Vamos mergulhar e construir um projeto NFT agora.
Se você estiver no Mac ou Linux, tudo o que você precisa fazer é executar dois comandos:
curl -L https://foundry.paradigm.xyz | bash
foundryup
Certifique-se de fechar o terminal antes de executar o foundryup
.
E voilá! Você está pronto.
Para Windows, você precisa ter o Rust instalado e depois:
cargo install --git https://github.com/foundry-rs/foundry --locked
Para este artigo, criaremos um projeto NFT simples chamado Figbots.
Comece criando um diretório chamado “Figbots”. E execute forge init
assim que estiver dentro do diretório. Este comando criará um projeto de fundição para você com git
inicializado.
Vamos dar uma olhada rápida na estrutura de pastas. Você tem três pastas principais, ou seja, src, lib e test. Muito auto-explicativo aqui, você escreve seus contratos em src
, testes em test
, e lib
contém todas as bibliotecas que você instalou, por exemplo, OpenZeppelin. Além disso, você obtém o foundry.toml
que contém todas as configurações como hardhat.config.js
e brownie-config.yaml
se você tiver usado essas estruturas. Outra coisa interessante é o .github, onde você pode escrever suas ações do Github. Acho muito útil para testes quando se trabalha em equipe.
Vamos começar a construir! Criaremos um NFT simples chamado Figbot com suprimento, custo (para cunhagem) e retirada limitados. Com essa abordagem, podemos cobrir arestas para diferentes testes. Em primeiro lugar, renomeie Contract.sol
e test/Contract.t.sol
para Figbot.sol
e Figbot.t.sol
respectivamente. Agora, não podemos escrever contratos inteligentes sem o Openzeppelin, podemos?
A instalação de bibliotecas com Foundry é um pouco diferente de Hardhat e Brownie. Não temos pacotes npm ou pip. Instalamos bibliotecas diretamente do Source (repositório do GitHub) no Foundry.
forge install Openzeppelin/openzeppelin-contracts
Agora podemos importar a extensão ERC721URIStorage.sol para criar nosso NFT. Para verificar se está tudo certo, podemos executar o comando forge build
, que irá compilar nosso projeto. O compilador gritará com você se houver algo errado. Caso contrário, você obterá uma compilação bem-sucedida.
Assim como qualquer outro gerenciador de pacotes, o Forge permite que você use forge install <lib>,
forge remove <lib>
e forge update <lib>
para gerenciar suas dependências.
Estaremos usando três contratos do Openzeppelin. Contadores, ERC721URIStorage e Ownable. Hora de carregar nosso recurso para IPFS usando Pinata . Usamos o contrato Ownable para definir o owner
do endereço de implantação e temos acesso ao modificador onlyOwner
para permitir que apenas o proprietário retire fundos. Counters
para nos ajudar com id(s) de token e ERC721URIStorage
para manter o contrato NFT simples.
Definindo a variável de estado:
MAX_SUPPLY
para 100COST
para 0,69 éterTOKEN_URI
para CID, recebemos de PinataUsando o contador para id de token:
using Counters for Counters.Counter;
Counters.Counter private tokenIds;
Construtor ERC721:
constructor() ERC721(“Figbot”, “FBT”) {}
Função de hortelã:
msg.value
é maior que COST
tokenIds.current()
é maior ou igual a MAX_SUPPLY
_safeMint
e _setTokenURI
Função de retirada:
function withdrawFunds() external onlyOwner { uint256 balance = address(this).balance; require(balance > 0, "No ether left to withdraw"); (bool success, ) = (msg.sender).call{value: balance}(""); require(success, "Withdrawal Failed"); emit Withdraw(msg.sender, balance); }
Função TotalSupply:
function totalSupply() public view returns (uint256) { return _tokenIds.current(); }
Como todos sabemos, testar nossos contratos inteligentes é muito importante. Nesta seção, escreveremos alguns testes para obter uma compreensão sólida do forge test
e nos acostumarmos a escrever testes na solidez nativa. Seremos três códigos de trapaça Foundry (eu os amo!) Para gerenciar os estados da conta para se adequar ao nosso cenário de teste.
Estaremos testando para os seguintes cenários:
Como podemos ter uma lógica complexa em nossos contratos inteligentes. E espera-se que eles se comportem de maneira diferente dependendo do estado, da conta usada para invocar, do tempo etc. Para lidar com esses cenários, podemos usar cheatcodes para gerenciar o estado do blockchain. Podemos usar esses cheatcodes usando vm
instance, que faz parte da biblioteca de Test
do Foundry.
Nós estaremos usando três cheatcodes em nossos testes:
startPrank
: Define msg.sender
para todas as chamadas subseqüentes até que stopPrank
seja chamado.
stopPrank
:
Pára uma partida ativa iniciada por startPrank
, redefinindo msg.sender
e tx.origin
para os valores antes startPrank
ser chamado.
deal
: Define o saldo de um endereço fornecido para o saldo fornecido.
O Foundry vem com uma biblioteca de teste integrada. Começamos importando esta biblioteca de teste, nosso contrato (aquele que queremos testar), definindo o teste, configurando as variáveis e a função setUp
.
pragma solidity ^0.8.13; import"forge-std/Test.sol"; import "../src/Figbot.sol"; contract FigbotTest is Test { Figbot figbot; address owner = address(0x1223); address alice = address(0x1889); address bob = address(0x1778); function setUp() public { vm.startPrank(owner); figbot = new Figbot(); vm.stopPrank(); } }
Para variáveis de estado, criamos uma variável figbot
do tipo Figbot
. Este também é o lugar onde gosto de definir contas de usuário. No Foundry, você pode descrever um endereço usando a sintaxe address(0x1243)
. você pode usar quaisquer quatro caracteres alfanuméricos para isso. Criei as contas denominadas owner, Alice e bob, respectivamente.
Agora nossa função setUp
. Este é um requisito para escrever testes no Foundry. É aqui que fazemos todas as implantações e coisas dessa natureza. Usei o cheatcode startPrank
para mudar o usuário para o “proprietário”. Por padrão, o Foundry usa um endereço específico para implantar contratos de teste. Mas isso torna mais difícil testar funções com privilégios especiais, como withdrawFunds
. Portanto, mudamos para a conta de "proprietário" para esta implantação.
Começando com um teste de asserção simples para aprender a convenção do Foundry. Por convenção, todas as funções de teste devem ter o prefixo test
. E usamos assertEq
para testar se dois valores são iguais.
Chamamos nossa função MaxSupply
e testamos se o valor do resultado é 100, conforme descrevemos em nosso contrato. E usamos forge test
para executar nossos testes.
E voilá!!! temos um teste aprovado.
Agora que escrevemos um teste simples, vamos escrever um com cheatcodes. A função principal do nosso contrato.
balanceOf
Alice é 1 Temos outra função de teste usada para testes que esperamos falhar. O prefixo usado para tal teste é testFail
. Testaremos se a função mint
reverte se o chamador não tiver fundos suficientes.
balanceOf
Bob é 1 Como mint não passou, o saldo de Bob não será 1. Portanto, ele falhará, exatamente para o que usamos testFail
. Então, quando você executar forge test
, ele passará.
Aqui vamos testar uma função que somente o “proprietário” pode executar com sucesso. Para este teste, iremos:
withdrawFunds
de fundos (se for bem-sucedida, deve fazer com que o saldo do proprietário seja 0,69 ether)Agora que testamos nosso contrato, é hora de implantá-lo. Precisamos de chaves privadas para uma carteira (com algum ETH de teste Rinkeby) e um URL RPC. Para nossa URL RPC, usaremos Figment DataHu .
O Figment DataHub nos fornece infraestrutura para desenvolver na Web 3. Ele suporta várias cadeias como Ethereum, Celo, Solana, Terra, etc.
Você pode obter seu URL RPC para Rinkeby na guia "Protocolos".
Abra seu terminal para inserir essas duas coisas como variáveis de ambiente.
export FIG_RINKEBY_URL=<Your RPC endpoint> export PVT_KEY=<Your wallets private key>
Assim que tivermos as variáveis de ambiente, estamos prontos para implantar
forge create Figbot --rpc-url=$FIG_RINKEBY_URL --private-key=$PVT_KEY
Estamos quase terminando aqui. Até agora, escrevemos, testamos e implantamos um contrato inteligente com Foundry e Figment DataHub. Mas ainda não terminamos totalmente. Agora vamos verificar nosso contrato. Precisamos configurar nossa chave de API Etherscan para isso.
export ETHERSCAN_API=<Your Etherscan API Key>
E agora podemos verificar nosso contrato inteligente.
forge verify-contract --chain-id <Chain-Id> --num-of-optimizations 200 --compiler-version <Compiler Version> src/<Contract File>:<Contract> $ETHERSCAN_API
Parabéns! Agora você pode escrever, testar e implantar contratos inteligentes usando o Foundry. Espero que você tenha gostado e aprendido com este artigo. Eu realmente gostei de escrever isso. Sinta-se livre para me deixar saber seus pensamentos sobre isso.