Deploy: subindo um contrato inteligente para a blockchain

Lucas Vieira
12 min readJul 28, 2022

--

No nosso último artigo adicionamos a funcionalidade de negociação de tokens (trading) no nosso contrato inteligente de tokens fungíveis. Permitindo que os proprietários dos tokens possam emitir ordens de venda dos seus ativos com o preço que quiserem e que outros usuários possam comprar tokens dessas ordens emitidas. Criando assim um mercado público de compra e venda de tokens e regulando o preço do mesmo com base na oferta e demanda do próprio mercado regulado pelos proprietários. Além da funcionalidade de staking que criamos nesse outro artigo, que permite com que os proprietários aloquem seus tokens em tokens em staking e ganhem recompensas por isso (podemos pensar como uma poupança), temos também as funcionalidades de transferência e permissão de gestão oriundas do protocolo ERC-20 além da possibilidade de emitir novos tokens ou destruir tokens existentes. Olhando para o que é possível fazer com esse contrato inteligente, temos muitas funções que hoje são realizadas na sociedade por diversos bancos só que de maneira descentralizada e aberta.

Nesse artigo vamos demonstrar passo a passo o processo de deploy desse nosso contrato para a blockchain. Subindo ele para uma rede de testes real, a Rinkeby. O processo é praticamente o mesmo se quisermos subir o nosso contrato para a Ethereum Mainnet, sua rede principal, ou até para um rede Layer 2 (uma blockchain separada que extende uma blockchain de Layer 1, usando suas funcionalidades e a tornando mais escalável) que estenda a Ethereum e use o compilador da EVM, como a Polygon. Vamos também validar o nosso contrato na Etherscan para que seja possível visualizar seu código por lá. E finalmente criaremos scripts usando o Hardhat Tasks para interagir com nosso contrato deployado e faremos juntos uma análise dessas transações no Etherscan, o explorador de blocos que iremos utilizar. Sem mais delongas, vamos botar a mão na massa!

I. Configuração

Para começar esse projeto vamos usar o código que foi desenvolvido no nosso último artigo e você pode encontrar ele nesse repositório. Vamos precisar de uma carteira para fazer o deploy do nosso contrato, nesse projeto vamos usar o Metamask. Sugiro instalar a extensão para o navegador para facilitar. Eu uso o Brave como navegador mas também é possível fazer a instalação da extensão em outros navegadores. Para usar a rede Rinkeby na sua carteira precisamos habilitar o uso das redes de teste nela. Ao clicar no ícone da extensão do Metamask clicamos também no seletor de redes onde por padrão está com a Ethereum Mainnet selecionada.

Clicamos no botão para exibir ou esconder as redes de teste.

Depois clicamos no switch para permitir a exibição das redes de teste na listagem.

Agora é possível ver outras redes no seletor, inclusive a rede Rinkeby na qual vamos usar.

Eu recomendo agora, caso você já tenha uma carteira instalada, criar uma conta separada que vamos usar nesse projeto. Nos projetos reais eu costumo criar um novo perfil no meu navegador para o projeto e nele instalar a extensão do metamask e criar uma carteira específica para esse projeto em questão. No processo de desenvolvimento do dia a dia vamos precisar de múltiplas contas na nossa carteira para simular o comportamento do nosso contrato ou dApp com diferentes usuários, nomeando cada conta de maneira clara para diferenciar cada um deles como: "Creator", "Stakeholder", "Owner", "Whitelist User", "Normal User",… ou o que se encaixar melhor no caso do seu projeto. Então clicamos no ícone de perfil redondo que fica ao lado do seletor de redes. E clicamos na opção de criar nova conta.

Damos um nome para essa conta e pronto!

Temos agora uma carteira e uma conta para usar no nosso processo de deploy.

