Criação de contratos de transferência de tokens Cross-Chain

Neste parte, você aprenderá a criar um sistema simples de transferência de tokens cross-chain utilizando o protocolo Wormhole através do Wormhole Solidity SDK. Vamos guiá-la na construção e implantação de smart contracts que permitem transferências fluidas de tokens compatíveis com IERC-20 entre blockchains. Seja você uma desenvolvedora interessada em explorar aplicações cross-chain ou simplesmente curiosa sobre o protocolo Wormhole, este guia ajudará a compreender os fundamentos.

Ao final deste tutorial, você terá um sistema funcional de transferência de tokens cross-chain construído com as ferramentas poderosas fornecidas pelo Wormhole Solidity SDK, que poderá personalizar e integrar aos seus projetos.

Pré-requisitos

Antes de começar, certifique-se de ter o seguinte:

  • Node.js e npm instalados em sua máquina

  • Foundry para implantar contratos

  • Tokens de teste para Avalanche-Fuji e Celo-Alfajores para cobrir taxas de gas

  • Tokens USDC de teste no Avalanche-Fuji e/ou Celo-Alfajores para transferência cross-chain

  • Chave privada de uma wallet

Tokens Válidos para Transferência

É importante notar que este tutorial utiliza o TokenBridge da Wormhole para transferir tokens entre as blockchains. Assim, os tokens que você deseja transferir devem possuir uma attestation no contrato TokenBridge da blockchain de destino.

Para simplificar este processo, incluímos uma ferramenta para verificar se um token possui uma attestation na chain de destino. Esta ferramenta utiliza a função wrappedAsset do contrato TokenBridge. Se o token possuir uma attestation, a função wrappedAsset retorna o endereço do token "empacotado" na blockchain de destino; caso contrário, retorna o endereço zero.

Teste os tokens Válidos

  1. Clone o repositório e navegue até o diretório do projeto

git clone https://github.com/wormhole-foundation/demo-cross-chain-token-transfer.git
cd cross-chain-token-transfers
  1. Instale as dependências:

  1. Execute o script para verificar a attestation do token:

  1. Siga as instruções:

  • Insira a URL RPC da blockchain de destino

  • Insira o endereço do contrato TokenBridge na blockchain de destino

  • Insira o endereço do contrato do token na blockchain de origem

  • Insira o ID da blockchain de origem

  1. A saída esperada quando o token tem uma atestação:

Usar esta ferramenta garante que você só tente transferir tokens com atestados verificados, evitando possíveis problemas durante o processo de transferência entre cadeias.

Configuração do Projeto

Vamos começar inicializando um novo projeto Foundry. Isso configurará uma estrutura básica para nossos contratos inteligentes.

  1. Abra o terminal e execute o seguinte comando para inicializar um novo projeto com o Foundry:

Isso criará um novo diretório chamado cross-chain-token-transfers com uma estrutura básica de projeto e também inicializará um repositório Git.

  1. Acesse o diretório recém-criado:

  1. Instale o Wormhole Solidity SDK:

Para facilitar o desenvolvimento, utilizaremos o Wormhole Solidity SDK, que oferece ferramentas úteis para desenvolvimento cross-chain. Este SDK inclui as classes abstratas TokenSender e TokenReceiver, que simplificam o envio e o recebimento de tokens entre blockchains.

Construir Contratos Cross-Chain

Nesta seção, construiremos dois contratos inteligentes para enviar tokens de uma cadeia de origem e recebê-los em uma cadeia de destino. Esses contratos irão interagir com o protocolo Wormhole para facilitar transferências de tokens cross-chain de forma segura e eficiente.

De forma geral, nossos contratos irão:

  1. Enviar tokens de uma blockchain para outra utilizando o protocolo Wormhole.

  2. Receber e processar os tokens na cadeia de destino, garantindo que sejam transferidos corretamente para o destinatário previsto.

Antes de implementar os contratos, vamos detalhar os principais componentes.

Contrato de Envio: CrossChainSender

O contrato CrossChainSender é responsável por calcular o custo de envio de tokens entre cadeias e facilitar a transferência dos tokens.

Passo inicial para escrever o contrato CrossChainSender:

  1. Crie um novo arquivo chamado CrossChainSender.sol no diretório /src:

  1. Abra o arquivo. Primeiro, começaremos com as importações e a configuração do contrato:

Isso configura a estrutura básica do contrato, incluindo os imports necessários e o construtor, que inicializa o contrato com os endereços relacionados ao Wormhole.

  1. Agora, vamos adicionar uma função que estima o custo de envio de tokens entre blockchains:

Essa função, quoteCrossChainDeposit, auxilia no cálculo do custo de transferência de tokens para outra blockchain. Ela considera o custo de entrega e o custo de publicação de uma mensagem utilizando o protocolo Wormhole.

  1. Por fim, adicionaremos a função que envia os tokens através das cadeias:

A função sendCrossChainDeposit é o núcleo do processo de transferência de tokens entre blockchains. Ela utiliza o protocolo Wormhole para enviar tokens ao destinatário na cadeia-alvo. Aqui está uma explicação detalhada das etapas envolvidas:

1. Cálculo do custo

  • A função inicia calculando o custo da transferência entre blockchains usando quoteCrossChainDeposit(targetChain).

  • Esse custo inclui a taxa de entrega e a taxa de publicação da mensagem no protocolo Wormhole.

  • Em seguida, a função verifica se o usuário enviou a quantidade correta de Ether para cobrir o custo, utilizando msg.value.

2. Transferência de tokens para o contrato

  • A próxima etapa transfere a quantidade especificada de tokens do usuário para o próprio contrato.

  • Isso é feito com IERC-20(token).transferFrom(msg.sender, address(this), amount).

  • Essa transferência garante que o contrato detenha os tokens antes de iniciar a transferência cross-chain.

3. Codificação do payload

  • O endereço do destinatário na cadeia-alvo é codificado em um payload usando abi.encode(recipient).

  • Esse payload acompanha a transferência dos tokens, permitindo que o contrato de destino saiba quem deve receber os tokens na cadeia de destino.

4. Transferência cross-chain

  • A função sendTokenWithPayloadToEvm é chamada para iniciar a transferência cross-chain. Ela:

    • Especifica a targetChain, que é o ID da cadeia Wormhole da blockchain de destino.

    • Envia o endereço do contrato targetReceiver na cadeia-alvo que receberá os tokens.

    • Anexa o payload contendo o endereço do destinatário.

    • Define o GAS_LIMITpara a transação.

    • Passa o endereço do token e a quantidade a ser transferida.

Essa chamada ativa o protocolo Wormhole para lidar com a mensagem cross-chain e a transferência de tokens, garantindo que os tokens e o payload cheguem ao destino correto na cadeia-alvo.

Código completo

O código completo para o arquivo CrossChainSender.sol está disponível e contém todas essas etapas implementadas detalhadamente.

Contrato Receptor: CrossChainReceiver

O contrato CrossChainReceiver é projetado para lidar com o recebimento de tokens e payloads de outra blockchain. Ele garante que os tokens sejam transferidos corretamente para o destinatário designado na cadeia de recebimento.

Vamos começar a escrever o contrato CrossChainReceiver:

Crie um novo arquivo chamado CrossChainReceiver.sol no diretório /src:

Abra o arquivo. Primeiro, começaremos com os imports e a configuração do contrato:

Semelhante ao contrato CrossChainSender, isso configura a estrutura básica do contrato, incluindo os imports necessários e o construtor que inicializa o contrato com os endereços relacionados ao Wormhole.

Em seguida, vamos adicionar uma função para lidar com o recebimento da payload e dos tokens:

A função receivePayloadAndTokens processa os tokens e a payload enviados de outra cadeia, decodifica o endereço do destinatário e transfere os tokens para ele usando o protocolo Wormhole. Esta função também valida o emissor (sourceAddress) para garantir que a mensagem veio de um remetente confiável.

Essa função garante que:

  • Apenas uma transferência de token é processada por vez.

  • O sourceAddress é verificado em uma lista de remetentes registrados usando o modificador isRegisteredSender, que confirma se o emissor tem permissão para enviar tokens para este contrato.

  • O endereço do destinatário é decodificado da payload, e os tokens recebidos são transferidos para ele utilizando a interface ERC-20.

Após chamarmos sendTokenWithPayloadToEvm na cadeia de origem, a mensagem passa pelo ciclo de vida padrão da mensagem Wormhole. Quando um VAA (Verifiable Action Approval) estiver disponível, o provedor de entrega chamará receivePayloadAndTokens na cadeia de destino e no endereço de destino especificado, com os parâmetros apropriados.

Início da implementação

