WEB3DEV

Cover image for Escreva um Contrato Inteligente com o ChatGPT, MetaMask, Infura e o Truffle
Panegali
Panegali

Posted on

Escreva um Contrato Inteligente com o ChatGPT, MetaMask, Infura e o Truffle

Vamos colocar o ChatGPT em um teste Web3. Podemos criar um contrato que esteja pronto para a rede principal?

Imagem gerada por The Digital Artist no Pixabay

Você provavelmente já ouviu falar que a IA generativa tem demonstrado o potencial de interromper muitos setores e empregos - e a Web3 não é exceção. Mas até que ponto o ChatGPT pode criar contratos inteligentes? O uso do ChatGPT para codificar contratos inteligentes pode torná-lo um desenvolvedor 10x melhor?

Neste artigo, vamos testá-lo e verificar. Vamos escrever e implantar um contrato inteligente da Ethereum usando a MetaMask, Infura e o Truffle… e pedir instruções ao ChatGPT sobre tudo, desde o código até a implantação.

O objetivo é ver se podemos dividir a tarefa de criar um contrato inteligente em um conjunto de prompts simples. O ideal é que o ChatGPT possa analisar esses prompts e fornecer respostas boas (e precisas) a eles, tornando-nos desenvolvedores mais rápidos e melhores.

Vamos ver o que podemos fazer!

Uma Nota sobre Precisão

O ChatGPT é um Large Language Model (LLM ou Modelo de Linguagem Grande) extremamente eficiente em explicar conceitos da blockchain, fornecer conselhos e até mesmo gerar trechos de código relacionados ao desenvolvimento da Web3. No entanto, lembre-se de que alguns dos códigos ou respostas que ele gera podem estar parcial ou totalmente incorretos. O acesso ao ChatGPT não elimina a necessidade de conhecer os fundamentos do desenvolvimento da blockchain. No entanto, mesmo um iniciante pode usar a inteligência artificial para aumentar drasticamente a produtividade.

O segundo ponto a observar é que a versão pública e gratuita do ChatGPT não está muito ciente dos eventos, atualizações e práticas que surgiram após 2021. Isso pode ser um problema em um campo como o desenvolvimento da Web3, onde tudo está melhorando e mudando em um ritmo vertiginoso. No entanto, é possível obter boas respostas se algo que você está perguntando for fundamental e estável ao longo dos anos (por exemplo, Truffle e Solidity).

Crie um contrato de garantia com o Truffle e o ChatGPT

Para ver o que o ChatGPT pode fazer, pediremos a ele que crie um contrato inteligente de garantia que permita que um comprador e um vendedor troquem dinheiro, e faremos com que o ChatGPT estabeleça um arbitrador para resolver disputas. Vamos ver o que a IA generativa pode fazer!

Etapa 1: Instale a MetaMask

Primeiro, precisamos configurar uma carteira. Usaremos a carteira MetaMask - a opção mais popular da Ethereum - e adicionaremos a rede de teste Sepolia. A MetaMask é segura e fácil de usar.

Você pode baixar a extensão da MetaMask para seu navegador aqui. Depois, basta instalar e configurar a carteira. Você receberá uma "frase secreta" - mantenha-a privada e segura! Nunca guarde em qualquer lugar público.

Nota: Se você precisar de informações básicas ou de uma cartilha sobre a Web3, consulte este artigo anterior que escrevi sobre o aprendizado da Web3/contratos inteligentes/Solidity.

Em seguida, clique na guia "Network" (Rede) no canto superior direito. Clique na opção para mostrar as redes de teste.

Agora você deve ver a rede de teste Sepolia no menu suspenso. Selecione-a.

Etapa 2: Obtenha SepoliaETH

Para implantar e interagir com um contrato inteligente, você precisa de ETH. Como estamos usando a rede de testes Sepolia, precisaremos obter algum ETH de teste da Sepolia. Não se preocupe - é grátis!

Você pode obter SepoliaETH gratuito da torneira lançada recentemente pela Infura aqui. Esta torneira oferece até 0,5 SepoliaETH por dia gratuitamente.

Etapa 3: Instale o Node e o NPM

Para construir um sistema de garantia usando o Truffle, precisaremos do Node e do NPM.

Para verificar se está instalado, execute o seguinte:

$ nó -v
Enter fullscreen mode Exit fullscreen mode