Cada conta que criarmos na nossa carteira vai ter uma chave pública e uma chave privada únicas. A chave pública é usada para que outras contas e contratos possam identificá-la e a chave privada é usada para confirmar a sua identidade nas transações. A chave pública é o identificador hexadecimal que aparece em baixo do nome da conta e podemos copiá-la clicando no ícone ao seu lado. Vamos precisar da chave privada para incluí-la no arquivo e configuração do nosso código e assim conseguirmos fazer o deploy do nosso contrato através dela. Para pegá-la precisamos clicar no ícone com três pontos que fica à direita do nome da conta e abaixo do ícone redondo de perfil da conta.

Selecionamos a opção de detalhes da conta. Vai aparecer um modal com o QR code para compartilhar sua conta, seu endereço público, um botão para visualizar a conta no Etherscan e outro para exportar a chave privada em que vamos clicar.

O Metamask vai pedir a sua senha senha e após inseri-la ele exibe a sua chave privada. Copie esse valor e lembre-se: não compartilhe sua chave privada com ninguém. Não importa qual seja a história triste.

Nesse projeto estamos usando a biblioteca dotenv para lidarmos com as variáveis de ambiente. Podemos instala-la usando o comando:

npm install dotenv --save

E assim podemos criar um arquivo .env no nosso diretório principal do projeto e incluir a chave privada que acabamos de copiar.

OWNER_PRIVATE_KEY="coloque-sua-chave-privada-aqui"

E poderemos então a referenciar no restante do código do projeto usando

require('dotenv').config();process.env.OWNER_PRIVATE_KEY

Como vamos usar uma rede de testes real precisamos ter fundos da moeda dessa rede na nossa carteira para poder custear os gastos com gás no deploy e nas demais interações com o contrato. Note que o processo é exatamente o mesmo que na rede principal do Ethereum mas para evitarmos o gasto com ETH de verdade nos testes do nosso projeto fazemos primeiro o deploy numa rede de testes, no caso a Rinkeby, e usamos o que chamamos de Test ETH que podemos conseguir usando alguns dos Faucets da rede que vamos utilizar. Abaixo alguns links de faucets que podemos utilizar:

Cada faucet vai ter suas particularidades de uso e suas limitações de pedidos, mas após repetir o processo algumas vezes já temos o suficiente para poder seguir adiante.

Pronto, agora já temos nossa carteira e conta configuradas como precisamos. Agora vamos precisar de um nó de blockchain na rede Rinkeby para fazermos o deploy. De maneira simplista podemos pensar nisso como uma AWS (ou outro cloud provider) da Web3. Nesse projeto vamos usar o Alchemy. Primeiro vamos criar uma conta por lá, o plano gratuito ja vai ser mais que suficiente para usarmos no projeto. Depois de criada a conta vamos então criar um app para o nosso projeto no dashboard do Alchemy.

Clicamos no botão de criar app no canto inferior direito da imagem e um modal vai surgir para incluirmos os detalhes.

Selecionamos a rede Rinkeby e podemos criar nosso app e ele vai aparecer na listagem de apps no dashboard. Clicando nele podemos ver uma página com detalhes de todas interações feitas com ele através do nosso nó.

Vamos precisar da chave do nosso app para usá-lo no deploy do nosso contrato, para isso vamos clicar no botão de visualizar chave no canto superior direito. Um modal com três chaves vai aparecer, vamos copiar a chave HTTPS e inseri-la no nosso arquivo .env.

OWNER_PRIVATE_KEY="coloque-sua-chave-privada-aqui"
RINKEBY_URL="sua-chave-https-aqui"

Vamos precisar também criar uma conta no Etherscan para usar a API deles no processo de verificação do contrato. Podemos criar uma nova conta no seguinte link. Após criar a conta vamos criar uma nova chave de API. No menu lateral à esquerda clicamos no botão de chaves de API.

Clicamos no botão no canto direito para adicionar uma nova chave.

Incluímos o nome da nossa chave

e depois de criada copiamos o seu valor para usá-la no nosso código.

