Call Solana from EVM

Rome's CPI precompile lets Solidity contracts call any Solana program directly. This guide covers the mechanics.

Prerequisites

  • Rome Solidity SDK installed: npm install @rome-protocol/solidity-sdk

  • A deployed Rome contract (see Deploy Solidity)

The CPI Precompile

The CPI precompile at 0xFF00000000000000000000000000000000000008 provides two functions:

import {CpiProgram} from "@rome-protocol/solidity-sdk/contracts/core/Precompiles.sol";

// Call a Solana program
CpiProgram.invoke(programId, accounts, instructionData);

// Call with PDA signing (your contract signs as a PDA)
CpiProgram.invoke_signed(programId, accounts, data, seeds);

Basic Example: Transfer SOL

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

import {SystemProgram, CpiProgram} from "@rome-protocol/solidity-sdk/contracts/core/Precompiles.sol";
import {RomeEVMAccount} from "@rome-protocol/solidity-sdk/contracts/core/RomeEVMAccount.sol";

contract SolTransfer {
    function transferSol(bytes32 recipient, uint64 lamports) external {
        // Get sender's PDA
        bytes32 senderPda = RomeEVMAccount.pda(msg.sender);

        // Build System Program transfer instruction
        ICrossProgramInvocation.AccountMeta[] memory accounts = new ICrossProgramInvocation.AccountMeta[](2);
        accounts[0] = ICrossProgramInvocation.AccountMeta(senderPda, true, true);   // sender (signer, writable)
        accounts[1] = ICrossProgramInvocation.AccountMeta(recipient, false, true);   // recipient (writable)

        // System Program transfer instruction (variant 2, little-endian u64 amount)
        bytes memory data = abi.encodePacked(uint32(2), lamports);

        CpiProgram.invoke(SystemProgram.program_id(), accounts, data);
    }
}

Reading Account Data

The CPI precompile also lets you read any Solana account's data:

Working with SPL Tokens

Use the SPL Token precompile for common token operations:

PDA Derivation

Find Program Derived Addresses from Solidity:

Base58 Conversion

Convert between bytes32 and base58 (Solana's address format):

Calling Custom Solana Programs

To call any arbitrary Solana program:

Key Constraints

  1. All accounts must be declared upfront. The Solana transaction must include every account the CPI will touch. Dynamic account discovery inside CPI is not possible.

  2. CPI depth limit: 4 levels. Rome EVM → Your target → Target's call → One more level. Plan your call depth carefully.

  3. Solana pubkeys are bytes32. All addresses are 32-byte Solana pubkeys, not 20-byte Ethereum addresses.

  4. Instruction data is raw bytes. You need to encode instruction data in the format the target program expects (typically Borsh-encoded, little-endian).

What's Next

Last updated

Was this helpful?