Você deve ver a versão do Node.

Etapa 4: Inscreva-se no Infura

O Infura é um provedor de RPC. Eles fornecem acesso fácil baseado em API a tudo o que precisamos para nos conectar - e trabalhar com - a blockchain Ethereum (e algumas outras).

Inscreva-se para uma conta gratuita aqui. Em seguida, vá para o painel e selecione Create New Key (Criar nova chave).

Escolha Web3 API como a rede e nomeie a nova chave com o nome Escrow (embora você possa nomeá-la como quiser).

Clique em Create (Criar) e o Infura gerará uma chave de API. Essa chave é o que você precisa para acessar seu ponto de extremidade RPC. Para nossos propósitos, queremos o ponto de extremidade Sepolia.

https://sepolia.infura.io/v3/<sua chave de API>

Etapa 5: Crie o projeto Node

Em seguida, devemos criar nosso projeto Node e concluir nossa configuração com todos os pacotes necessários.

$ mkdir escrow && cd escrow
$ npm init -y
Enter fullscreen mode Exit fullscreen mode

Para implantar e testar nosso contrato, usaremos o Truffle. O Truffle é um conjunto de ferramentas que oferece tudo o que você precisa para desenvolver, testar e implantar contratos inteligentes. Vamos instalá-lo:

$ npm install --save truffle
Enter fullscreen mode Exit fullscreen mode

Você pode criar um esqueleto de projeto usando o Truffle executando:

$ npx truffle init
Enter fullscreen mode Exit fullscreen mode

Para verificar se tudo correu bem:

$ npx truffle test
Enter fullscreen mode Exit fullscreen mode

Agora temos o Truffle configurado com sucesso. Em seguida, vamos instalar o pacote de contratos do OpenZeppelin. Este pacote nos dará acesso a mais algumas funcionalidades úteis de que podemos precisar.

$ npm install @openzeppelin/contracts
Enter fullscreen mode Exit fullscreen mode

Estamos quase terminando a configuração! Em seguida, temos que permitir que a MetaMask e o Truffle trabalhem juntos. Precisamos do Truffle para assinar transações, pagar gás, etc. Para isso, usaremos hdwalletprovider. Instale-o:

$ npm install @truffle/hdwallet-provider
Enter fullscreen mode Exit fullscreen mode

E, finalmente, vamos usar dotenvpara manter nossas informações de carteira seguras.

$ npm install dotenv
Enter fullscreen mode Exit fullscreen mode

Etapa 6: Inscreva-se no ChatGPT

Não escreveremos o código do contrato inteligente de garantia do zero. Em vez disso, veremos o que o ChatGPT pode fazer.

Para usar o ChatGPT, inscreva-se em uma conta gratuita na OpenAI.

Depois de se inscrever para uma conta, visite esta página. Você deve ver uma interface parecida com esta:

Etapa 7: Crie o contrato de garantia

Em seguida, faremos com que o ChatGPT crie um contrato de garantia extremamente simples que permite que um comprador e um vendedor troquem uma certa quantia de dinheiro e um árbitro resolva disputas.

Vamos usar o seguinte prompt no ChatGPT.

Como um desenvolvedor especializado em contratos inteligentes, crie um contrato inteligente usando o Solidity, que implemente um depósito de garantia.

Haverá três partes: o comprador, o vendedor e o árbitro.

O construtor definirá o comprador, o vendedor e o árbitro. Ele também definirá o valor que será igual à quantia enviada ao construtor.

Haverá duas funções.

A primeira função permite que o comprador ou o árbitro libere fundos para o vendedor.

A segunda função permite que o comprador ou o árbitro devolva o valor ao comprador.

Implemente quaisquer outras funções que você considere relevantes.

Observe o início do prompt “Como um desenvolvedor especializado em contratos inteligentes”. Este tipo de “interpretação de papéis” com o ChatGPT funciona muito bem.

Agora, o ChatGPT irá gerar uma resposta única para você. E essa resposta mudará sempre. Você pode não obter a mesma saída mostrada abaixo, mas deve ser algo semelhante.

Claro, aqui está um exemplo de implementação de um contrato inteligente de garantia no Solidity:

pragma solidity ^0.8.0;

