# Взаимодействие токенов

Rome EVM связывает ERC-20 токены и SPL токены через модель единого состояния. На этой странице объясняется, как токены работают одновременно в EVM и Solana.

## Модель единого состояния

В отличие от традиционных мостов, Rome не блокирует токены в одной сети и не выпускает их обёрнутые копии в другой. Вместо этого ERC-20 токены в Rome EVM являются **прозрачными обёртками** над базовыми SPL token accounts в Solana.

```
┌──────────────────────────────────┐
│ Rome EVM                         │
│                                  │
│   ERC-20 "rUSDC"                 │
│   ┌────────────────────────┐     │
│   │ balanceOf(user)        │─────┼──► читает напрямую из SPL ATA
│   │ transfer(to, amount)   │─────┼──► выполняет SPL transfer через precompile
│   │ totalSupply()          │─────┼──► читает объём выпуска SPL mint
│   └────────────────────────┘     │
│                                  │
└──────────────────────────────────┘
                 │
                 │ одни и те же базовые данные
                 ↓
┌──────────────────────────────────┐
│ Solana                           │
│                                  │
│   SPL Token Account (ATA)        │
│   Владелец: PDA пользователя     │
│   Mint: USDC (нативный Circle)   │
│   Количество: 1000000 (= 1 USDC) │
│                                  │
└──────────────────────────────────┘
```

**Что это означает:**

* Нет задержки моста — баланс ERC-20 ЯВЛЯЕТСЯ балансом SPL
* Нет фрагментации ликвидности — DeFi с обеих сторон видит одни и те же токены
* Нет риска моста — нет отдельного эскроу, который можно эксплуатировать

## ERC20SPL: контракт-обёртка

`SPL_ERC20` — это стандартный контракт-обёртка, предоставляющий полный интерфейс ERC-20 поверх SPL token mint:

```solidity
import {SPL_ERC20} from "@rome-protocol/solidity-sdk/contracts/token/ERC20SPL.sol";

// Обёртка читает балансы из SPL ATA пользователя
uint256 balance = wrapper.balanceOf(userAddress);

// Переводы выполняются через precompile SPL Token
wrapper.transfer(recipient, amount);
```

**Как это работает на низком уровне:**

* `balanceOf()` → выводит ATA пользователя (Associated Token Account) → считывает баланс из Solana
* `transfer()` → вызывает precompile SPL Token (`0xff...05`) → перемещает токены в Solana
* `approve()` / `allowance()` → использует хранилище EVM (стандартный шаблон ERC-20), поскольку SPL нативно не поддерживает allowance в стиле EVM
* `totalSupply()` → читает данные из аккаунта SPL mint

## ERC20SPLFactory

Фабричный контракт развёртывает обёртки для любого SPL токена:

```solidity
import {ERC20SPLFactory} from "@rome-protocol/solidity-sdk/contracts/token/ERC20SPLFactory.sol";

ERC20SPLFactory factory = ERC20SPLFactory(0xfd21da046c282e1d36cc45e46d9599cff5742f2b);

// Развернуть обёртку для SPL mint (загружает имя/символ из метаданных Metaplex)
address wrapper = factory.add_spl_token_with_metadata(splMintPubkey);

// Или указать имя/символ вручную
address wrapper = factory.add_spl_token_no_metadata(splMintPubkey, "USD Coin", "USDC");
```

**Адрес фабрики (devnet):** `0xfd21da046c282e1d36cc45e46d9599cff5742f2b`

## Реестр токенов

Реестр `токенов` обеспечивает управляемую администратором регистрацию одобренных SPL токенов с кроссчейн-метаданными:

```solidity
import {TokenRegistry, TokenOrigin} from "@rome-protocol/solidity-sdk/contracts/token/TokenRegistry.sol";

// Зарегистрировать нативный SPL токен
registry.registerToken(
    splMint,
    TokenOrigin.NativeSPL,
    bytes32(0),   // нет внешнего адреса
    0             // нет внешней сети
);

// Зарегистрировать токен, обёрнутый через Wormhole, с кроссчейн-метаданными
registry.registerToken(
    wormholeMint,
    TokenOrigin.WormholeWrapped,
    externalTokenAddress,  // исходный токен в исходной сети
    2                       // ID сети Wormhole для Ethereum
);
```

Реестр гарантирует, что каждый актив сопоставляется с одним каноническим SPL mint, предотвращая фрагментацию ликвидности из-за нескольких представлений USDC.

## Поток депозита / вывода

### Депозит SPL → EVM

1. Пользователь переводит SPL токены в vault моста
2. Мост создаёт ATA пользователя в Rome EVM (если он не существует)
3. Обёртка ERC-20 становится активной — пользователь видит баланс в MetaMask

### Вывод EVM → SPL

1. Пользователь вызывает precompile Withdraw (`0x42...16`) в Rome EVM
2. Precompile выполняет SPL transfer из PDA пользователя обратно в его Solana-кошелёк
3. SPL токены появляются в Solana-кошельке пользователя

## Вычисление PDA

Каждому EVM-адресу соответствует Solana PDA, владеющий его токен-аккаунтами:

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

// Получить Solana PDA для EVM-адреса
bytes32 userPda = RomeEVMAccount.pda(msg.sender);

// Получить ATA пользователя для конкретного mint
bytes32 ata = AssociatedSplToken.create_associated_token_account(userPda, mintPubkey);
```

## Ключевые шаблоны

### Чтение SPL-балансов из Solidity

```solidity
// Прочитать исходное состояние SPL token account
ISplToken.Account memory account = SplToken.account_state(tokenAccountPubkey);
uint64 balance = account.amount;
uint8 decimals = SplToken.decimals_eq(mintPubkey, 9); // проверить decimals
```

### Перевод токенов через SPL precompile

```solidity
// Прямой SPL transfer (более низкий уровень, чем обёртка ERC-20)
SplToken.transfer(recipientAta, mintPubkey, amount);
```

## Газовый токен

У каждой сети Rome EVM есть собственный газовый токен — любой SPL токен, выбранный при регистрации сети:

* **RSOL** — газовый токен по умолчанию (обёрнутый SOL)
* Пользовательские токены — любой SPL токен, цена которого определяется через пул Meteora DAMM V1

Газовые токены — это ERC-20 представления SPL токенов. Transfer Hooks НЕ срабатывают при внутренних платежах газа в EVM.

## Ограничения

* Суммы SPL токенов имеют тип `uint64` — максимальное значение 18,446,744,073,709,551,615
* Количество decimals по умолчанию для новых SPL mint: 9
* Символы обёрток ERC-20 должны быть глобально уникальны в пределах одной фабрики
* Allowance используют хранилище EVM (а не делегатов Solana)

## Что дальше

* [Transfer Hooks](/ru/osnovnye-koncepcii/transfer-hooks.md) — логика EVM в Token-2022 transfer hooks
* [Руководство по обёртыванию токенов](https://github.com/rome-protocol/docs/blob/main/developer-guides/token-wrapping.md) — разверните собственную обёртку ERC-20
* [Адреса контрактов](/ru/spravochnik/contract-addresses.md) — адреса развёрнутых фабрик


---

# 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/ru/osnovnye-koncepcii/token-interop.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.
