WEB3DEV

Cover image for Como chamar um contrato inteligente de outro contrato inteligente (Parte 2/3)
Fatima Lima
Fatima Lima

Posted on

Como chamar um contrato inteligente de outro contrato inteligente (Parte 2/3)

É hora de atualizar nossas habilidades aprendendo tudo sobre Chamadas entre Contratos. Aqui está a Parte 2 da série de tutoriais trazida a você pelo Laika, o Request Builder para Web3.

Image description

Conforme exploramos na primeira parte desta série, é possível a interação entre os contratos inteligentes, de modo que uma interação em um contrato inteligente possa afetar outro contrato inteligente. Se você perdeu a primeira parte, aqui está o link útil: https://www.web3dev.com.br/fatimalima/como-chamar-um-contrato-inteligente-a-partir-de-outro-contrato-inteligente-parte-13-3bfn

Certifique-se de ter configurado seu espaço de trabalho Laika antes de continuar. Consulte nossos documentos aqui.
https://docs.getlaika.app/fundamentals/create-a-new-request

Nesta parte desta série de artigos, exploraremos a chamada de funções no Solidity. Portanto, prepare seu IDE Remix (ou qualquer outro IDE de sua preferência) e vamos lá!

Passo 1 — Usando o Contrato de Exemplo em Tempo Real

A beleza de todo esse sistema é que podemos considerar e usar qualquer contrato inteligente e habilitar chamadas em um contrato separado, tudo usando seu endereço de contrato implantado (o único fator aqui é que você precisa saber especificamente qual método chamar, ou seja, a ABI - Application Binary Interface deve ser conhecida). Podemos simplesmente criar um contrato de chamada para chamada(s) específica(s) usando os métodos diretamente na instância do contrato que é criado.

Nesta parte da série de tutoriais, consideraremos o uso do seguinte contrato. Você já deve ter ouvido falar do Protocolo UMA, talvez até o tenha usado!

Consideraremos especificamente o Oracle Optimistic (OO) do UMA e exploraremos a "integração OO mínima viável" oficial. O mesmo contrato pode ser encontrado em seu link de documentação oficial aqui: https://docs.umaproject.org/developers/getting-started

Passo 2 — Analisando o Contrato

O contrato abaixo é fornecido oficialmente pelo Protocolo UMA, no momento da redação deste artigo.

// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity ^0.8.14;

import "https://github.com/UMAprotocol/protocol/blob/master/packages/core/contracts/optimistic-oracle/interfaces/OptimisticOracleV2Interface.sol";
// *************************************
// *   Integração Mínima Viável do OO   *
// *************************************

// Este contrato mostra como começar a trabalhar o mais rápido possível com o Oracle Optimistic do UMA.
// Fazemos uma solicitação de preço simples para o OO e a retornamos para o usuário.