contract Escrow {
   address payable public buyer;
   address payable public seller;
   address public arbiter;
   uint public value;
   bool public released;
   bool public refunded;

   constructor(address payable _buyer, address payable _seller, address _arbiter) {
       buyer = _buyer;
       seller = _seller;
       arbiter = _arbiter;
       value = msg.value;
   }

   function release() public {
       require(!released, "Fundos já foram liberados.");
       require(msg.sender == buyer || msg.sender == arbiter, "Somente o comprador ou árbitro pode liberar fundos.");
       released = true;
       seller.transfer(value);
   }

   function refund() public {
       require(!refunded, "Os fundos já foram reembolsados.");
       require(msg.sender == buyer || msg.sender == arbiter, "Somente o comprador ou o árbitro pode reembolsar fundos.");
       refunded = true;
       buyer.transfer(value);
   }

   function getBalance() public view returns (uint) {
       return address(this).balance;
   }

   function setArbiter(address _arbiter) public {
       require(msg.sender == arbiter, "Somente o árbitro pode definir o árbitro.");
       arbiter = _arbiter;
   }

   function setSeller(address payable _seller) public {
       require(msg.sender == seller, "Somente o vendedor pode definir o vendedor.");
       seller = _seller;
   }
}
Enter fullscreen mode Exit fullscreen mode

O contrato Escrow tem um construtor que recebe três argumentos: os endereços do comprador, vendedor e árbitro, e define o value igual ao valor enviado ao construtor.

A função release() permite que o comprador ou o árbitro libere os fundos para o vendedor. Ele primeiro verifica se os fundos ainda não foram liberados e se o chamador é o comprador ou o árbitro. Se ambas as condições forem atendidas, a variável released é definida como true e o value é transferido para o endereço do vendedor.

A função refund() permite que o comprador ou o árbitro reembolse os fundos de volta ao comprador. Ele primeiro verifica se os fundos já não foram reembolsados e se o chamador é o comprador ou o árbitro. Se ambas as condições forem atendidas, a variável refunded é definida como true e o value é transferido de volta para o endereço do comprador.

A função getBalance() retorna o saldo do contrato.

A função setArbiter() permite que o árbitro defina um novo árbitro.

A função setSeller() permite que o vendedor defina um novo vendedor.

Observe que esta é uma implementação muito básica de um contrato de garantia e não deve ser usada na produção sem testes e auditorias completas. Além disso, pode haver recursos adicionais que você deseja adicionar para atender ao seu caso de uso específico.

Após a inspeção, o trecho fornecido pelo ChatGPT é bom! Mas há um erro — o construtor não está marcado payable mesmo que estejamos acessando msg.value e esperando que o Ether seja enviado para ele.

Novamente, uma observação importante: Nunca espere que o ChatGPT forneça um código 100% correto. Na maioria das vezes, você terá que fazer pequenas correções como fizemos aqui.

Além disso, o ChatGPT usa uma versão anterior do Solidity e usa uma prática de transferência de fundos que não é mais considerada a melhor prática. Para este tutorial, vamos deixar assim.

Na pasta de contratos do seu projeto, crie um novo arquivo chamado Escrow.sol e adicione o código fornecido pelo ChatGPT com as correções.

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

contract Escrow {
   address payable public buyer;
   address payable public seller;
   address public arbiter;
   uint public value;
   bool public released;
   bool public refunded;

   constructor(address payable _buyer, address payable _seller, address _arbiter) payable {
       buyer = _buyer;
       seller = _seller;
       arbiter = _arbiter;
       value = msg.value;
   }

   function release() public {
       require(!released, "Os fundos já foram liberados.");
       require(msg.sender == buyer || msg.sender == arbiter, "Somente o comprador ou árbitro pode liberar fundos.");
       released = true;
       seller.transfer(value);
   }

   function refund() public {
       require(!refunded, "Os fundos já foram reembolsados.");
       require(msg.sender == buyer || msg.sender == arbiter, "Somente o comprador ou o árbitro pode reembolsar fundos.");
       refunded = true;
       buyer.transfer(value);
   }

   function getBalance() public view returns (uint) {
       return address(this).balance;
   }

   function setArbiter(address _arbiter) public {
       require(msg.sender == arbiter, "Somente o árbitro pode definir o árbitro.");
       arbiter = _arbiter;
   }

   function setSeller(address payable _seller) public {
       require(msg.sender == seller, "Somente o vendedor pode definir o vendedor.");
       seller = _seller;
   }
}
Enter fullscreen mode Exit fullscreen mode

