# Interoperabilitas Token

Rome EVM menjembatani token ERC-20 dan token SPL melalui model satu status. Halaman ini menjelaskan cara kerja token di EVM dan Solana.

## Model Satu Status

Tidak seperti bridge tradisional, Rome tidak mengunci token di satu chain dan mencetak salinan wrapped di chain lain. Sebaliknya, token ERC-20 di Rome EVM adalah **pembungkus transparan** di atas akun token SPL yang mendasarinya di Solana.

```
┌──────────────────────────────────┐
│ Rome EVM                         │
│                                  │
│   ERC-20 "rUSDC"                 │
│   ┌────────────────────────┐     │
│   │ balanceOf(user)        │─────┼──► membaca langsung dari SPL ATA
│   │ transfer(to, amount)   │─────┼──► mengeksekusi transfer SPL via precompile
│   │ totalSupply()          │─────┼──► membaca suplai mint SPL
│   └────────────────────────┘     │
│                                  │
└──────────────────────────────────┘
                 │
                 │ data dasar yang sama
                 ↓
┌──────────────────────────────────┐
│ Solana                           │
│                                  │
│   Akun Token SPL (ATA)           │
│   Pemilik: PDA milik pengguna    │
│   Mint: USDC (native Circle)     │
│   Jumlah: 1000000 (= 1 USDC)    │
│                                  │
└──────────────────────────────────┘
```

**Artinya ini berarti:**

* Tidak ada penundaan bridging — saldo ERC-20 ADALAH saldo SPL
* Tidak ada fragmentasi likuiditas — DeFi di kedua sisi melihat token yang sama
* Tidak ada risiko bridge — tidak ada escrow terpisah yang bisa dieksploitasi

## ERC20SPL: Kontrak Pembungkus

`SPL_ERC20` adalah kontrak pembungkus standar yang menyediakan antarmuka ERC-20 penuh di atas mint token SPL:

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

// Pembungkus membaca saldo dari ATA SPL milik pengguna
uint256 balance = wrapper.balanceOf(userAddress);

// Transfer dieksekusi melalui precompile SPL Token
wrapper.transfer(recipient, amount);
```

**Cara kerjanya di balik layar:**

* `balanceOf()` → menurunkan ATA pengguna (Associated Token Account) → membaca saldo dari Solana
* `transfer()` → memanggil precompile SPL Token (`0xff...05`) → memindahkan token di Solana
* `approve()` / `allowance()` → menggunakan penyimpanan EVM (pola ERC-20 standar) karena SPL tidak secara native mendukung allowance bergaya EVM
* `totalSupply()` → membaca dari akun mint SPL

## ERC20SPLFactory

Kontrak factory menerapkan pembungkus untuk token SPL apa pun:

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

ERC20SPLFactory factory = ERC20SPLFactory(0xfd21da046c282e1d36cc45e46d9599cff5742f2b);

// Menerapkan pembungkus untuk mint SPL (memuat nama/simbol dari metadata Metaplex)
address wrapper = factory.add_spl_token_with_metadata(splMintPubkey);

// Atau tentukan nama/simbol secara manual
address wrapper = factory.add_spl_token_no_metadata(splMintPubkey, "USD Coin", "USDC");
```

**Alamat factory (devnet):** `0xfd21da046c282e1d36cc45e46d9599cff5742f2b`

## Register Token

The `TokenRegistry` menyediakan pendaftaran token SPL yang disetujui dengan metadata lintas-chain yang dikontrol admin:

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

// Mendaftarkan token SPL native
registry.registerToken(
    splMint,
    TokenOrigin.NativeSPL,
    bytes32(0),   // tidak ada alamat eksternal
    0             // tidak ada chain eksternal
);

// Mendaftarkan token wrapped Wormhole dengan metadata lintas-chain
registry.registerToken(
    wormholeMint,
    TokenOrigin.WormholeWrapped,
    externalTokenAddress,  // token asli di chain sumber
    2                       // ID chain Wormhole untuk Ethereum
);
```

Registry memastikan setiap aset dipetakan ke satu mint SPL kanonik — mencegah beberapa representasi USDC memecah likuiditas.

## Alur Deposit / Withdraw

### Mendepositkan SPL → EVM

1. Pengguna mentransfer token SPL ke vault bridge
2. Bridge membuat ATA pengguna di Rome EVM (jika belum ada)
3. Pembungkus ERC-20 menjadi aktif — pengguna melihat saldo di MetaMask

### Menarik EVM → SPL

1. Pengguna memanggil precompile Withdraw (`0x42...16`) di Rome EVM
2. Precompile mengeksekusi transfer SPL dari PDA pengguna kembali ke dompet Solana mereka
3. Token SPL muncul di dompet Solana milik pengguna

## Derivasi PDA

Setiap alamat EVM dipetakan ke PDA Solana yang memiliki akun token mereka:

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

// Dapatkan PDA Solana untuk alamat EVM
bytes32 userPda = RomeEVMAccount.pda(msg.sender);

// Dapatkan ATA pengguna untuk mint tertentu
bytes32 ata = AssociatedSplToken.create_associated_token_account(userPda, mintPubkey);
```

## Pola Utama

### Membaca Saldo SPL dari Solidity

```solidity
// Baca state akun token SPL mentah
ISplToken.Account memory account = SplToken.account_state(tokenAccountPubkey);
uint64 balance = account.amount;
uint8 decimals = SplToken.decimals_eq(mintPubkey, 9); // verifikasi desimal
```

### Mentransfer Token via Precompile SPL

```solidity
// Transfer SPL langsung (level lebih rendah daripada pembungkus ERC-20)
SplToken.transfer(recipientAta, mintPubkey, amount);
```

## Token Gas

Setiap chain Rome EVM memiliki token gas sendiri — token SPL apa pun yang dipilih saat pendaftaran chain:

* **RSOL** — token gas default (SOL wrapped)
* Token kustom — token SPL apa pun, diberi harga melalui pool Meteora DAMM V1

Token gas adalah representasi ERC-20 dari token SPL. Transfer Hook TIDAK dijalankan pada pembayaran gas internal EVM.

## Batasan

* Jumlah token SPL adalah `uint64` — nilai maksimum 18,446,744,073,709,551,615
* Desimal default untuk mint SPL baru: 9
* Simbol pembungkus ERC-20 harus unik secara global per factory
* Allowance menggunakan penyimpanan EVM (bukan delegate Solana)

## Berikutnya

* [Transfer Hooks](/id/konsep-inti/transfer-hooks.md) — logika EVM di transfer hook Token-2022
* [Panduan Pembungkus Token](https://github.com/rome-protocol/docs/blob/main/developer-guides/token-wrapping.md) — terapkan pembungkus ERC-20 milik Anda sendiri
* [Alamat Contract](/id/referensi/contract-addresses.md) — alamat factory yang telah diterapkan


---

# 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/konsep-inti/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.
