> 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/es/guias-para-desarrolladores/call-evm-from-solana.md).

# Llamar a EVM desde Solana

Permite que una cartera de Solana controle contratos EVM en Rome, sin clave de Ethereum. La cartera firma y su transacción se envía a Solana.

Lo inverso de [Llamar a Solana desde EVM](/es/guias-para-desarrolladores/call-solana-from-evm.md): una billetera de Solana (por ejemplo, Solflare) llama directamente a cualquier contrato EVM en Rome, con **sin clave de Ethereum**. Así es como [Aerarium](/es/apps-en-rome/apps.md) permite a los usuarios nativos de Solana compartir los mismos contratos que los usuarios EVM.

La forma de una sola llamada es la del SDK `submitRomeTxV1`, que hace que el proxy componga una transacción v1 de Solana para la llamada; esta página explica la mecánica.

## Direcciones sintéticas

La identidad EVM de una billetera de Solana es su **dirección sintética** — los últimos 20 bytes de `keccak256` de su clave pública de Solana de 32 bytes:

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

Este es el `msg.sender` cuando la billetera llama a un contrato, y la identidad estable bajo la cual viven su nonce y su almacenamiento. La derivación está fijada en el protocolo, así que una billetera siempre se asigna a la misma dirección.

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

## La sintética es un canal de paso — no mantiene tokens en reposo

El saldo disponible de un usuario nativo de Solana vive en su **wallet de Solana** (como tokens SPL), expuesto 1:1 en el lado EVM como el **envoltorio ERC20SPL** (p. ej., `wUSDC`). La sintética no mantiene nada en reposo, así que el valor fluye *a través de* ella — cada paso firmado por la billetera de Solana:

1. **Aprovisionamiento (una vez).** La PDA de autenticación externa de una sintética recién creada no existe hasta que `create_pda` se ejecuta — y las transferencias siguientes están firmadas por esa PDA. `submitRomeTxSolanaLane` la aprovisiona automáticamente en el primer uso (o llama a `provisionSynthetic` para un paso explícito de "Activar"; compruébalo con `isSyntheticProvisioned`). Con `submitRomeTxV1`, comprueba `isSyntheticProvisioned` y envía `buildCreatePdaCall` a través de ella una vez.
2. **Pierna de fondeo (billetera → sintética).** Mueve el token desde la ATA de la billetera a la de la sintética — el `ActivateAta` paso, construido por `buildFundLeg`. Ahora `wrapper.balanceOf(synthetic)` lee ese saldo, así que la sintética lo gasta como un ERC-20 ordinario (`transfer` / `transferFrom`) — **no** como nativo `msg.value`, que no posee.
3. **La(s) llamada(s) (`DoTxUnsigned`).** La sintética ejecuta la(s) transacción(es) EVM — p. ej. `approve` luego un vault `deposit` que extrae mediante `transferFrom`.
4. **Pierna de barrido (sintética → billetera).** Después de que un withdraw / borrow / claim deje tokens en la sintética, `buildSweepLeg` los empuja de vuelta a la propia ATA de la billetera del usuario (`HelperProgram.transfer_spl`), de modo que la sintética queda en cero.