Verifique se o contrato está sendo compilado corretamente executando o seguinte:

$ npx truffle compile
Enter fullscreen mode Exit fullscreen mode

Etapa 8: Atualize sua configuração no Truffle

A seguir, faremos uma pequena configuração sem o ChatGPT. Esta é uma configuração padrão e dependerá do ambiente que estivermos usando.

Crie um novo arquivo .env no diretório raiz do seu projeto e adicione o seguinte:

INFURA_API_KEY = "https://sepolia.infura.io/v3/<insert API key here>"
MNEMONIC = "<insira a frase secreta da Metamask aqui>"
Enter fullscreen mode Exit fullscreen mode

Agora, vamos configurar o ponto de extremidade do Infura. Em truffle.config.js substitua o código existente por esta configuração padrão:

require('dotenv').config();
const HDWalletProvider = require('@truffle/hdwallet-provider');
const {INFURA_API_KEY, MNEMONIC} = process.env;

module.exports = {
   networks: {
     development: {
       host: "127.0.0.1",
       port: 8545,
       network_id: "*"
     },
     sepolia: {
       provider: () => new HDWalletProvider(MNEMONIC, INFURA_API_KEY),
       network_id: '11155111',
     }
   }
};
Enter fullscreen mode Exit fullscreen mode

Etapa 9: Implante o contrato

Agora, é hora de implantar! Em vez de fornecer o script para implantar nosso contrato usando o Truffle, vamos pedir ao ChatGPT as instruções relevantes.

Na mesma janela que você usou para pedir o código do contrato de garantia, digitaremos o seguinte prompt:

Forneça um script de migração que implemente o contrato Escrow usando o Truffle.

Preciso enviar 0,001 ETH para o construtor durante a implementação. E preciso que o endereço que implementa o contrato seja o comprador.

Obtemos esta resposta:

Claro, aqui está um exemplo de script de migração que implementa o contrato Escrow e envia 0,001 ETH para o construtor durante a implementação. Nesse script, o endereço que implementa o contrato será definido como o comprador.

  1. Crie um novo arquivo JavaScript chamado 2_deploy_escrow.js (o número no início indica a ordem em que as migrações serão executadas).
  2. Copie o código a seguir em 2_deploy_escrow.js:
const Escrow = artifacts.require("Escrow");

module.exports = async function(deployer, network, accounts) {
 const buyer = accounts[0]; // definir o comprador como o endereço que implementa o contrato
 const seller = "0x2222222222222222222222222222222222222222"; // substituir pelo endereço do vendedor
 const arbiter = "0x3333333333333333333333333333333333333333"; // substituir pelo endereço do árbitro
 const value = web3.utils.toWei('0.001', 'ether'); // altere para o valor que você deseja enviar

 await deployer.deploy(Escrow, seller, arbiter, { from: buyer, value: value });
};
Enter fullscreen mode Exit fullscreen mode
  1. Substitua os endereços do vendedor e do árbitro pelos endereços reais da Ethereum das partes envolvidas na transação de garantia.
  2. Salve o arquivo.
  3. Certifique-se de ter uma rede configurada em seu arquivo truffle-config.js. Se quiser implantar em uma rede de teste, você precisará configurar o projeto Truffle para usar a rede na qual deseja implantar.
  4. Execute truffle migrate --network <network-name> para implantar o contrato na rede especificada. Substitua <network-name> pelo nome da rede na qual você deseja implantar, por exemplo, ropsten para a rede de teste Ropsten. Isso implementará o contrato e enviará 0,001 ETH para o construtor com o endereço que implementa o contrato definido como o comprador.

Mais uma vez, as instruções fornecidas pelo ChatGPT estão corretas em sua maioria. A nomenclatura está errada (queremos que seja prefixado com 1_ e não 2_) e precisa ser corrigido na definição dos argumentos da função deploy.

Vamos criar um novo arquivo 1_deploy_contract.js na pasta migrations. Adicione o seguinte código ligeiramente modificado.

const Escrow = artifacts.require("Escrow");

