Back to Blog

Protegendo o Ecossistema Solana (2) — Chamadas Entre Programas

18 de março de 2022
6 min read

0. Revisão

1. Visão Geral

No blog anterior, apresentamos como implantar e interagir com o programa. Além de invocar as instruções de um programa pelo lado do cliente, o Solana também permite que programas se chamem mutuamente por meio de um mecanismo chamado invocação entre programas. Nesta publicação, ilustramos como a invocação entre programas é utilizada. O código de teste está aqui.

2. Invocação Entre Programas

A invocação entre programas geralmente é implementada com a função invoke. Nesta seção, ilustramos o uso de invoke transferindo lamports dentro de um programa.

No Solana, existe um programa nativo chamado System Program que desempenha um papel na criação de novas contas e na transferência de lamports (SOL). Neste caso, para transferir lamports dentro de um programa (por exemplo, Programa A), o programa A invocará a função transfer() no System Program. Vamos analisar o exemplo concreto abaixo.

2.1 Revisão do Código

Da linha 3 à linha 10, as bibliotecas necessárias são importadas. Observe que a função invoke() está na biblioteca solana_program::program.

Na função process_instruction, da linha 22 à linha 30, as três contas passadas pelo cliente são extraídas. Observe que os lamports serão transferidos de from_account para to_account. Da linha 33 à linha 44, a função invoke() é invocada. Ela recebe dois argumentos. O primeiro é a instrução alvo invocada e o segundo é um conjunto de contas. Neste exemplo, a instrução alvo é transfer(), que é usada para transferir lamports. As contas incluem todas as contas exigidas pela instrução sendo invocada. Neste caso, from_account e to_account.

O programa implantado pode ser encontrado no seguinte link.

https://explorer.solana.com/address/EPaLuYQ4c11BJAe9ucLbta3xGFb17Zy3cZh3UDPbXRG9?cluster=devnet

2.2 Transferindo os Lamports

Como mencionado, enviamos a transação para o programa implantado. O programa implantado invocará o System Program para transferir os lamports para o endereço de destino. O código acima mostra como o cliente constrói as transações. Da linha 93 à linha 101, o programId do programa implantado é extraído. Da linha 103 à linha 109, os endereços do remetente, destinatário e do System Program são gerados. Da linha 111 à linha 117, a transação é construída. Na linha 118, a transação é enviada ao cluster Solana. Observe que o único assinante nesta transação é o remetente, definido na linha 112. O remetente deve autorizar (ou seja, assinar) a transação que retira dinheiro de sua conta, e o destinatário não precisa fazê-lo (linha 113).

A transação pode ser encontrada no seguinte link.

https://explorer.solana.com/tx/4cxqnff8SakVcE9y5phmh6utcbBUGaLDPvqMRgSy9aPGdNVH6DCsQyJXCCzRGvW5CpygUi5pqhgBQxczXnWCoqPJ?cluster=devnet

3. Invoke ou Invoke_signed

No Solana, os programas podem gerar contas em tempo de execução, chamadas de Endereços Derivados de Programa (PDA). Se a instrução alvo invocada por um programa contiver contas assinadas com PDA, invoke_signed() deve ser usado em vez de invoke(). Usaremos outro exemplo para demonstrar o uso de invoke_signed(). Agora vamos primeiro analisar o código do contrato.

3.1 Revisão do Código

Neste exemplo, criamos um PDA em tempo de execução dentro de um programa (ou seja, Programa B). Para criar um PDA, o System Program deve ser invocado no programa B.

Da linha 3 à linha 10, as bibliotecas necessárias serão importadas. Observe que invoke_signed() é importado desta vez (linha 6).

Semelhante ao exemplo da Seção 2, extraímos as contas necessárias (linha 22 - linha 27), que são o System Program e o PDA. Em seguida, usamos a função find_program_address() para gerar o endereço do PDA e a semente usada para empurrar esse PDA para fora da curva ed25519 (linha 29 - linha 30). Isso garante que o endereço não tenha uma chave privada associada. Neste exemplo, o cliente e o programa usam a mesma semente (ou seja, 'You pass butter') para gerar o PDA. Portanto, a chave pública deve ser a mesma, o que é verificado da linha 31 à linha 34. Após isso, invocamos invoke_signer para emitir a instrução allocate() da linha 37 à linha 47. Diferente da função invoke(), ela recebe mais um argumento, que são as sementes usadas para criar o PDA, bem como a semente de incremento usada pela função find_program_address().