OWNER_PRIVATE_KEY="coloque-sua-chave-privada-aqui"
RINKEBY_URL="sua-chave-https-aqui"
ETHERSCAN_API_KEY="sua-chave-api-etherscan-aqui"

Se estivermos usando a API do CoinMarketCap para ter estimativas reais dos gastos precisamos incluir também a chave de API deles no nosso arquivo de variáveis de ambiente.

OWNER_PRIVATE_KEY="coloque-sua-chave-privada-aqui"
RINKEBY_URL="sua-chave-https-aqui"
ETHERSCAN_API_KEY="sua-chave-api-etherscan-aqui"
COINMARKETCAP_API_KEY="sua-chave-api-coinmarketcap-aqui"

Se já não estiver instalado, instalamos a biblioteca hardhat-etherscan.

npm install @nomiclabs/hardhat-etherscan

Nesse artigo temos mais detalhes do processo de criação da conta no CoinMarketCap.

Nosso arquivo de configuração deve estar igual ao arquivo abaixo.

Note que temos o objeto networks no objeto que exportamos. Dentro deles listamos cada uma das redes que temos configuradas e com isso podemos usar o seguinte parâmetro nos comandos:

npx hardhat deploy --network rinkeby

E note também que além da url do nosso nó de blockchain, temos um array com as contas que podemos usar. Nas tasks do hardhat podemos acessar essas contas usando

const [deployer] = await hre.ethers.getSigners();

Sempre por padrão a conta usada nas interações com o contrato é a primeira conta definida no nosso array do arquivo de configuração, mas podemos definir múltiplas contas nesse array e usá-las usando a função connect nas interações.

II. Deploy

Agora vamos começar fazer os preparativos para o deploy do nosso contrato. Vamos primeiro ajustar o nosso contrato principal, vamos ajustar o nome dele para PiggyBank.sol.

Aqui apenas mudamos o nome do contrato que desenvolvemos. Agora vamos ajustar o script de deploy em scripts/deploy.js.

Antes de rodar o deploy, vamos rodar o comando de testes mais uma vez para garantir que todos estão passando corretamente (é sempre importante fazer isso antes de um deploy).

npx hardhat test

Lembre-se de ajustar o passo de deploy em todos os arquivos de testes para apontar para o novo nome que definimos para o nosso contrato.

contractFactory = await ethers.getContractFactory("PiggyBank");token = await contractFactory.deploy(5000000, "PiggyBank", "PIG", 18);

E podemos ver que todos os testes passam corretamente.

Agora que checamos que esta tudo certo, vamos rodar o nosso comando de deploy!

npx hardhat deploy --network rinkeby

E podemos ver que o deploy foi feito corretamente no endereço 0x92734D58b1CDAFed6E90bB8BD3027afd270911D5 🥳

Para visualizar nosso contrato vamos usar o explorador de blocos do Etherscan na Rinkeby. Colocamos o endereço do contrato que subimos no campo de busca.

E podemos acessar os detalhes e a transações do nosso contrato através do link.

Agora vamos verificar o nosso contrato usando o seguinte comando:

npx hardhat verify 0x92734D58b1CDAFed6E90bB8BD3027afd270911D5 5000000 PiggyBank PIG 18 --network rinkeby

Podemos ver que o nosso contrato foi verificado corretamente! 🥳

Agora podemos acessar o código do nosso contrato com o link exibido no terminal.

Nosso contrato está armazenado e verificado na blockchain através da rede Rinkeby. E agora podemos interagir com ele usando o seu endereço! :)

III. Interação

Agora vamos começar os scripts para interagirmos com o nosso contrato que subimos na rede Rinkeby. Para isso vamos usar, semelhantemente ao nosso arquivo de deploy, as tasks do hardhat para criar os scripts. Primeiro vamos criar um script para poder fazer transferências de tokens então criamos o arquivo scripts/transfer.js.