contract OO_GettingStarted {


   // Crie uma instância do Oracle Optimistic no endereço implementado na rede Görli.
   OptimisticOracleV2Interface oo = OptimisticOracleV2Interface(0xA5B9d8a0B0Fa04Ba71BDD68069661ED5C0848884);

   // Use o identificador yes no (sim não) para fazer perguntas arbitrárias, como o clima em um determinado dia.
   bytes32 identifier = bytes32("YES_OR_NO_QUERY");

   // Publique a pergunta em dados auxiliares. Observe que essa é uma forma simplificada de dados auxiliares para servir de exemplo. Um mercado 
  // de produção do mundo real usaria algo um pouco mais complexo e precisaria estar em conformidade com uma estrutura mais robusta.
   bytes ancillaryData =
       bytes("Q:Did the temperature on the 25th of July 2022 in Manhattan NY exceed 35c? A:1 for yes. 0 for no.");

   uint256 requestTime = 0; // Armazene a hora da solicitação para usarmos novamente mais tarde.

   // Envie uma solicitação de dados para o Oracle Optimistic.
   function requestData() public {
       requestTime = block.timestamp; // Defina a hora da solicitação como a hora do bloco atual.
       IERC20 bondCurrency = IERC20(0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6); // Use o WETH Görli como moeda de bônus.
       uint256 reward = 0; // Defina a recompensa como 0 (para não precisarmos financiá-la com esse contrato)).

       // Agora, faça a solicitação de preço para o Oracle Optimistic e defina a liveness como 30 para que ela seja liquidada rapidamente.
       oo.requestPrice(identifier, requestTime, ancillaryData, bondCurrency, reward);
       oo.setCustomLiveness(identifier, requestTime, ancillaryData, 30);
   }

   // Liquide a solicitação depois que ela tiver passado pelo período de atividade de 30 segundos. Isso faz com que o preço votado seja finalizado.
   // No mundo real, o uso do Oracle Optimistic deve ser mais longo para dar tempo aos competidores de pegarem as propostas de preço de BAT (Basic Attention Token).
   function settleRequest() public {
       oo.settle(address(this), identifier, requestTime, ancillaryData);
   }

   // Obtenha o preço resolvido do Oracle Optimistic que foi liquidado.
   function getSettledData() public view returns (int256) {
       return oo.getRequest(address(this), identifier, requestTime, ancillaryData).resolvedPrice;
   }
}
Enter fullscreen mode Exit fullscreen mode

Em vez de seguir o caminho tradicional de escrever nosso contrato inteligente e interagir com outro contrato auto-escrito, entenderemos um contrato pré-escrito e exploraremos novas metodologias.

Neste contrato, podemos ver alguns aspectos importantes:

  1. A criação da instância OO dentro do contrato é mostrada assim:
// Crie uma instância do Oracle Optimistic no endereço implantado na rede Görli.
   OptimisticOracleV2Interface oo = OptimisticOracleV2Interface(0xA5B9d8a0B0Fa04Ba71BDD68069661ED5C0848884);
Enter fullscreen mode Exit fullscreen mode

Esse é o método mais comum de instanciar um contrato implantado existente dentro do contrato de chamada de que você precisa.

  1. A ABI está sendo fornecida diretamente pela importação do arquivo de código do contrato (https://github.com/UMAprotocol/protocol/blob/master/packages/core/contracts/oracle/interfaces/OptimisticOracleV2Interface.sol. Isso é importante para fazer com que o contrato herde as variáveis e funções do contrato de Interface, que será usado posteriormente.

  2. Podemos ver o uso de variáveis especialmente declaradas, como o identifier que deve ser o "YES_OR_NO_QUERY" neste exemplo específico (elas foram predefinidas para uso específico no ecossistema UMA).

//Use o identificador yes no para fazer perguntas arbitrárias, como o clima em um determinado dia.
   bytes32 identifier = bytes32("YES_OR_NO_QUERY");
Enter fullscreen mode Exit fullscreen mode
  1. Lidaremos com a solicitação de dados do Oracle, que já está predefinida no mesmo contrato para nossa conveniência.
// Envie uma solicitação de dados para o Oracle Optimistic.
   function requestData() public {
       requestTime = block.timestamp; // Defina a hora da solicitação como a hora do bloco atual.
       IERC20 bondCurrency = IERC20(0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6); // Use WETH Görli como moeda de bônus.
       uint256 reward = 0; // Defina a recompensa como 0 (para não precisarmos financiá-la com esse contrato).

       // Agora, faça a solicitação de preço para o Oracle Optimistic e defina a liveness (tempo em que o sistema se mantém funcionando e atualizado em tempo real) como 30 para que ela seja liquidada rapidamente.
       oo.requestPrice(identifier, requestTime, ancillaryData, bondCurrency, reward);
       oo.setCustomLiveness(identifier, requestTime, ancillaryData, 30);
   }
Enter fullscreen mode Exit fullscreen mode

Alguns aspectos importantes a serem observados aqui são: \
a) Estamos definindo IERC20 bondCurrency = IERC20(…)usando o endereço (0xB4FBF271143F4FBf7B91A5ded31805e42b2208d6) que é o endereço implantado na Goerli ETH. Esse é o bondCurrency solicitado pelo sistema Oracle para solicitar dados.

