# Panggil Solana dari EVM

CPI precompile Rome memungkinkan kontrak Solidity memanggil program Solana apa pun secara langsung. Panduan ini membahas mekanismenya.

## Prasyarat

* Rome Solidity SDK terinstal: `npm install @rome-protocol/solidity-sdk`
* Sebuah kontrak Rome yang telah di-deploy (lihat [Deploy Solidity](/id/panduan-pengembang/deploy-solidity.md))

## CPI Precompile

CPI precompile di `0xFF00000000000000000000000000000000000008` menyediakan dua fungsi:

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

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

// Memanggil dengan penandatanganan PDA (kontrak Anda menandatangani sebagai PDA)
CpiProgram.invoke_signed(programId, accounts, data, seeds);
```

## Contoh Dasar: Transfer SOL

```solidity
// 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 {
        // Dapatkan PDA pengirim
        bytes32 senderPda = RomeEVMAccount.pda(msg.sender);

        // Bangun instruksi transfer System Program
        ICrossProgramInvocation.AccountMeta[] memory accounts = new ICrossProgramInvocation.AccountMeta[](2);
        accounts[0] = ICrossProgramInvocation.AccountMeta(senderPda, true, true);   // pengirim (penandatangan, dapat ditulis)
        accounts[1] = ICrossProgramInvocation.AccountMeta(recipient, false, true);   // penerima (dapat ditulis)

        // Instruksi transfer System Program (varian 2, jumlah u64 little-endian)
        bytes memory data = abi.encodePacked(uint32(2), lamports);

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

## Membaca Data Akun

CPI precompile juga memungkinkan Anda membaca data akun Solana apa pun:

```solidity
(
    uint64 lamports,
    bytes32 owner,
    bool isSigner,
    bool isWritable,
    bool executable,
    bytes memory data
) = CpiProgram.account_info(accountPubkey);
```

## Bekerja dengan SPL Token

Gunakan precompile SPL Token untuk operasi token umum:

```solidity
import {SplToken, AssociatedSplToken} from "@rome-protocol/solidity-sdk/contracts/core/Precompiles.sol";

contract TokenOperations {
    // Membaca saldo akun token
    function getBalance(bytes32 tokenAccount) external view returns (uint64) {
        ISplToken.Account memory acc = SplToken.account_state(tokenAccount);
        return acc.amount;
    }

    // Transfer token SPL
    function transferTokens(bytes32 recipientAta, bytes32 mint, uint256 amount) external {
        SplToken.transfer(recipientAta, mint, amount);
    }

    // Membuat Associated Token Account
    function createAta(bytes32 wallet, bytes32 mint) external {
        AssociatedSplToken.create_associated_token_account(wallet, mint);
    }
}
```

## Derivasi PDA

Menemukan Program Derived Address dari Solidity:

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

// Menurunkan sebuah PDA
ISystemProgram.Seed[] memory seeds = new ISystemProgram.Seed[](2);
seeds[0] = ISystemProgram.Seed("my-program-seed");
seeds[1] = ISystemProgram.Seed(abi.encodePacked(someValue));

(bytes32 pda, uint8 bump) = SystemProgram.find_program_address(targetProgramId, seeds);
```

## Konversi Base58

Konversi antara bytes32 dan base58 (format alamat Solana):

```solidity
// bytes32 → string base58
bytes memory base58Str = SystemProgram.bytes32_to_base58(pubkey);

// string base58 → bytes32
bytes32 pubkey = SystemProgram.base58_to_bytes32(base58Bytes);
```

## Memanggil Program Solana Kustom

Untuk memanggil program Solana arbitrer apa pun:

```solidity
contract CustomCPI {
    bytes32 constant MY_PROGRAM = 0x...; // ID program Solana Anda

    function callMyProgram(bytes32 account1, bytes32 account2, bytes calldata ixData) external {
        ICrossProgramInvocation.AccountMeta[] memory accounts = new ICrossProgramInvocation.AccountMeta[](2);
        accounts[0] = ICrossProgramInvocation.AccountMeta(account1, false, true);
        accounts[1] = ICrossProgramInvocation.AccountMeta(account2, false, false);

        CpiProgram.invoke(MY_PROGRAM, accounts, ixData);
    }
}
```

## Batasan Utama

1. **Semua akun harus dideklarasikan di awal.** Transaksi Solana harus menyertakan setiap akun yang akan disentuh oleh CPI. Penemuan akun secara dinamis di dalam CPI tidak dimungkinkan.
2. **Batas kedalaman CPI: 4 level.** Rome EVM → target Anda → panggilan target → satu level lagi. Rencanakan kedalaman panggilan Anda dengan cermat.
3. **Pubkey Solana adalah bytes32.** Semua alamat adalah pubkey Solana 32-byte, bukan alamat Ethereum 20-byte.
4. **Data instruksi adalah byte mentah.** Anda perlu mengodekan data instruksi dalam format yang diharapkan program target (biasanya dikodekan Borsh, little-endian).

## Berikutnya

* [Wrapping Token](https://github.com/rome-protocol/docs/blob/main/developer-guides/token-wrapping.md) — terapkan wrapper ERC-20 untuk token SPL
* [Bangun Transfer Hook](https://github.com/rome-protocol/docs/blob/main/developer-guides/build-transfer-hook.md) — buat hook transfer yang didukung EVM
* [Optimasi CU](https://github.com/rome-protocol/docs/blob/main/developer-guides/cu-optimization.md) — kurangi konsumsi unit komputasi untuk panggilan CPI


---

# Agent Instructions: Querying This Documentation

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

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.rome.builders/id/panduan-pengembang/call-solana-from-evm.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
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.
