> 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/ru/rukovodstva-dlya-razrabotchikov/call-solana-from-evm.md).

# Вызов Solana из EVM

Вызывайте программы Solana из Solidity через CPI Rome и вспомогательные precompile.

Прекомпиляции Rome позволяют контрактам Solidity напрямую вызывать программы Solana. Это руководство описывает механику.

## Требования

* Интерфейсы Rome Solidity из публичного [`rome-solidity`](https://github.com/rome-protocol/rome-solidity) репозитория (устанавливается из GitHub, а не из npm — см. [Разверните Solidity](/ru/rukovodstva-dlya-razrabotchikov/deploy-solidity.md#using-the-rome-solidity-sdk)) — интерфейсы прекомпиляций находятся в [`contracts/interface.sol`](https://github.com/rome-protocol/rome-solidity/blob/master/contracts/interface.sol)
* Развернутый контракт Rome (см. [Разверните Solidity](/ru/rukovodstva-dlya-razrabotchikov/deploy-solidity.md))

Свяжите каждый интерфейс с его адресом прекомпиляции:

```solidity
import {ICrossProgramInvocation, ISystemProgram, IHelperProgram}
    from "@rome-protocol/rome-solidity/contracts/interface.sol";

ICrossProgramInvocation constant CpiProgram    = ICrossProgramInvocation(0xFF00000000000000000000000000000000000008);
ISystemProgram          constant SystemProgram = ISystemProgram(0xFF00000000000000000000000000000000000007);
IHelperProgram          constant Helper        = IHelperProgram(0xFF00000000000000000000000000000000000009);
```

## Прекомпиляция CpiProgram

`CpiProgram` (`0xFF…08`) выполняет CPI (`invoke` / `invoke_signed`) плюс быстрые ярлыки чтения cross-state (`account_info`, `account_data_at`, `account_u64_at`, `account_lamports`, `pdas_batch_derive`):

```solidity
// Вызов программы Solana
CpiProgram.invoke(programId, accounts, instructionData);

// Вызов с подписью PDA: подписывает PDA внешней авторизации вашего контракта, плюс один
// подсуб-PDA с солью для каждой записи в `salts` (Rome выводит ["EXTERNAL_AUTHORITY", contract, salt])
CpiProgram.invoke_signed(programId, accounts, data, salts);
```

## Перевод лампортов

Для простых переводов лампортов и SPL используйте прекомпиляцию HelperProgram — вручную собирать CPI не требуется. Контракт, вызывающий ее, действует как **сам**: приведенные ниже переводы перемещают собственные лампорты и токены контракта (подписывает его PDA внешней авторизации), а не пользователя. Чтобы контракт мог перевести SPL-токены пользователя на контролируемый им токен-аккаунт и определить, чьи они, пользователь предоставляет делегирование SPL. ERC-20 `transfer` или `transferFrom` контракту лишь зачисляет средства в эскроу-реестр обертки и не предоставляет контракту токен-аккаунт, из которого можно тратить — см. [Интеграция программы Solana](/ru/rukovodstva-dlya-razrabotchikov/integrate-solana-program.md).

```solidity
contract Transfers {
    IHelperProgram constant Helper = IHelperProgram(0xFF00000000000000000000000000000000000009);

    // Перевести лампорты с PDA этого контракта на PDA адреса EVM
    function transferSol(address to, uint64 lamports) external {
        Helper.transfer_lamports(to, lamports);
    }

    // Перевести SPL-токен с токен-аккаунта, принадлежащего PDA этого контракта
    function transferSpl(address to, uint64 tokens, bytes32 mint) external {
        Helper.transfer_spl(to, tokens, mint);
    }

    // Создать ATA вызывающей стороны для mint
    function createAta(bytes32 mint) external {
        Helper.create_ata(msg.sender, mint);
    }
}
```

`transfer_spl` имеет несколько перегрузок (включая вариант с делегатом для `transferFrom` потоков); см. `interface.sol`. На кэшированном треке используйте `ISplCached` (`0xff…05`) / `IAssociatedSplCached` (`0xff…06`) вместо этого — контракт последовательно использует один трек, и только устаревший трек может `invoke` пользоваться пользовательской программой (см. [Интеграция программы Solana](/ru/rukovodstva-dlya-razrabotchikov/integrate-solana-program.md)).

## Чтение данных аккаунта

Читайте данные любого аккаунта Solana через ярлыки чтения CpiProgram:

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

## Вывод PDA

Находите Program Derived Addresses из Solidity через прекомпиляцию System:

```solidity
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);
```

## Преобразование Base58

Преобразуйте между `bytes32` и base58 (формат адресов Solana):

```solidity
bytes memory base58Str = SystemProgram.bytes32_to_base58(pubkey);
bytes32 pubkey = SystemProgram.base58_to_bytes32(base58Bytes);
```

## Вызов пользовательских программ Solana

Чтобы вызвать любую программу Solana, самостоятельно сформируйте список аккаунтов и данные инструкции:

```solidity
contract CustomCPI {
    ICrossProgramInvocation constant CpiProgram = ICrossProgramInvocation(0xFF00000000000000000000000000000000000008);
    bytes32 constant MY_PROGRAM = 0x0000000000000000000000000000000000000000000000000000000000000000; // ваш идентификатор программы Solana

    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);
    }
}
```

## Ключевые ограничения

1. **Все аккаунты должны быть объявлены заранее.** Транзакция Solana должна включать каждый аккаунт, к которому обратится CPI — динамическое обнаружение аккаунтов внутри CPI невозможно.
2. **Ограничение глубины CPI: 4 уровня.** Rome EVM → ваша цель → вызов цели → еще один уровень. Планируйте глубину вызова.
3. **Публичные ключи Solana — это `bytes32`,** не 20-байтные адреса Ethereum.
4. **Данные инструкции — это сырые байты** в формате, ожидаемом целевой программой (обычно Borsh, little-endian).

## Что дальше

* **Посмотрите это в реальном приложении** — [cardo](https://github.com/rome-protocol/cardo) отправляет вызовы CPI напрямую в прекомпиляцию из кошелька пользователя, без адаптерного контракта; [rome-dex](https://github.com/rome-protocol/rome-dex) (dual-lane AMM) делает то же самое и также имеет некостодиальный контракт-маршрутизатор; [aerarium](https://github.com/rome-protocol/aerarium) — это кредитное приложение, которое не вызывает программы Solana из Solidity.
* [Интеграция программы Solana](/ru/rukovodstva-dlya-razrabotchikov/integrate-solana-program.md) — идентичность Solana пользователя, подпись от ее имени, правило одного трека и выделение аккаунтов для реальной программы на другой стороне
* [Справочник precompile](/ru/spravochnik/precompiles.md) — каждый селектор каждой прекомпиляции
* [Вызов EVM из Solana](/ru/rukovodstva-dlya-razrabotchikov/call-evm-from-solana.md) — обратное: управлять контрактами EVM из кошелька Solana
* [Совместимость токенов](/ru/klyuchevye-ponyatiya/token-interop.md) — как совместно работают токены ERC-20 и SPL
* [Ограничения](/ru/klyuchevye-ponyatiya/constraints.md) — глубина CPI и другие ограничения


---

# 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/ru/rukovodstva-dlya-razrabotchikov/call-solana-from-evm.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.