La siguiente sección describe qué hace el más antiguo `submitRomeTxSolanaLane` se construye del lado del cliente. `submitRomeTxV1` hace que el proxy componga en su lugar una transacción v1, sin descubrimiento de cuentas, ComputeBudget ni billetera tesoro en tu código; consulta [los endpoints externos V1](#the-external-v1-endpoints) abajo.

## Cómo se construye la llamada

`submitRomeTxSolanaLane` hace todo esto. La mecánica:

1. **Construye una transacción EIP-1559 sin firmar** con `desde` = la dirección sintética — sin firma secp256k1.
2. **Descubre cuentas** — llama a [`rome_emulateCallAccounts`](/es/referencia/json-rpc.md) con los `desde`, `a`, `datos`, **y `valor`** (cuando la llamada es payable). Pasar `valor` importa: el proxy emula la *real* llamada, así que cualquier escritura de almacenamiento dependiente del valor — p. ej., un nuevo slot de mapeo — se asigna y se devuelve su cuenta de Solana. Omitirlo hace que esa cuenta falte, y la transacción falle con *"instruction modified data of a read-only account."*
3. **Ensambla la transacción de Solana:** dos **ComputeBudget** instrucciones (la EVM de Rome necesita un límite de CU elevado ≈1.35M y un marco de heap grande ≈250 KB — los valores predeterminados de Solana fallan) + la **`DoTxUnsigned`** instrucción (el RLP sin firmar + las cuentas descubiertas) + la por cadena **billetera tesoro** (la ejecución le paga una pequeña comisión; el descubrimiento la omite, así que el SDK la añade).
4. **La billetera firma y envía.** La **La billetera de Solana firma la transacción de Solana (Ed25519) y la envía al RPC de Solana — no al proxy.** El runtime de Solana verifica la firma; en cadena, el programa deriva `msg.sender` a partir de ese firmante. La autoridad es la firma de Solana, no una de Ethereum. (El proxy se usa solo para la emulación/descubrimiento en el paso 2.)

La PDA del usuario (`["EXTERNAL_AUTHORITY", synthetic_address]`) posee sus cuentas de tokens y firma CPI de SPL en su nombre — así que un usuario de Solana puede aportar, pedir prestado, intercambiar y hacer LP íntegramente desde su billetera de Solana.

## Los endpoints externos V1

`submitRomeTxV1` es la forma de una sola llamada: pide al proxy una transacción v1 compuesta, la verifica, hace que la billetera la firme y la envía al RPC de Solana, retransmitiendo a través del proxy cuando la llamada no encaja. El proxy expone la misma vía que los métodos RPC, así que cualquier cliente puede usarla sin el SDK (lista completa en [Soporte de JSON-RPC](/es/referencia/json-rpc.md)):

* `rome_composeUnsignedAtomicV1(rlp, pubkey, signature)` — una transacción v1 de Solana; la billetera la firma y la aplicación la difunde al RPC de Solana. Se rechaza cuando la llamada no cabe en una sola transacción atómica.
* `rome_composeUnsignedIterativeV1(rlp, pubkey, signature)` — cada tramo de la ejecución (atómico si encaja, o de lo contrario los tramos iterativos); la billetera firma cada uno, `rome_submitSignedV1Plan` los difunde. Los límites de un plan largo están en [Llamadas reenviadas y llamadas largas](#relayed-calls-and-long-calls).
* `rome_relayUnsignedV1(rlp, pubkey, signature)` — una sola firma de la billetera, el pagador del proxy conduce los tramos y devuelve el hash de la tx EVM; la sintética paga el gas de Rome, así que cárgala una vez con `rome_composeExternalDepositV1`.

**La firma de autorización.** `rlp` es el cuerpo EIP-1559 sin firmar de 9 campos. La billetera firma, con su clave Ed25519, ya sea el hash en bruto de 32 bytes `keccak256(0x02 ‖ rlp)` o el mensaje legible

```
Rome authorization
0x<64 lowercase hex chars of that hash>
```

Ambos se aceptan; la forma legible es la que una billetera muestra de manera legible en su `signMessage` ventana. El programa vuelve a calcular el hash a partir del cuerpo que ejecuta y exige que el mensaje firmado sea exactamente una de las dos formas, así que una firma sobre un cuerpo nunca puede autorizar otro, y el nonce del cuerpo evita la repetición.

## Llamadas reenviadas y llamadas largas

Algunas llamadas no caben en una sola transacción de Solana. Esta sección cubre qué ocurre entonces y qué límites aplican.

### Cuando el compositor atómico se niega

`rome_composeUnsignedAtomicV1` rechaza una llamada que no cabe en una transacción atómica. `submitRomeTxV1` entonces retransmite la llamada a través del proxy con la **misma** firma de autorización, así que no se le pide de nuevo a la billetera. El resultado tiene `route: "relay"` y sin firma de Solana `firma`. Pasa `relayOnRefusal: false` para obtener el rechazo como un error en su lugar, o llama a `relayV1` tú mismo para retransmitir a propósito.

Tres cosas que saber sobre una llamada retransmitida:

* **La sintética paga el gas.** En la ruta de retransmisión, el proxy envía y paga las transacciones de Solana, y la llamada se paga en el token nativo de gas de la cadena con el saldo de la sintética. El saldo debe ser al menos `gasLimit × maxFeePerGas`. `fundSyntheticGas(deps, amountWei)` lo recarga desde la propia cuenta de token de la billetera del token de gas de la cadena (USDC en Hadrian y Rubicon); la billetera firma una sola transacción v1 normal y necesita un poco de SOL para la comisión de Solana. `amountWei` está en el wei de 18 decimales de la cadena y debe ser múltiplo de 10^12, o el proxy lo rechaza. Sin el SDK, `rome_composeExternalDepositV1` construye la misma transacción.
* **Un revert no lanza una excepción.** Una llamada retransmitida que revierte en el lado EVM se resuelve normalmente, con `receipt.status === "0x0"`. Comprueba `receipt?.status === "0x1"` antes de considerar la llamada como completada. `receipt` es `null` si el receipt no apareció a tiempo.
* **`relayOnRefusal: false` es una decisión tomada en el SDK, no un bloqueo.** El proxy ya tiene la firma de autorización para esa carga útil y puede ejecutarla por cualquiera de las dos rutas, hasta `gasLimit × maxFeePerGas`.

```javascript
const res = await submitRomeTxV1(deps, { to, data, value });
if (res.route === "relay" && res.receipt?.status !== "0x1") {
  // una llamada retransmitida que revirtió se resuelve; no lanza una excepción
}
```

### Llamadas largas

Una llamada que necesita más de una transacción se ejecuta como una sesión iterativa: el programa ejecuta tantos pasos EVM como caben en cada transacción de Solana y guarda su estado entre ellos. Dos formas de conducirla desde una billetera de Solana:

* **Retransmítela.** `rome_relayUnsignedV1` requiere una sola firma de la billetera y el pagador del proxy envía cada tramo. La sintética paga el gas, como arriba.
* **Firma tú mismo los tramos.** `rome_composeUnsignedIterativeV1` devuelve cada tramo con un espacio de firma vacío, la billetera firma cada uno y `rome_submitSignedV1Plan` los difunde en orden. Cada tramo es una transacción de Solana separada para que la billetera la firme, así que una billetera que firma una transacción a la vez solicita una vez por tramo, además de la firma de autorización. La billetera paga la comisión de Solana en cada tramo.

Los límites:

| Límite                                                 | Valor                | De dónde viene                                                                                                                 |
| ------------------------------------------------------ | -------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| Transacciones en una `rome_submitSignedV1Plan` llamada | 64                   | El proxy rechaza un plan más largo                                                                                             |
| Tramos que planificará el compositor iterativo         | 128                  | El tope en el compositor iterativo del SDK Rust de Rome, que también limita el plan `rome_composeUnsignedIterativeV1` devuelve |
| Iteraciones en una sesión                              | 160                  | El programa EVM de Rome; más allá de eso la sesión deja de reanudarse, libera sus bloqueos de cuentas y termina                |
| Tamaño de la transacción de Solana y cuentas           | 4 KB, 64 direcciones | Cada tramo es una transacción v1 de Solana                                                                                     |

La mayoría de las llamadas reales se resuelven en muchos menos tramos que estos topes. El límite de 64 transacciones en un plan firmado por la billetera es el primero que encontrarás. Una llamada que necesite más tramos que eso no puede difundirse a través de `rome_submitSignedV1Plan`.

Una llamada larga no puede hacer CPI de la vía legacy. Las llamadas que mutan en los precompilados legacy (`0xff…08`, `0xff…09` y `0x42…16`) se rechazan en una sesión iterativa con `CpiProhibitedInIterativeTx`. Las lecturas del estado de Solana y de los precompilados de la vía caché (`0xff…04`, `0xff…05`, `0xff…06`, `0xff…0b`) funcionan. Una llamada que realiza CPI de la vía legacy debe caber en una sola transacción atómica, sea cual sea la vía que la envíe. Consulta [Restricciones](/es/conceptos-basicos/constraints.md) y [Presupuesto de cómputo](/es/conceptos-basicos/compute-budget.md).

## Implementaciones de referencia

* **Aerarium** — impulsa Compound v3 (supply / borrow) desde una billetera de Solana vía `DoTxUnsigned`. Es la referencia para la vía más antigua de transacciones legacy descrita arriba, no para `submitRomeTxV1`.
* **Rome DEX** no es un ejemplo de esta página: su lado de Solana es un programa nativo de Solana por el que la billetera firma directamente, y su lado EVM comparte el mismo pool.

Aerarium no necesita puente ni segunda billetera — la dirección sintética convierte una clave de Solana en una cuenta EVM de primera clase. Para el patrón v1, sigue [Construir una app de doble carril](/es/guias-para-desarrolladores/dual-lane-app.md).

## Qué sigue

* [Llamar a Solana desde EVM](/es/guias-para-desarrolladores/call-solana-from-evm.md) — la otra dirección, vía CPI
* [Interop de tokens](/es/conceptos-basicos/token-interop.md) — cómo se comparten los saldos entre EVM y 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/es/guias-para-desarrolladores/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.