Note como adicionamos 4 parâmetros posicionais nessa task. Para usá-los nós passamos cada um deles após o comando pelo terminal e usamos a ordem deles para definirmos qual é qual. Então junto com o comando deveremos passar o endereço do contrato que acabamos de subir, o endereço da conta de quem vai receber os tokens transferidos, o total de tokens a serem transferidos e o id da conta que vai transferir que, no caso, é a posição da conta no array de de contas do arquivo de configuração do hardhat. Por padrão, caso o parâmetro não seja passado, usamos o id 0 referente a conta que usamos para fazer o deploy do contrato. Para usar o script precisamos importá-lo no nosso arquivo de configuração do hardhat.

require("./scripts/transfer.js");

Antes de rodar o comando para transferir os tokens, vamos criar uma nova conta na nossa carteira para recebê-los.

Copiamos o endereço dessa conta criada e executamos a transferência com o seguinte comando:

npx hardhat transfer 0x92734D58b1CDAFed6E90bB8BD3027afd270911D5 0x4aee60Ab97D690880661f9e7b8a1381209eaB9a1 10000 0 --network rinkeby

E podemos ver os detalhes da transação no terminal.

Vamos agora criar um novo script para executar mais uma das funcionalidades do contrato e para certificarmos que a última transferência ocorreu corretamente. Então criamos o arquivo scripts/stake.js para executarmos a função de staking do contrato.

Agora precisamos importar a nova task no nosso arquivo de configuração incluindo:

require("./scripts/stake.js");

Para executarmos a função como a nova conta que criamos vamos também precisar incluir sua chave privada no código. Fazemos o mesmo processo que foi detalhado acima e incluímos a seguinte linha no arquivo de variáveis de ambiente.

USER1_PRIVATE_KEY="sua-outra-chave-privada"

E também incluímos essa variável no arquivo de configuração.

networks: {
rinkeby: {
url: process.env.RINKEBY_URL,
accounts: [process.env.OWNER_PRIVATE_KEY, process.env.USER1_PRIVATE_KEY]
}

Não se esqueça de transferir fake ETH para a nova conta para conseguir custear o gasto com gás. Agora podemos fazer o staking com o seguinte comando:

npx hardhat stake 0x92734D58b1CDAFed6E90bB8BD3027afd270911D5 5000 1 --network rinkeby

E podemos ver que o stake foi feito corretamente e os detalhes da transação são exibidos no terminal.

Com esse stake a conta do user 1 deverá ter agora 5k tokens. Vamos fazer um teste tentando transferir um número maior que esse para a conta do dono do contrato usando o seguinte comando:

npx hardhat transfer 0x92734D58b1CDAFed6E90bB8BD3027afd270911D5 0x180CA611606f804c61122f2F8A05F55deD0C372D 10000 1 --network rinkeby

E podemos ver que um erro é retornado como esperado!

E dessa forma podemos usar as tasks do hardhat para interagir com o contrato que subimos para a rede Rinkeby. Olhando o nosso contrato na Etherscan da rede Rinkeby podemos ver as transações referentes as últimas tasks que rodamos.

Clicando em uma delas podemos ver os detalhes da transação.

Podemos também fazer tasks para executar funções de leitura que retornam valores do contrato na blockchain. Então vamos criar um arquivo scripts/balance.js e importá-lo no nosso arquivo de configuração.

E podemos usar a task usando o seguinte comando:

npx hardhat balance 0x92734D58b1CDAFed6E90bB8BD3027afd270911D5 0x4aee60Ab97D690880661f9e7b8a1381209eaB9a1 --network rinkeby

Agora eu desafio você leitor a fazer outras tasks para executar as demais funcionalidades do contrato! O código completo do projeto com todas as tasks desenvolvidas pode ser encontrado aqui no meu Github.

No próximo artigo vamos desenvolver um frontend para interagirmos com esse mesmo contrato. Então se quiser acompanhar não se esquece de me seguir aqui no Medium :)

--

--

Lucas Vieira

Hi! I'm a brazilian software engineer who love to learn and build new things. My goal here is to share I little about that on the way :) https://bushi.solutions