Core Contracts

Contratos Centrais do Wormhole

Os Contratos Centrais do Wormhole, implantados em cada rede blockchain suportada, possibilitam as operações fundamentais de envio e recebimento de mensagens cross-chain.

Embora os detalhes de implementação dos Contratos Centrais variem conforme a rede, a funcionalidade central permanece consistente entre as blockchains. Cada versão do Contrato Central facilita a comunicação cross-chain de forma segura e confiável, garantindo que os desenvolvedores possam publicar e verificar mensagens de maneira eficaz.

Este guia explicará as variações e métodos chave dos Contratos Centrais, fornecendo o conhecimento necessário para integrá-los aos seus contratos cross-chain. Para obter mais informações sobre as funcionalidades dos Contratos Centrais e como eles funcionam, consulte a página de Contratos Centrais na seção Learn.

Pré-requisitos

Para interagir com o Contrato Central do Wormhole, você precisará de:

  • O endereço do Contrato Central nas blockchains nas quais você está implantando seu contrato.

  • O ID da cadeia do Wormhole das blockchains onde você está implantando seu contrato.

  • Os níveis de consistência (finalidade necessária) das blockchains nas quais você está implantando seu contrato.

Como Interagir com os Contratos Centrais

Antes de escrever seus próprios contratos, é essencial entender as funções e eventos principais dos Contratos Centrais do Wormhole. A funcionalidade principal gira em torno de:

  • Envio de mensagens - Submissão de mensagens à rede Wormhole para comunicação cross-chain.

  • Recebimento e verificação de mensagens - Validação das mensagens recebidas de outras blockchains via a rede Wormhole.

Embora os detalhes de implementação dos Contratos Centrais variem de rede para rede, a funcionalidade central é consistente.

Envio de Mensagens

Para enviar uma mensagem, independentemente do ambiente ou da blockchain, o Contrato Central é invocado com um argumento de mensagem de um emissor. Esse emissor pode ser seu contrato ou uma aplicação existente, como o Token Bridge.

EVM Solana

A interface IWormhole.sol fornece a função publishMessage, que pode ser usada para publicar uma mensagem diretamente no Contrato Central:

function publishMessage(
    uint32 nonce,
    bytes memory payload,
    uint8 consistencyLevel
) external payable returns (uint64 sequence);

Parâmetros

  • nonce uint32: Um campo inteiro livre que pode ser utilizado como desejar. Observe que alterar o nonce resultará em um digest diferente.

  • payload bytes memory: O conteúdo da mensagem emitida. Devido às limitações de cada blockchain, pode haver um limite máximo de tamanho.

  • consistencyLevel uint8: Um valor que define o nível de finalização necessário que deve ser atingido antes que os Guardiões observem e atestem os eventos emitidos.

Retorno

  • sequence uint64: Um número único que incrementa a cada mensagem de um determinado emissor (e implicitamente, da blockchain). Isso, combinado com o endereço do emissor e o ID da cadeia do emissor, permite que o VAA para essa mensagem seja consultado na API Wormholescan.

Exemplo

IWormhole wormhole = IWormhole(wormholeAddr);

// Obtenha a taxa para publicar uma mensagem
uint256 wormholeFee = wormhole.messageFee();

// Verifique a taxa e envie os parâmetros

// Crie a estrutura HelloWorldMessage
HelloWorldMessage memory parsedMessage = HelloWorldMessage({
    payloadID: uint8(1),
    message: helloWorldMessage
});

// Codifique a estrutura HelloWorldMessage em bytes
bytes memory encodedMessage = encodeMessage(parsedMessage);

// Envie a mensagem HelloWorld chamando publishMessage no
// contrato central do wormhole e pagando a taxa do protocolo Wormhole.
messageSequence = wormhole.publishMessage{value: wormholeFee}(
    0, // batchID
    encodedMessage,
    wormholeFinality()
);

Após a emissão da mensagem pelo Contrato Central, a Rede de Guardiões observará a mensagem e assinará o digest de uma Attestation VAA. Nas blockchains EVM, o corpo do VAA é hashado duas vezes com keccak256 para gerar a mensagem de digest assinada. No Solana, o programa Solana secp256k1 fará o hash da mensagem passada. Nesse caso, o argumento para a mensagem deve ser um único hash do corpo, não o corpo hashado duas vezes.

Os VAAs são multicast por padrão. Isso significa que não há uma cadeia de destino padrão para uma mensagem específica. O desenvolvedor da aplicação decide o formato da mensagem e seu tratamento ao ser recebida.

Recebendo Mensagens

A maneira como uma mensagem é recebida e tratada depende do ambiente.

EVM Solana

Nas blockchains EVM, a mensagem passada é o VAA bruto codificado como binário. A interface IWormhole.sol fornece a função parseAndVerifyVM, que pode ser usada para analisar e verificar a mensagem recebida:

function parseAndVerifyVM(
    bytes calldata encodedVM
) external view returns (VM memory vm, bool valid, string memory reason);

Parâmetros

  • encodedVM bytes calldata: A mensagem codificada como Verified Action Approval (VAA), que contém todas as informações necessárias para verificação e processamento.

Retornos

  • vm VM memory: O VAA analisado e válido, que incluirá o endereço original do emissor, número de sequência e nível de consistência, entre outros campos descritos na página dos VAAs.

  • valid bool: Um booleano indicando se o VAA é válido ou não.

  • reason string: Se o VAA não for válido, uma razão será fornecida.

Exemplo

function receiveMessage(bytes memory encodedMessage) public {
    // Chame o contrato central do Wormhole para analisar e verificar a mensagem codificada
    (
        IWormhole.VM memory wormholeMessage,
        bool valid,
        string memory reason
    ) = wormhole().parseAndVerifyVM(encodedMessage);

    // Realize verificações de segurança aqui

    // Decodifique a carga útil da mensagem na estrutura HelloWorldMessage
    HelloWorldMessage memory parsedMessage = decodeMessage(
        wormholeMessage.payload
    );

    // Sua lógica personalizada de aplicação aqui
}

Validando o Emissor

Ao processar mensagens cross-chain, é crucial garantir que a mensagem tenha origem de um remetente (emissor) confiável. Isso pode ser feito verificando o endereço do emissor e o ID da cadeia no VAA analisado.

Normalmente, os contratos devem fornecer um método para registrar emissores confiáveis e verificar mensagens recebidas contra essa lista antes de processá-las. Por exemplo, a seguinte verificação garante que o emissor esteja registrado e autorizado:

require(isRegisteredSender(emitterChainId, emitterAddress), "Invalid emitter");

Essa verificação pode ser aplicada após o VAA ser analisado, garantindo que apenas emissores autorizados possam interagir com o contrato receptor. Emissores confiáveis podem ser registrados usando um método como setRegisteredSender durante a implantação ou inicialização do contrato.

Verificações Adicionais

Além das verificações específicas de ambiente, um contrato deve verificar outros campos no corpo da mensagem, incluindo:

  • Sequência: Esse é o número de sequência esperado? Como as entregas fora de ordem devem ser tratadas?

  • Nível de consistência: Para a cadeia de onde a mensagem veio, o nível de consistência é suficiente para garantir que a transação não será revertida após a ação ser tomada?

O digest do VAA é separado do corpo do VAA, mas também é relevante. Ele pode ser usado para proteção contra repetição verificando se o digest já foi visto. Como a carga útil em si é específica da aplicação, pode haver outros elementos a serem verificados para garantir a segurança.

Referências de Código Fonte

Para um entendimento mais profundo da implementação do Contrato Central para um ambiente blockchain específico e para revisar o código fonte real, consulte os seguintes links:

Last updated