Aprenda a usar o Dapptools, a estrutura de implantação de contrato inteligente para desenvolvedores web3 que amam Bash e a linha de comando. Analisamos o aprendizado desta estrutura de implantação de blockchain de ponta a ponta.
MakerDAO é um dos maiores protocolos DeFi existentes, sendo a stablecoin DAI uma das mais utilizadas na indústria. Sua equipe usa um framework especial chamado dapptools para criar, implantar, testar e interagir com seus contratos inteligentes.
Criado pela equipe do Dapphub, o framework dapptools é uma ferramenta minimalista amigável ao bash que qualquer usuário avançado do Linux facilmente se apaixonará, e muitos já o fizeram.
Transmissions11 exclamando entusiasmo ao dapptools
Também é incrivelmente amigável para iniciantes, portanto, se esta é sua primeira olhada em um framework de implantação, você veio ao lugar certo. Neste artigo, vamos mostrar como fazer o seguinte com o dapptools:
- Escrever e compilar contratos
- Contratos de teste com solidity e fuzzing
- Implantar contratos
- Interagir com contratos implantados
Vamos usar nosso dapptools-demo que configuramos para aprender sobre isso. Sinta-se livre para pular lá para entrar. Se você quiser, você também pode conferir a ferramenta Foundry, que é uma reescrita do dapptools, mas escrita em rust pela equipe Paradigm.
Para um repositório mais completo, com mais código e bons exemplos, confira o dapptools-starter-kit, ele inclui exemplos de código usando a Chainlink!
Se você quiser apenas clonar o repositório para começar a usar ele, sinta-se à vontade para acompanhar o readme no repositório!
O vídeo sobre tudo isso será lançado em breve:
https://youtu.be/ZurrDzuurQs
Vídeo do Dapptools
Sumário
1 . Configurar
2 . Ambiente
3 . Requerimentos de instalação
4 . Crie um projeto local dapptools
5 . Executar testes
6 . Fuzzing
7 . Importação do Openzeppelin e contratos externos
8 . O Contrato NFT
9 . Remapeamentos
10 . Implantando em uma rede de teste
11 . Definir uma variável de ambiente
12 . Criar um remetente padrão
13 . Adicione sua chave privada
16 . Interagindo com contratos
17 . Verifique seu contrato no Etherscan
18 . E finalmente
19 . Recursos
Configurar
Ambiente
Primeiro, você precisará de um editor de código, sou um grande fã do VSCode. Se você estiver no Windows, precisará baixar o WSL, pois executaremos vários comandos do Windows.
Uma vez que você estiver usando o VSCode, abra um terminal para executar comandos para instalação, ou de qualquer maneira que você normalmente executa comandos de shell.
Requerimentos de instalação
- Git
- Make
- Dapptools
Primeiro, você precisará instalar o git, siga este link para instalá-lo. Você saberá que fez certo se puder executar:
git --version
Em seguida, você precisará ter certeza de ter o make
instalado. A maioria dos computadores já vem com ele instalado, mas se não, confira estas perguntas sobre o assunto na rede Stack Exchange.
Em seguida, instale o dapptools. Certifique-se de ir para a documentação oficial para instalar, mas será algo como executar isto:
# usuário deve estar em sudoers
curl -L https://nixos.org/nix/install | sh
# Execute isso ou faça login novamente para usar o Nix
. "$HOME/.nix-profile/etc/profile.d/nix.sh"
curl https://dapp.tools/install | sh
E você deve ter dapp, seth, ethsign, hevm
e alguns outros comandos que você pode executar agora!
Estas instruções só funcionam para sistemas baseados em Unix (por exemplo, MacOS)
Crie um projeto local dapptools
Para criar uma nova pasta, execute o seguinte:
dapp init
Isso lhe dará um layout de arquivo básico que deve se parecer com isso:
.
├── Makefile
├── lib
│ └── ds-test
│ ├── LICENSE
│ ├── Makefile
│ ├── default.nix
│ ├── demo
│ │ └── demo.sol
│ └── src
│ └── test.sol
├── out
│ └── dapp.sol.json
└── src
├── DapptoolsDemo.sol
└── DapptoolsDemo.t.sol
Makefile
: Onde você coloca seus “scripts”. O Dapptools é baseado em linha de comando, e nosso makefile nos ajuda a executar comandos grandes com poucos caracteres.
lib
: esta pasta é para dependências externas, como o Openzeppelin ou o ds-test.
out
: para onde vai o seu código compilado. Semelhante à pasta build
em brownie
ou à pasta artifacts
no hardhat.
src
: é aqui que estão seus contratos inteligentes. Semelhante à pasta contracts
em brownie
e hardhat
.
Executar testes
Para executar testes, você só precisará executar:
dapp test
e você verá uma saída como:
Running 2 tests for src/DapptoolsDemo.t.sol:DapptoolsDemoTest
[PASS] test_basic_sanity() (gas: 190)
[PASS] testFail_basic_sanity() (gas: 2355)
Fuzzing
Dapptools vem incorporado com ênfase em fuzzing. Uma ferramenta incrivelmente poderosa para testar nossos contratos com dados aleatórios.
Vamos atualizar nosso DapptoolsDemo.sol
com uma função chamada play
. Aqui está como nosso novo arquivo deve ficar:
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.6;
contract DapptoolsDemo {
function play(uint8 password) public pure returns(bool){
if(password == 55){
return false;
}
return true;
}
}
E vamos adicionar um novo teste em nosso DappToolsDemo.t.sol
que é compatível com fuzzing chamado test_basic_fuzzing
. O arquivo então ficará assim:
// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity ^0.8.6;
import "ds-test/test.sol";
import "./DapptoolsDemo.sol";
contract DapptoolsDemoTest is DSTest {
DapptoolsDemo demo;
function setUp() public {
demo = new DapptoolsDemo();
}
function testFail_basic_sanity() public {
assertTrue(false);
}
function test_basic_sanity() public {
assertTrue(true);
}
function test_basic_fuzzing(uint8 value) public {
bool response = demo.play(value);
assertTrue(response);
}
}
Agora podemos fornecer dados aleatórios ao nosso contrato e esperamos que ele dê um erro se nosso código fornecer o número 55. Vamos executar nossos testes agora com o sinalizador fuzzing:
dapp test — fuzz-runs 1000
E veremos uma saída como:
+ dapp clean
+ rm -rf out
Executando 3 testes para src/DapptoolsDemo.t.sol:DapptoolsDemoTest
[PASS] test_basic_sanity() (gas: 190)
[PASS] testFail_basic_sanity() (gas: 2355)
[FAIL] test_basic_fuzzing(uint8). Counterexample: (55)
Run:
dapp test --replay '("test_basic_fuzzing(uint8)","0x0000000000000000000000000000000000000000000000000000000000000037")'
para testar este case novamente, ou
depuração do dapp --replay '("test_basic_fuzzing(uint8)","0x0000000000000000000000000000000000000000000000000000000000000037")'
para depurá-lo.
Falha:
Erro: Asserção falhada
E nossos testes fuzzing detectaram o outlier! Corri 1000
trilhas diferentes para o nosso teste test_basic_fuzzing
e encontrei o outlier 55. Isso é incrivelmente importante para encontrar os casos de uso aleatórios que quebram seus contratos nos quais você pode não ter pensado.
Importação do Openzeppelin e contratos externos
Digamos que queremos criar um NFT usando o padrão Openzeppelin. Para instalar contratos ou pacotes externos, podemos usar o comando dapp install
. Precisamos nomear a organização do repositório GitHub e o nome do repositório a ser instalado.
Primeiro, precisamos confirmar nossas alterações até agora! O Dapptools traz pacotes externos como git submodules, então precisamos confirmar primeiro.
Execute:
git add .
git commit -m 'initial commit'
Então, podemos instalar nossos pacotes externos. Por exemplo, para OpenZeppelin, usaríamos:
dapp install OpenZeppelin/openzeppelin-contracts
Você deve ver uma nova pasta em sua pasta lib
agora rotulada como openzeppelin-contracts
.
O Contrato NFT
Crie um novo arquivo na pasta src
chamado NFT.sol
. E adicione este código:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
contract NFT is ERC721 {
uint256 public tokenCounter;
constructor () ERC721 ("NFT", "NFT"){
tokenCounter = 0;
}
function createCollectible() public returns (uint256) {
uint256 newItemId = tokenCounter;
_safeMint(msg.sender, newItemId);
tokenCounter = tokenCounter + 1;
return newItemId;
}
}
Se você tentar dapp build
agora, você receberá um grande erro!
Remapeamentos
Precisamos informar ao dapptools que import
"@openzeppelin/contracts/token/ERC721/ERC721.sol";
está apontando para nossa pasta lib
. Então criamos um arquivo chamado remappings.txt
e adicionamos:
@openzeppelin/=lib/openzeppelin-contracts/
ds-test/=lib/ds-test/src/
Em seguida, criamos um arquivo chamado .dapprc
adicionamos a seguinte linha:
export DAPP_REMAPPINGS=$(cat remappings.txt)
O Dapptools procura em nosso .dapprc
por diferentes variáveis de configuração, como hardhat.config.js
no hardhat. Neste arquivo de configuração, dizemos a ele para ler a saída remappings.txt
e usá-la como “remapeamentos”. Remapeamentos são como informamos nossas importações em solidity de onde devemos importar os arquivos. Por exemplo em nosso remapping.txt
vemos:
@openzeppelin/=lib/openzeppelin-contracts/
Isso significa que estamos dizendo ao dapptools que quando ele compila um arquivo e vê @openzeppelin/
em uma instrução de importação, ele deve procurar arquivos em lib/openzeppelin-contracts/
. Então se fizermos
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
Estamos realmente dizendo:
import "lib/openzeppelin-contracts/contracts/token/ERC721/ERC721.sol";
Então, para não compilarmos toda a biblioteca, precisamos adicionar o seguinte ao nosso arquivo .dapprc
:
export DAPP_LINK_TEST_LIBRARIES=0
Isto diz ao dapptools para não compilar tudo em lib
quando executamos testes.
Implantando em uma rede de teste
Nota: Se você deseja configurar sua própria rede local, você pode executar
dapp testnet
.
Adicione .env
ao seu arquivo .gitignore
.
Se você ainda não tiver um, crie um arquivo .gitignore
e apenas anexe esta linha dentro dele:
.env
Por favor faça isso. Não vamos empurrar sua chave privada para git com este passo a passo (yee!), mas queremos adquirir o hábito de adicionar isto ao nosso .gitignore
sempre! Isso ajudará a protegê-lo contra o envio acidental de variáveis de ambiente para um repositório git público. Você ainda pode forçá-los, então tenha cuidado!
Definir uma variável de ambiente
Para implantar em uma rede de teste, precisamos de um nó blockchain. Uma escolha fantástica é o projeto Alchemy. Você pode obter um endpoint HTTP de rede de teste gratuito. Basta se inscrever para um projeto gratuito e clicar em view key
(ou qualquer que seja o texto no momento) e você terá um endpoint HTTP!
Você pode escolher sua rede de teste e vai querer ficar bom em trabalhar com diferentes redes de teste. Eu escolheria um dos Faucets Chainlink, onde você pode obter a rede de teste LINK e ETH. Kovan ou Rinkeby serão ótimas escolhas, então qualquer uma funciona.
Se ainda não o fez, crie um arquivo .env
e, em seguida, adicione seu endpoint ao arquivo .env
. Será algo como:
export ETH_RPC_URL=http://alchemy.io/adfsasdfasdf
Criar um remetente padrão
Obtenha uma carteira eth se ainda não tiver. Você pode ver instruções mais detalhadas para configurar uma Metamask aqui. Mas, idealmente, você obtém uma Metamask e, em seguida, obtém algum ETH da rede de teste das Faucets Chainlink. Em seguida, mude para a rede de teste com a qual está trabalhando. Sua metamask deve ser algo como:
Uma vez que você tenha uma carteira, defina o endereço dessa carteira como uma variável de ambiente ETH_FROM
.
export ETH_FROM=YOUR_ETH_WALLET_ADDRESS
Além disso, se estiver usando o Kovan, financie sua carteira com ETH da rede de teste.
Adicione sua chave privada
NOTA: RECOMENDO ALTAMENTE O USO DE UMA METAMASK QUE NÃO TENHA DINHEIRO DE VERDADE PARA DESENVOLVIMENTO.
Se você enviar sua chave privada para um repositório público com dinheiro real, as pessoas podem roubar seus fundos.
Portanto, se você acabou de criar sua Metamask e está trabalhando apenas com fundos da rede de teste, está seguro.
O Dapptools vem com uma ferramenta chamada ethsign
, e é aqui que vamos armazenar e criptografar nossa chave. Para adicionar nossa chave privada (necessária para enviar transações) pegue a chave privada da sua carteira e execute:
ethsign import
Em seguida, ele solicitará que você adicione sua chave privada e, em seguida, uma senha para criptografá-la. Isso criptografa sua chave privada em ethsign
. Você precisará da sua senha sempre que quiser enviar uma transação para o futuro. Se você executar o comando ethsign ls
e receber uma resposta como:
0x3DF02ac6fEe39B79654AA81C6573732439e73A81 keystore
Você fez certo.
Atualize seu Makefile
O comando que podemos usar para implantar nossos contratos é dapp create DapptoolsDemo
e depois alguns sinalizadores para adicionar variáveis de ambiente. Para facilitar nossas vidas, podemos adicionar nosso comando de implantação a um Makefile, e apenas dizer ao Makefile para usar nossas variáveis de ambiente.
Adicione o seguinte ao nosso Makefile
-include .env
Implemente o contrato
Em nosso Makefile
, temos um comando chamado deploy
, que será executado dapp create DapptoolsDemo
e incluirá nossas variáveis de ambiente. Para executá-lo, basta executar:
make deploy
E você será solicitado a fornecer sua senha. Uma vez bem-sucedido, ele implantará seu contrato!
criar dapp DapptoolsDemo
++ seth send --create 608060405234801561001057600080fd5b50610158806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c806353a04b0514610030575b600080fd5b61004a60048036038101906100459190610096565b610060565b60405161005791906100d2565b60405180910390f35b600060378260ff161415610077576000905061007c565b600190505b919050565b6000813590506100908161010b565b92915050565b6000602082840312156100ac576100ab610106565b5b60006100ba84828501610081565b91505092915050565b6100cc816100ed565b82525050565b60006020820190506100e760008301846100c3565b92915050565b60008115159050919050565b600060ff82169050919050565b600080fd5b610114816100f9565b811461011f57600080fd5b5056fea264697066735822122004d7143940853a7650f1383002b6ba56991e7a5c7d763e755774a149ca0465e364736f6c63430008060033 'DapptoolsDemo()'
seth-send: warning: `ETH_GAS' não definido; utilizando a quantidade de gás padrão
Senha de conta Ethereum (não refletida): seth-send:
Transação publicada com 376 bytes de calldata.
seth-send: 0xeb871eee1fa31c34583b63002e2b16a0252410b5615623fd254b1f90b67369d4
seth-send: Aguardando o recebimento da transação........
seth-send: Transação incluída no bloco 29253678.
0xC5a62934B912c3B1948Ab0f309e31a9b8Ed08dd1
E você deve ser capaz de ver o endereço final dado no Etherscan.
Interagindo com contratos
Para interagir com contratos implantados, podemos usar seth call
e seth send
. Eles são um pouco diferentes:
-
seth call
: só lerá dados da blockchain. Não vai “gastar” nenhum gás. -
seth send
: Isso enviará uma transação para a blockchain, potencialmente modificará o estado do blockchain e gastará gás.
Para ler dados da blockchain, poderíamos fazer algo como:
ETH_RPC_URL=<YOUR_RPC_URL> seth call <YOUR_DEPLOYED_CONTRACT> "FUNCTION_NAME()" <ARGUMENTS_SEPARATED_BY_SPACE>
Como:
ETH_RPC_URL=<YOUR_RPC_URL> seth call 0x12345 "play(uint8)" 55
Para o qual você terá que 0x0000000000000000000000000000000000000000000000000000000000000000
significa falso, já que essa resposta é igual a 0 e, em
bool`, 0 significa falso.
Para escrever dados na blockchain, poderíamos fazer algo como:
ETH_RPC_URL=<YOUR_RPC_URL> ETH_FROM=<YOUR_FROM_ADDRESS> seth send <YOUR_DEPLOYED_CONTRACT> "FUNCTION_NAME()" <ARGUMENTS_SEPARATED_BY_SPACE>
Não implantamos um contrato que tenha um ótimo exemplo para fazer isso, mas digamos que a função play
foi capaz de modificar o estado da blockchain, que ficaria assim:
ETH_RPC_URL=<YOUR_RPC_URL> ETH_FROM=<YOUR_FROM_ADDRESS> seth send 0x12345 "play(uint8)" 55
Verifique seu contrato no Etherscan
Depois de implantar um contrato no etherscan, você pode verificá-lo:
Obtendo uma chave de API Etherscan.
Em seguida, executando
solidity
ETHERSCAN_API_KEY=<api-key> dapp verify-contract <contract_directory>/<contract>:<contract_name> <contract_address>
Por exemplo:
solidity
ETHERSCAN_API_KEY=123456765 dapp verify-contract ./src/DapptoolsDemo.sol:DapptoolsDemo 0x23456534212536435424
E finalmente
Adicione
cache
ao seu.gitignore
Adicione
update:; dapp update
no topo do seuMakefile
. Isso atualizará e baixará os arquivos em.gitmodules
elib
quando você executar omake
.Adicione uma
LICENSE
. Você pode simplesmente copiar uma do nosso repositório se não souber como!
E pronto!
Recursos
Se você gostou, considere doar!
Endereço da carteira ETH: 0x9680201d9c93d65a3603d2088d125e955c73BD65
Este artigo foi escrito por Patrick Collins. A versão original pode ser encontrada aqui. Traduzido e adaptado por Marcelo Panegali.
Latest comments (0)