Para criar/alocar uma conta, a própria conta deve fornecer uma assinatura, e neste exemplo o PDA é o assinante. Para assinar o PDA, invoke_signed é usado. Especificamente, o Solana usará as sementes e o programId do chamador (ou seja, Programa B) para recriar o PDA e compará-lo com as contas fornecidas (o segundo argumento). Se forem iguais, o PDA será assinado.

O programa implantado pode ser verificado abaixo.

https://explorer.solana.com/address/4h3RXGsouTRvUWNG1Dqq2tuuASTXFebHC3wFzv3tSFCK?cluster=devnet

3.2 Criando um PDA

Vamos analisar o script do cliente para o segundo exemplo.

Na linha 104, extraímos o PDA e a semente de incremento por meio da função findProgramAddress(). Da linha 112 à linha 120, a transação será criada e enviada. Observe que a propriedade (isSigner) do PDA é 'false' (linha 113) aqui, pois não pode ser assinado pelo cliente. Em tempo de execução, o Programa B assinará o PDA e invocará a instrução allocate no programa System Program.

Você pode encontrar o PDA alocado na seguinte transação.

https://explorer.solana.com/tx/5fzdfzbD4281pY1HJm37f1fxSEMGmWtQmbmFPzEiP9v6hWF8GRRZmfcMDvPJugTrs3npnCsaWUGvw15URyBhx3LS?cluster=devnet

3.3 Podemos Usar Invoke()?

Para demonstrar que invoke não pode ser usado aqui, usamos outro programa (ou seja, Programa C) para invocar a instrução allocation.

A única mudança que fizemos foi substituir a função invoke_signed() pela função invoke(). Observamos que a conta não pôde ser criada.

O erro mostra que a invocação entre programas precisa de um assinante para ser executada com sucesso. Ou seja, a função invoke_signed() é necessária.

4. Conclusão

Neste artigo, apresentamos como implementar a invocação entre programas por meio da função invoke(). Também usamos diferentes exemplos para ilustrar as diferenças entre invoke() e invoke_signed(). Fique ligado, pois mais artigos desta série serão publicados.

Leia outros artigos desta série:

Sign up for the latest updates
Perdas de ~5,57 milhões USD: exploração de falhas no X100 Freezer e no NEM | Boletim semanal da BlockSec
Security Insights

Perdas de ~5,57 milhões USD: exploração de falhas no X100 Freezer e no NEM | Boletim semanal da BlockSec

Este relatório semanal aborda dois incidentes de segurança na Ethereum e na BNB Chain no período de 19/10/2026–25/10/2026. Ele examina uma tomada de controle da governança do X100 Freezer financiada por um empréstimo-relâmpago e uma falha na liquidação de impostos que afetou um pool de liquidez de um token NEM na BNB Chain. As perdas estimadas no escopo do relatório totalizam aproximadamente 5,57 milhões USD: cerca de 4,75 milhões USD da transação representativa do X100 e cerca de 820 mil USD do incidente no pool do NEM. O total exclui as extrações subsequentes do X100 relatadas separadamente.

Perdas de ~3,87 milhões USD: ataques à Autheo Network e à UNCX | Resumo semanal da BlockSec
Security Insights

Perdas de ~3,87 milhões USD: ataques à Autheo Network e à UNCX | Resumo semanal da BlockSec

Este relatório semanal aborda 3 incidentes de segurança no período de 12/10/2026–18/10/2026, com perdas totais estimadas em aproximadamente 3,87 milhões USD. A Autheo Network sofreu um comprometimento de chave privada com perdas de cerca de 1,76 milhões USD, a Qubic Wallet perdeu cerca de 1,30 milhões USD devido à geração de seeds fracas, e os contratos Smart Token Vesting V2 da UNCX Network sofreram um erro contábil de cerca de 807 mil USD nas redes Ethereum, BNB Chain, Base e Robinhood Chain. A análise em destaque da UNCX explica como um cálculo incorreto do total de cotas misturou parcelas de vesting criadas com diferentes proporções entre tokens e cotas, permitindo saques acima do devido de pools compartilhados.

O que é a certificação SEAL? Garantia de segurança operacional para cripto
Security Insights

O que é a certificação SEAL? Garantia de segurança operacional para cripto

A certificação SEAL oferece uma avaliação independente da segurança operacional em cripto dentro de um escopo acordado. Conheça seus seis módulos, os requisitos de evidências, os limites da certificação e o processo de avaliação da BlockSec.