Para começar a implementar o CrossChainReceiver, siga os passos abaixo:

  1. Criação do arquivo do contrato:

    • Crie um novo arquivo chamado CrossChainReceiver.sol no diretório /src do projeto

  • Estrutura inicial do contrato:

    • O contrato incluirá as seguintes partes:

      • Importações necessárias do Wormhole Solidity SDK.

      • Declaração do contrato e configuração inicial.

  • Definição inicial do contrato:

    • Aqui está a estrutura básica:

  • Descrição do código:

    • O contrato implementa a interface IWormholeReceiver para garantir compatibilidade com o protocolo Wormhole.

    • A variável tokenAddress armazena o endereço do token suportado pelo contrato.

    • O construtor inicializa o contrato com o endereço do token.

Próximos passos

Com a estrutura básica definida, podemos avançar para implementar as funções principais, como:

  • Processar mensagens recebidas do protocolo Wormhole.

  • Transferir tokens para o destinatário correto na cadeia receptora.

Entendendo a Tokenreceived Struct

Vamos detalhar os campos fornecidos na estrutura TokenReceived:

  1. tokenHomeAddress – o endereço original do token na sua cadeia nativa. Este é o mesmo endereço do token utilizado na chamada para sendTokenWithPayloadToEvm, a menos que o token enviado originalmente seja um token embalado no Wormhole. Nesse caso, este será o endereço da versão original do token (na sua cadeia nativa) no formato de endereço do Wormhole (com 12 zeros à esquerda).

  2. tokenHomeChain – o ID da cadeia do Wormhole correspondente ao endereço original acima. Normalmente, isso será a cadeia de origem, a menos que o token original enviado seja um ativo embalado no Wormhole, caso em que o ID da cadeia será o da versão desembrulhada do token.

  3. tokenAddress – o endereço do token IERC-20 na cadeia de destino que foi transferido para este contrato. Se tokenHomeChain for igual à cadeia de destino, este valor será o mesmo que o tokenHomeAddress; caso contrário, será a versão embalado no Wormhole do token enviado.

  4. amount – a quantidade de tokens enviada para este contrato, com as mesmas unidades do token original. Como o TokenBridge envia com precisão de oito casas decimais, se o token tiver 18 casas decimais, esse valor será a quantidade enviada, arredondada para o múltiplo mais próximo de 10^10.

  5. amountNormalized – a quantidade de tokens dividida por (1 se o número de casas decimais for ≤ 8, caso contrário, 10^(decimais - 8)).

Você pode encontrar o código completo para o contrato CrossChainReceiver.sol abaixo:

CrossChainReceiver.sol

Implantação dos Contratos

Agora que você escreveu os contratos CrossChainSender e CrossChainReceiver, é hora de implantá-los nas redes escolhidas.

Configuração da Implantação

Antes de realizar a implantação, você precisa configurar as redes e o ambiente de implantação. Essas informações serão armazenadas em um arquivo de configuração.

  1. Crie um diretório chamado deploy-config no diretório raiz do seu projeto:

  1. Crie um arquivo config.json no diretório deploy-config:

  1. Abra o arquivo config.json e adicione a seguinte configuração:

Este arquivo especifica os detalhes de cada cadeia onde você planeja implantar seus contratos, incluindo a URL RPC, o endereço do TokenBridge, o Wormhole relayer, e o Wormhole Core Contract.

  • Nota: Você pode adicionar as cadeias desejadas a este arquivo, especificando os campos necessários para cada uma. Neste exemplo, usamos as testnets Avalanche Fuji e Celo Alfajores.

  1. Crie um arquivo contracts.json no diretório deploy-config:

Este arquivo pode ser deixado em branco inicialmente. Ele será atualizado automaticamente com os endereços dos contratos implantados após uma implantação bem-sucedida.

Configuração do Ambiente Node.js

Você precisará configurar o ambiente Node.js para executar o script de implantação.

  1. Inicialize um projeto Node.js:

  1. Instale as dependências necessárias:

Essas dependências são necessárias para o correto funcionamento do script de implantação.

Compile seus Contratos Inteligentes

Compile seus contratos usando Foundry. Isso garante que seus contratos estejam atualizados e prontos para a implantação.

  1. Execute o seguinte comando para compilar seus contratos:

Isso gerará os arquivos necessários ABI e bytecode em um diretório chamado /out.

Escreva o Script de Implantação

Você precisará de um script para automatizar a implantação de seus contratos. Vamos criar o script de implantação.

  1. Crie um novo arquivo chamado deploy.ts no diretório /script:

  1. Abra o arquivo e carregue as importações e a configuração:

Aqui, estamos importando as bibliotecas necessárias para interagir com o Ethereum, manipular caminhos de arquivos, carregar variáveis de ambiente e permitir interação com o usuário via terminal.

  1. Defina as interfaces para a configuração da cadeia e implantação do contrato:

Essas interfaces definem a estrutura da configuração da cadeia e os detalhes da implantação do contrato.

  1. Carregue e selecione as cadeias para a implantação:

A função loadConfig lê a configuração da cadeia a partir do arquivo config.json, e a função selectChain permite ao usuário escolher as cadeias de origem e destino para a implantação interativamente.

  1. Defina a função principal para a implantação e carregue a configuração da cadeia:

  1. Configure o provedor e a carteira:

Os scripts estabelecem uma conexão com a blockchain usando um provedor e criam uma instância de carteira usando uma chave privada. Esta carteira será responsável por assinar a transação de implantação na cadeia de origem.

  1. Leia os contratos compilados:

  1. Extraia o ABI e o bytecode do contrato:

  1. Crie a Fábrica de Contratos:

  1. Implante os contratos CrossChainSender e CrossChainReceiver:

Ambas as funções fazem o deploy dos respectivos contratos nas blockchains selecionadas.

Para o contrato CrossChainReceiver:

  • Define a carteira relacionada à blockchain de destino.

  • A lógica lê o ABI compilado e o bytecode a partir do arquivo JSON gerado durante a compilação.

  • Cria uma nova fábrica de contrato usando o ABI, bytecode e a carteira.

  • Realiza o deploy do contrato na blockchain selecionada, passando os endereços do Wormhole Relayer, TokenBridge e Wormhole.

  1. Salve os endereços dos contratos implantados.

Você pode exibir os endereços dos contratos implantados no terminal ou salvá-los em um arquivo JSON para referência futura.

Registrar o endereço do CrossChainSender na blockchain de destino:

Após implantar o contrato CrossChainReceiver na rede de destino, o endereço do contrato do remetente da cadeia de origem precisa ser registrado. Isso garante que apenas mensagens do contrato CrossChainSender registrado sejam processadas.

Este passo adicional é essencial para aplicar a validação do emissor, impedindo que remetentes não autorizados entreguem mensagens ao contrato CrossChainReceiver.

  1. Salvar os detalhes do deploy:

Exemplo de Salvamento dos Detalhes de Implantação:

Esta função salva os detalhes de implantação, registrando as informações sobre o contrato implantado, incluindo os endereços do CrossChainSender e CrossChainReceiver, e atualiza o arquivo contracts.json com os dados mais recentes. Se o contrato já existir na rede, ele será atualizado, caso contrário, uma nova entrada será adicionada.

Adicione sua lógica desejada para salvar os endereços dos contratos implantados em um arquivo JSON (ou outro formato). Isso será importante mais tarde ao transferir tokens, pois você precisará desses endereços para interagir com os contratos implantados.

  1. Trate erros e finalize o script:

A estrutura try-catch envolve a lógica de implantação para capturar quaisquer erros que possam ocorrer.

  • Se o erro for devido a fundos insuficientes, ele registra uma mensagem clara sobre a necessidade de mais taxas de gas.

  • Para outros erros, registra a mensagem de erro específica para ajudar no processo de depuração.

  • O process.exit(1) garante que o script seja finalizado com um código de status de falha caso ocorra algum erro.

Você pode encontrar o código completo do arquivo deploy.ts abaixo:

  1. Adicione sua chave privada - você precisará fornecer sua chave privada. Ela permite que o seu script de implantação assine as transações que implantam os contratos inteligentes na blockchain. Sem ela, o script não será capaz de interagir com a blockchain em seu nome.

    Crie um arquivo .env na raiz do projeto e adicione sua chave privada:

    Dentro do arquivo .env, adicione sua chave privada no seguinte formato:

  2. Execute o script de implantação

I - Abra um terminal e execute o seguinte comando:

Isso executará o script de implantação, implantando ambos os contratos nas cadeias selecionadas.

II - Verifique a saída da implantação:

Você verá os endereços dos contratos implantados impressos no terminal, caso tenha sido bem-sucedido. O arquivo contracts.json será atualizado com esses endereços.

Se você encontrar um erro, o script fornecerá um feedback, como fundos insuficientes para pagar o gas.

Se você seguiu a lógica fornecida no código completo acima, a saída do seu terminal deve ser algo assim:

Transferir Tokens Entre Cadeias