module.exports = async function (deployer, network, accounts) {
   const buyer = accounts[0]; // definir o comprador como o endereço que implementa o contrato
   const seller = accounts[1]; // substituir pelo endereço do vendedor
   const arbiter = accounts[2]; // substituir pelo endereço do árbitro
   const value = web3.utils.toWei('0.001', 'ether'); // alterar para o valor que você deseja enviar

   await deployer.deploy(Escrow, seller, arbiter, { from: buyer, value: value });
};
Enter fullscreen mode Exit fullscreen mode

E por fim, vamos implantar nosso contrato:

$ truffle migrate --network sepolia
Enter fullscreen mode Exit fullscreen mode

Você deve ver algo semelhante a isto:

Compiling your contracts...
===========================
> Everything is up to date, there is nothing to compile.


Migrations dry-run (simulation)
===============================
> Network name:    'sepolia-fork'
> Network id:      11155111
> Block gas limit: 30000000 (0x1c9c380)


1_deploy_contract.js
====================

  Deploying 'Escrow'
  ------------------
  > block number:        3400252
  > block timestamp:     1682974543
  > account:             0xc361Fc33b99F88612257ac8cC2d852A5CEe0E217
  > balance:             0.506876109994053108
  > gas used:            849556 (0xcf694)
  > gas price:           2.500000007 gwei
  > value sent:          0.001 ETH
  > total cost:          0.003123890005946892 ETH

  -------------------------------------
  > Total cost:     0.003123890005946892 ETH

Summary
=======
> Total deployments:   1
> Final cost:          0.003123890005946892 ETH




Starting migrations...
======================
> Network name:    'sepolia'
> Network id:      11155111
> Block gas limit: 30000000 (0x1c9c380)


1_deploy_contract.js
====================

  Deploying 'Escrow'
  ------------------
  > transaction hash:    0x7a7804d92a6b6e805991eeb8249d79a2b8c5da43cffe633a31f987e9fe596654
  > Blocks: 1            Seconds: 33
  > contract address:    0x64ccE52898F5d61380D2Ec8C02F2EF16F28436de
  > block number:        3400258
  > block timestamp:     1682974584
  > account:             0xc361Fc33b99F88612257ac8cC2d852A5CEe0E217
  > balance:             0.506876109994053108
  > gas used:            849556 (0xcf694)
  > gas price:           2.500000007 gwei
  > value sent:          0.001 ETH
  > total cost:          0.003123890005946892 ETH

  > Saving artifacts
  -------------------------------------
  > Total cost:     0.003123890005946892 ETH

Summary
=======
> Total deployments:   1
> Final cost:          0.003123890005946892 ETH
Enter fullscreen mode Exit fullscreen mode

Para validar a implantação, você pode encontrar o endereço do seu contrato no Sepolia Etherscan:

Parabéns! Você implantou seu contrato. E você fez isso usando o ChatGPT para gerar mais de 95% do seu código.

Dicas e truques

Aqui estão algumas dicas e truques para usar o ChatGPT ao codificar:

  • O ChatGPT tem conhecimento limitado e tem um limite de base de conhecimento em setembro de 2021. Portanto, algumas dessas práticas recomendadas e os desenvolvimentos mais recentes em contratos inteligentes devem ser adicionados ao seu conhecimento.
  • Existem várias versões do ChatGPT. GPT-4 tende a dar melhores respostas, mas é um serviço pago. O GPT-3.5 (que usamos aqui) é gratuito e funciona bem.
  • Faça suas perguntas da forma mais específica possível.
  • Não pare de escrever código. O ChatGTP pode depurar seu código, auditá-lo, documentá-lo, torná-lo bonito, analisá-lo, encontrar vulnerabilidades e muito mais.

Conclusão

O ChatGPT foi um co-desenvolvedor extremamente útil, mas não foi perfeito. Eu não o usaria para criar um código não modificado que eu enviasse para a rede principal - especialmente se eu fosse um novo desenvolvedor. Mas, como parceiro de codificação e como ponto de partida, ele foi útil. Isso me economizou um tempo significativo e criou um código surpreendentemente bom. Nas mãos de um desenvolvedor experiente, acredito que pode aumentar a produtividade em muitas vezes. Pretendo fortemente usá-lo em projetos futuros, juntamente com a MetaMask, Infura e o Truffle.

Tenha um ótimo dia!


Artigo escrito por John Vester. Traduzido por Panegali

Top comments (0)