> For the complete documentation index, see [llms.txt](https://docs.rome.builders/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.rome.builders/pt-br/guias-do-desenvolvedor/call-evm-from-solana.md).

# Chamar EVM a partir da Solana

Permita que uma carteira Solana controle contratos EVM na Rome — sem chave Ethereum. A carteira assina, e sua transação vai para a Solana.

O inverso de [Chamar Solana a partir da EVM](/pt-br/guias-do-desenvolvedor/call-solana-from-evm.md): uma carteira Solana (por exemplo, Solflare) chama diretamente qualquer contrato EVM na Rome, com **sem chave Ethereum**. É assim que [Aerarium](/pt-br/apps-na-rome/apps.md) permite que usuários nativos de Solana compartilhem os mesmos contratos que os usuários EVM.

A forma de uma única chamada é a do SDK `submitRomeTxV1`, que faz o proxy compor uma transação Solana v1 para a chamada; esta página explica os mecanismos.

## Endereços sintéticos

A identidade EVM de uma carteira Solana é seu **endereço sintético** — os últimos 20 bytes do `keccak256` de sua chave pública Solana de 32 bytes:

```
synthetic_evm_address = keccak256(solana_pubkey)[12:]
```

Este é o `msg.sender` quando a carteira chama um contrato, e a identidade estável sob a qual seu nonce e armazenamento residem. A derivação é fixada no protocolo, então uma carteira sempre mapeia para o mesmo endereço.

```javascript
import { syntheticAddress } from "@rome-protocol/sdk";
const from = syntheticAddress(solanaPubkey); // 0x… 20 bytes
```

## O sintético é apenas um intermediário — ele não mantém tokens em repouso

O saldo utilizável de um usuário nativo de Solana fica em sua **wallet Solana** (como tokens SPL), expostos 1:1 no lado EVM como o **wrapper ERC20SPL** (por exemplo, `wUSDC`). O sintético não mantém nada em repouso, então o valor flui *por meio de* ele — cada etapa assinada pela carteira Solana:

1. **Provisione (uma vez).** A PDA de autorização externa de um sintético recém-criado não existe até `create_pda` ser executada — e as transferências abaixo são assinadas por essa PDA. `submitRomeTxSolanaLane` faz o provisionamento automaticamente no primeiro uso (ou chame `provisionSynthetic` para uma etapa explícita de "Ativar"; verifique com `isSyntheticProvisioned`). Com `submitRomeTxV1`, verifique `isSyntheticProvisioned` e envie `buildCreatePdaCall` por meio dele uma vez.
2. **Etapa de financiamento (carteira → sintético).** Mova o token da ATA da carteira para a do sintético — a `ActivateAta` etapa, construída por `buildFundLeg`. Agora `wrapper.balanceOf(synthetic)` lê esse saldo, então o sintético o gasta como um ERC-20 comum (`transfer` / `transferFrom`) — **não** como nativo `msg.value`, que ele não mantém.
3. **A(s) chamada(s) (`DoTxUnsigned`).** O sintético executa a(s) transação(ões) EVM — por exemplo `approve` depois um vault `deposit` que puxa via `transferFrom`.
4. **Etapa de varredura (sintético → carteira).** Depois que um withdraw / borrow / claim deposita tokens no sintético, `buildSweepLeg` envia-os de volta para a própria ATA da carteira do usuário (`HelperProgram.transfer_spl`), de modo que o sintético zera o saldo líquido.

A próxima seção descreve o que o mais antigo `submitRomeTxSolanaLane` constrói no lado do cliente. `submitRomeTxV1` faz o proxy compor uma transação v1 em vez disso, sem descoberta de contas, ComputeBudget ou carteira tesouro no seu código; veja [os endpoints external-V1](#the-external-v1-endpoints) abaixo.

## Como a chamada é construída

`submitRomeTxSolanaLane` faz tudo isso. Os mecanismos:

1. **Construa uma transação EIP-1559 não assinada** com `from` = o endereço sintético — sem assinatura secp256k1.
2. **Descubra as contas** — chame [`rome_emulateCallAccounts`](/pt-br/referencia/json-rpc.md) com o `from`, `em`, `data`, **e `value`** (quando a chamada é payable). Passar `value` importa: o proxy emula a *real* chamada, então qualquer gravação de armazenamento dependente de valor — por exemplo, um novo slot de mapeamento — é alocada e sua conta Solana é retornada. Omiti-lo faz essa conta faltar, e a transação falha com *"instruction modified data of a read-only account."*
3. **Monte a transação Solana:** duas **ComputeBudget** instruções (a EVM da Rome precisa de um limite de CU aumentado ≈1,35M e de um heap frame grande ≈250 KB — os padrões da Solana falham) + a **`DoTxUnsigned`** instrução (o RLP não assinado + as contas descobertas) + a **carteira tesouro** (a execução lhe paga uma pequena taxa; a descoberta a omite, então o SDK a anexa).
4. **A carteira assina e envia.** Os **A carteira Solana assina a transação Solana (Ed25519) e a envia para o RPC da Solana — não para o proxy.** O runtime da Solana verifica a assinatura; on-chain, o programa deriva `msg.sender` a partir desse signatário. A autoridade é a assinatura da Solana, não uma do Ethereum. (O proxy é usado apenas para a emulação/descoberta na etapa 2.)

A PDA do usuário (`["EXTERNAL_AUTHORITY", synthetic_address]`) é dona das contas de token e assina CPIs SPL em nome do usuário — assim, um usuário Solana pode fornecer, tomar emprestado, trocar e fazer LP inteiramente a partir de sua carteira Solana.

## Os endpoints external-V1

`submitRomeTxV1` é a forma de uma única chamada: ele pede ao proxy uma transação v1 composta, a verifica, faz a carteira assiná-la e a envia ao RPC da Solana, encaminhando pelo proxy quando a chamada não cabe. O proxy expõe a mesma via como métodos RPC, então qualquer cliente pode usá-la sem o SDK (lista completa em [Suporte a JSON-RPC](/pt-br/referencia/json-rpc.md)):

* `rome_composeUnsignedAtomicV1(rlp, pubkey, signature)` — uma única transação Solana v1; a carteira a assina e o app a transmite ao RPC da Solana. Recusado quando a chamada não cabe em uma transação atômica.
* `rome_composeUnsignedIterativeV1(rlp, pubkey, signature)` — cada etapa da execução (atômica se couber, caso contrário, as etapas iterativas); a carteira assina cada uma, `rome_submitSignedV1Plan` e as transmite. Os limites de um plano longo estão em [Chamadas retransmitidas e chamadas longas](#relayed-calls-and-long-calls).
* `rome_relayUnsignedV1(rlp, pubkey, signature)` — uma única assinatura da carteira, o pagador do proxy conduz as etapas e retorna o hash da tx EVM; o sintético paga o gas da Rome, então financie-o uma vez com `rome_composeExternalDepositV1`.

**A assinatura de autorização.** `rlp` é o corpo EIP-1559 não assinado bruto de 9 campos. A carteira assina, com sua chave Ed25519, seja o bruto de 32 bytes `keccak256(0x02 ‖ rlp)` ou a mensagem legível

```
Rome authorization\n0x<64 lowercase hex chars of that hash>
```

Ambas são aceitas; o formato legível é o que uma carteira exibe de forma legível em seu `signMessage` prompt. O programa recalcula o hash a partir do corpo que executa e exige que a mensagem assinada seja exatamente uma das duas formas, então uma assinatura sobre um corpo nunca pode autorizar outro, e o nonce do corpo impede replay.

## Chamadas retransmitidas e chamadas longas

Algumas chamadas não cabem em uma transação Solana. Esta seção cobre o que acontece nesse caso e quais limites se aplicam.

### Quando o compositor atômico recusa

`rome_composeUnsignedAtomicV1` recusa uma chamada que não cabe em uma transação atômica. `submitRomeTxV1` então encaminha a chamada pelo proxy com a **mesma** assinatura de autorização, então a carteira não é solicitada novamente. O resultado tem `route: "relay"` e nenhuma `assinatura`. `relayOnRefusal: false` para receber a recusa como erro em vez disso, ou chame `relayV1` você mesmo para fazer relay de propósito.

Três coisas para saber sobre uma chamada em relay:

* **O sintético paga o gas.** Na rota de relay, o proxy envia e paga pelas transações Solana, e a chamada é paga no token nativo de gas da chain a partir do saldo do sintético. O saldo deve ser pelo menos `gasLimit × maxFeePerGas`. `fundSyntheticGas(deps, amountWei)` recarrega a partir da própria conta de token da carteira para o token de gas da chain (USDC em Hadrian e Rubicon); a carteira assina uma transação v1 simples e precisa de um pouco de SOL para a taxa da Solana. `amountWei` está no wei de 18 casas decimais da chain e deve ser um múltiplo de 10^12, ou o proxy o recusa. Sem o SDK, `rome_composeExternalDepositV1` constrói a mesma transação.
* **Um revert não lança exceção.** Uma chamada em relay que reverte do lado EVM é resolvida normalmente, com `receipt.status === "0x0"`. Verifique `receipt?.status === "0x1"` antes de considerar a chamada concluída. `receipt` é `null` se o receipt não aparecer a tempo.
* **`relayOnRefusal: false` é uma escolha feita no SDK, não um bloqueio.** O proxy já possui a assinatura de autorização para esse payload e pode executá-lo por qualquer rota, até `gasLimit × maxFeePerGas`.

```javascript
const res = await submitRomeTxV1(deps, { to, data, value });
if (res.route === "relay" && res.receipt?.status !== "0x1") {
  // uma chamada em relay que reverte é resolvida; ela não lança exceção
}
```

### Chamadas longas

Uma chamada que precisa de mais de uma transação roda como uma sessão iterativa: o programa executa quantos passos EVM couberem em cada transação Solana e salva seu estado entre elas. Duas maneiras de acioná-la a partir de uma carteira Solana:

* **Faça relay dela.** `rome_relayUnsignedV1` usa uma única assinatura da carteira e o pagador do proxy envia cada etapa. O sintético paga o gas, como acima.
* **Assine as etapas você mesmo.** `rome_composeUnsignedIterativeV1` retorna cada etapa com um campo de assinatura vazio, a carteira assina cada uma, e `rome_submitSignedV1Plan` as transmite em ordem. Cada etapa é uma transação Solana separada para a carteira assinar, então uma carteira que assina uma transação por vez solicita uma vez por etapa, além da assinatura de autorização. A carteira paga a taxa Solana em cada etapa.

Os limites:

| Limite                                              | Valor              | De onde vem                                                                                                            |
| --------------------------------------------------- | ------------------ | ---------------------------------------------------------------------------------------------------------------------- |
| Transações em uma `rome_submitSignedV1Plan` chamada | 64                 | O proxy recusa um plano mais longo                                                                                     |
| Etapas que o compositor iterativo planejará         | 128                | O limite no compositor iterativo do Rust Rome SDK, que também limita o plano `rome_composeUnsignedIterativeV1` retorna |
| Iterações em uma sessão                             | 160                | O programa Rome EVM; além dele, a sessão deixa de ser retomada, libera seus bloqueios de conta e termina               |
| Tamanho da transação Solana e contas                | 4 KB, 64 endereços | Cada etapa é uma transação Solana v1                                                                                   |

A maioria das chamadas reais se resolve em bem menos etapas do que esses limites. O limite de 64 transações em um plano assinado pela carteira é o primeiro que você encontrará. Uma chamada que precise de mais etapas do que isso não pode ser transmitida por meio de `rome_submitSignedV1Plan`.

Uma chamada longa não pode fazer CPIs da trilha legada. Chamadas mutadoras nos precompilados legados (`0xff…08`, `0xff…09` e `0x42…16`) são recusadas em uma sessão iterativa com `CpiProhibitedInIterativeTx`. Leituras do estado Solana e dos precompilados da trilha em cache (`0xff…04`, `0xff…05`, `0xff…06`, `0xff…0b`) funcionam. Uma chamada que faça CPIs da trilha legada deve caber em uma transação atômica, independentemente da via que a envie. Veja [Restrições](/pt-br/conceitos-principais/constraints.md) e [Orçamento de computação](/pt-br/conceitos-principais/compute-budget.md).

## Implementações de referência

* **Aerarium** — opera o Compound v3 (supply / borrow) a partir de uma carteira Solana via `DoTxUnsigned`. É a referência para a via mais antiga de transação legada descrita acima, não para `submitRomeTxV1`.
* **Rome DEX** não é um exemplo desta página: seu lado Solana é um programa nativo da Solana para o qual a carteira assina diretamente, e seu lado EVM compartilha o mesmo pool.

Aerarium não precisa de ponte nem de segunda carteira — o endereço sintético faz de uma chave Solana uma conta EVM de primeira classe. Para o padrão v1, siga [Construir um app de duas lanes](/pt-br/guias-do-desenvolvedor/dual-lane-app.md).

## O que Vem a Seguir

* [Chamar Solana a partir da EVM](/pt-br/guias-do-desenvolvedor/call-solana-from-evm.md) — na outra direção, via CPI
* [Interoperabilidade de tokens](/pt-br/conceitos-principais/token-interop.md) — como os saldos são compartilhados entre EVM e Solana


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://docs.rome.builders/pt-br/guias-do-desenvolvedor/call-evm-from-solana.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