b) Estamos chamando as funções corretas (conforme herdadas pela interface importada), fazendo a solicitação de preço com os parâmetros necessários aqui.

//Faça a solicitação de preço para o Oracle Optimistic e defina a liveness como 30, para que a liquidação seja rápida.
       oo.requestPrice(identifier, requestTime, ancillaryData, bondCurrency, reward);
       oo.setCustomLiveness(identifier, requestTime, ancillaryData, 30);
Enter fullscreen mode Exit fullscreen mode

Portanto, você pode ver como podemos configurar chamadas para outro contrato pré-implantado, certificando-nos de que os aspectos mencionados acima devam ser cumpridos.

Observação: Se não tivermos o código-fonte do contrato em mãos, precisaremos definir nossa própria interface no mesmo contrato. Além disso, é importante ter em mente os parâmetros exigidos no contrato original, sem os quais nossos esforços falhariam.

Passo 3 — Implantando o contrato de chamada

Agora que entendemos como será o nosso contrato e como ele funciona, tudo o que precisamos fazer é compilá-lo e implantá-lo na rede certa. Lembre-se de que aqui estamos lidando com a testnet (rede de teste) Goerli ETH!

Conforme explicado na Parte 1 desta série, tudo o que você precisa fazer é ir até a guia Compile (Compilar) e, uma vez feito isso, ir até a guia Deploy and Run (Implantar e Executar) e conectar seu provedor injetado (ou seja, a carteira Metamask) em seu IDE Remix. Certifique-se de que sua carteira Metamask esteja configurada na rede Goerli ETH neste momento.

>>>>> gd2md-html alert: inline image link here (to images/image2.png). Store image on your image server and adjust path/filename/extension if necessary.
(Back to top)(Next alert)
>>>>>

alt_text

Detalhes da Testnet Goerli ETH

Caso não tenha a rede habilitada em sua carteira, você pode usar os detalhes fornecidos acima para adicioná-la.

Agora, basta clicar em Deploy e aguardar a conclusão do processo. (É claro que você precisará de um pouco de ETH da Goerli nesse momento)

Passo 4 — Finalmente, Laika!

Agora que implantamos nosso contrato e temos seu endereço, podemos simplesmente importá-lo para nosso espaço de trabalho do Laika!

\
_Nosso endereço de contrato: 0xe06cF07b37c80555B8191e70DD73E4B05d5E6E8F \
_(você pode usar nosso contrato implantado e concluir o experimento).

Lembre-se de que primeiro precisamos ir para https://web.getlaika.app e clique em [New Request].

>>>>> gd2md-html alert: inline image link here (to images/image3.png). Store image on your image server and adjust path/filename/extension if necessary.
(Back to top)(Next alert)
>>>>>

alt_text

Clique em “ABI” para copiar a ABI

Você precisará da ABI do contrato antes de poder criar a coleção. Clique em copiar a ABI e cole-a no modal New Request.

>>>>> gd2md-html alert: inline image link here (to images/image4.png). Store image on your image server and adjust path/filename/extension if necessary.
(Back to top)(Next alert)
>>>>>

alt_text

Cole o endereço do contrato implantado e a ABI e clique em [Import]

[
{
 "inputs": [],
 "name": "requestData",
 "outputs": [],
 "stateMutability": "nonpayable",
 "type": "function"
},
{
 "inputs": [],
 "name": "settleRequest",
 "outputs": [],
 "stateMutability": "nonpayable",
 "type": "function"
},
{
 "inputs": [],
 "name": "getSettledData",
 "outputs": [
  {
   "internalType": "int256",
   "name": "",
   "type": "int256"
  }
 ],
 "stateMutability": "view",
 "type": "function"
}
]
Enter fullscreen mode Exit fullscreen mode

Acima está o ABI json com o qual estamos trabalhando aqui.

>>>>> gd2md-html alert: inline image link here (to images/image5.png). Store image on your image server and adjust path/filename/extension if necessary.
(Back to top)(Next alert)
>>>>>

