For the complete documentation index, see llms.txt. This page is also available as Markdown.

Call EVM from Solana

Let a Solana wallet drive EVM contracts on Rome — no Ethereum key. The wallet signs, and its transaction goes to Solana.

The reverse of Call Solana from EVM: a Solana wallet (e.g. Phantom) calls any EVM contract on Rome directly, with no Ethereum key. This is how Aerarium and Rome DEX let Solana-native users share the same contracts as EVM users.

The one-call way is the SDK's submitRomeTxSolanaLane; this page explains what it does.

Synthetic addresses

A Solana wallet's EVM identity is its synthetic address — the last 20 bytes of the keccak256 of its 32-byte Solana public key:

synthetic_evm_address = keccak256(solana_pubkey)[12:]

This is the msg.sender when the wallet calls a contract, and the stable identity its nonce and storage live under. The derivation is pinned in the protocol, so a wallet always maps to the same address.

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

The synthetic is a pass-through — it holds no tokens at rest

A Solana-native user's spendable balance lives in their Solana wallet (as SPL tokens), surfaced 1:1 on the EVM side as the token's ERC20SPL wrapper (e.g. wUSDC). The synthetic holds nothing at rest, so value flows through it — every step Solana-wallet-signed:

  1. Provision (once). A brand-new synthetic's external-auth PDA doesn't exist until create_pda runs — and the transfers below are signed by that PDA. submitRomeTxSolanaLane provisions it automatically on first use (or call provisionSynthetic for an explicit "Activate" step; check with isSyntheticProvisioned).

  2. Fund leg (wallet → synthetic). Move the token from the wallet's ATA into the synthetic's — the ActivateAta step, built by buildFundLeg. Now wrapper.balanceOf(synthetic) reads that balance, so the synthetic spends it as an ordinary ERC-20 (transfer / transferFrom) — not as native msg.value, which it doesn't hold.

  3. The call(s) (DoTxUnsigned). The synthetic runs the EVM transaction(s) — e.g. approve then a vault deposit that pulls via transferFrom.

  4. Sweep leg (synthetic → wallet). After a withdraw / borrow / claim lands tokens in the synthetic, buildSweepLeg pushes them back to the user's own wallet ATA (HelperProgram.transfer_spl), so the synthetic nets to nothing.

How the call is built

submitRomeTxSolanaLane does all of this. The mechanics:

  1. Build an unsigned EIP-1559 transaction with from = the synthetic address — no secp256k1 signature.

  2. Discover accounts — call rome_emulateCallAccounts with the call's from, to, data, and value (when the call is payable). Passing value matters: the proxy emulates the real call, so any value-dependent storage write — e.g. a fresh mapping slot — is allocated and its Solana account is returned. Omit it and that account is missing, and the transaction fails with "instruction modified data of a read-only account."

  3. Assemble the Solana transaction: two ComputeBudget instructions (Rome's EVM needs a raised CU limit ≈1.35M and a large heap frame ≈250 KB — Solana's defaults fault) + the DoTxUnsigned instruction (the unsigned RLP + the discovered accounts) + the per-chain treasure wallet (the execution pays it a small fee; discovery omits it, so the SDK appends it).

  4. The wallet signs and submits. The Solana wallet signs the Solana transaction (Ed25519) and sends it to the Solana RPC — not to the proxy. The Solana runtime verifies the signature; on-chain, the program derives msg.sender from that signer. Authority is the Solana signature, not an Ethereum one. (The proxy is used only for the emulation/discovery in step 2.)

The user's PDA (["EXTERNAL_AUTHORITY", synthetic_address]) owns their token accounts and signs SPL CPIs on their behalf — so a Solana user can supply, borrow, swap, and LP entirely from Phantom.

Reference implementations

  • Aerarium — drives Compound v3 (supply / borrow) from Phantom via DoTxUnsigned.

  • Rome DEX — the Solana lane trades and LPs the same pool as the EVM lane.

Both are Solana-native without a bridge or a second wallet — the synthetic address makes one Phantom key a first-class EVM account.

What's Next

Last updated

Was this helpful?