Resumo Rápido Até este ponto, você configurou um novo projeto Solidity usando o Foundry, desenvolveu dois contratos principais (CrossChainSender e CrossChainReceiver) e criou um script de implantação para implantar esses contratos em diferentes redes blockchain. O script de implantação também salva os endereços dos contratos para fácil referência. Com tudo pronto, agora é hora de transferir tokens usando os contratos implantados.

Neste passo, você escreverá um script para transferir tokens entre cadeias utilizando os contratos CrossChainSender e CrossChainReceiver que você implantou anteriormente. Este script irá interagir com os contratos e facilitar a transferência de tokens entre cadeias.

Script de Transferência

Configuração do Script de Transferência

Crie um novo arquivo chamado transfer.ts no diretório /script:

Abra o arquivo. Comece com as importações necessárias, interfaces e configurações:

Essas importações incluem as bibliotecas essenciais para interagir com o Ethereum, manipular caminhos de arquivos, carregar variáveis de ambiente e gerenciar entradas do usuário.

Carregar Configuração e Contratos:

Essas funções carregam os detalhes da rede e dos contratos que foram salvos durante a implantação.

Permitir que os usuários selecionem as cadeias de origem e destino:

Considere os contratos implantados e crie a lógica conforme necessário. No nosso exemplo, tornamos esse processo interativo, permitindo que os usuários selecionem as cadeias de origem e destino entre todos os contratos implantados historicamente. Essa abordagem interativa ajuda a garantir que as cadeias corretas sejam selecionadas para a transferência de tokens.

Implementar a Lógica de Transferência de Tokens

Inicie a função principal:

A função principal é onde a lógica de transferência de tokens residirá. Ela carrega os detalhes da cadeia e dos contratos, configura a carteira e o provedor, e carrega o contrato CrossChainSender.

Solicitar os Detalhes da Transferência de Tokens ao Usuário:

Agora, você pedirá ao usuário o endereço do contrato do token, o endereço do destinatário na cadeia de destino e a quantidade de tokens a transferir.

Esta seção do script solicita ao usuário o endereço do contrato do token e o endereço do destinatário, obtém o valor decimal do token e analisa a quantidade de acordo.

Iniciar a Transferência:

Finalmente, inicie a transferência entre as cadeias e registre os detalhes.

Esta parte do script primeiro aprova a transferência de tokens, depois inicia a transferência entre as cadeias usando o contrato CrossChainSender e finalmente registra o hash da transação para o usuário acompanhar.

Finalizar o Script:

Esta seção finaliza o script chamando a função principal e tratando quaisquer erros que possam ocorrer durante o processo de transferência de tokens.

Você pode encontrar o código completo para o arquivo transfer.ts abaixo:

Transferir Tokens

Agora que seu script de transferência está pronto, é hora de executá-lo e realizar a transferência de tokens entre cadeias.

Executar o script de transferência

Abra o terminal e execute o script de transferência:

Este comando iniciará o script, solicitando que você selecione as cadeias de origem e destino, insira o endereço do token, o endereço do destinatário e a quantidade de tokens a ser transferida.

Siga as instruções - o script irá guiá-lo na seleção das cadeias de origem e destino e na inserção dos detalhes necessários para a transferência de tokens. Assim que você fornecer todas as informações requeridas, o script iniciará a transferência dos tokens.

Verifique a transação - após executar o script, você verá uma mensagem de confirmação com o hash da transação. Você pode usar esse hash de transação para verificar o status da transferência nos exploradores de blockchain respectivos.

Você pode verificar a transação no Wormhole Explorer usando o link fornecido na saída do terminal. Este explorador também oferece a opção de adicionar o token transferido automaticamente à sua carteira MetaMask.

Se você seguiu a lógica fornecida no arquivo transfer.ts acima, a saída do seu terminal deve ser algo assim:

Recursos

Se você quiser explorar o projeto completo ou precisar de uma referência enquanto segue este tutorial, pode encontrar o código completo no repositório do GitHub de Transferências de Tokens Cross-Chainarrow-up-right. O repositório inclui todos os scripts, contratos e configurações necessários para implantar e transferir tokens entre cadeias usando o protocolo Wormhole.

Conclusão

Parabéns! Você construiu e implantou com sucesso um sistema de transferência de tokens entre cadeias usando Solidity e o protocolo Wormhole. Você aprendeu como:

  • Configurar um novo projeto Solidity usando o Foundry

  • Desenvolver contratos inteligentes para enviar e receber tokens entre cadeias

  • Escrever scripts de implantação para gerenciar e implantar contratos em diferentes redes

Last updated