alt_text

Espaço de Trabalho Laika com a coleção de solicitações importada

Se todas as etapas tiverem sido seguidas corretamente até este ponto, você poderá ver as três solicitações criadas na coleção de solicitações New Contract. Agora, tudo o que você precisa fazer é clicar em [Send] para chamar a função.

Vamos tentar clicar em write requestData. Observe que essa é uma função Write (de gravação), portanto, precisaremos assinar uma transação em nossa carteira conectada e passar a transação on-chain.

>>>>> gd2md-html alert: inline image link here (to images/image6.png). Store image on your image server and adjust path/filename/extension if necessary.
(Back to top)(Next alert)
>>>>>

alt_text

Resposta bruta recebida da chamada requestData

{
 "to": "0xe06cF07b37c80555B8191e70DD73E4B05d5E6E8F",
 "from": "0x5568416Fc7E9D575277c78a4f8272e873839f001",
 "contractAddress": null,
 "transactionIndex": 19,
 "gasUsed": "177419",
 "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200100080000000000000000000000000000000002000040000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000004000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
 "blockHash": "0x4dbce8ac0273efa1cae57469703ddae367172efa8c5f03a0895e42360e1f870e",
 "transactionHash": "0xfe89d049503ef921c2581a6887b66aa6cd451e02d60f6932423393244473af6d",
 "logs": [
   {
     "transactionIndex": 19,
     "blockNumber": 8339720,
     "transactionHash": "0xfe89d049503ef921c2581a6887b66aa6cd451e02d60f6932423393244473af6d",
     "address": "0xA5B9d8a0B0Fa04Ba71BDD68069661ED5C0848884",
     "topics": [
       "0xf1679315ff325c257a944e0ca1bfe7b26616039e9511f9610d4ba3eca851027b",
       "0x000000000000000000000000e06cf07b37c80555b8191e70dd73e4b05d5e6e8f"
     ],
     "data": "0x5945535f4f525f4e4f5f515545525900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000063c9843000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000b4fbf271143f4fbf7b91a5ded31805e42b2208d6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061513a446964207468652074656d7065726174757265206f6e207468652032357468206f66204a756c79203230323220696e204d616e68617474616e204e5920657863656564203335633f20413a3120666f72207965732e203020666f72206e6f2e00000000000000000000000000000000000000000000000000000000000000",
     "logIndex": 65,
     "blockHash": "0x4dbce8ac0273efa1cae57469703ddae367172efa8c5f03a0895e42360e1f870e"
   }
 ],
 "blockNumber": 8339720,
 "confirmations": 2,
 "cumulativeGasUsed": "5442917",
 "effectiveGasPrice": "2678517203",
 "status": 1,
 "type": 2,
 "byzantium": true
}
Enter fullscreen mode Exit fullscreen mode

Portanto, estamos basicamente solicitando dados do Oracle Optimistic do UMA implantados ao vivo e servindo a seu propósito na blockchain. Você está convidado a se aprofundar no ecossistema UMA para entender melhor o que está acontecendo aqui.

Você sempre poderá usar o Laika para ajudá-lo em sua jornada de desenvolvedor.

E é isso! Laika é a sua interface de usuário completa baseada em ABI para interação de contratos em muitas, se não em todas, as redes EVM! Mais redes serão adicionadas em breve, portanto, fique de olho! Compartilhe suas experiências de uso do Laika conosco em nossas redes sociais.

Adios por enquanto e até breve!

🐶❤💛

Conecte-se conosco

Facebook: https://www.facebook.com/getlaikaapp/ \
Discord: https://discord.gg/4DzwHuxhcf \
Website: https://getlaika.app

Mais referências (em inglês):

  1. Introdução Geral aos Contratos Inteligentes da Fundação Ethereum
  2. Documentação Laika
  3. Github UMA
  4. UMA DocumentUMA Githubation

Esse artigo foi escrito por Ishan Pandey e traduzido por Fátima Lima. O original pode ser lido aqui.

Latest comments (0)