> 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/tr/gelistirici-kilavuzlari/integrate-solana-program.md).

# Bir Solana programını entegre edin

Bir Solana programını Rome EVM ile entegre edin — Solana imzacısının kim olduğu, değerin programınıza nasıl ulaşıp geri döndüğü, tek hat kuralı, atomik ile yinelemeli modlar ve hesap sağlama.

Bu kılavuz, Rome EVM kullanıcılarının kendi programınızı kullanmasını isteyen bir Solana program ekibi içindir — EVM hesapları için değer tutması gereken bir gizlilik, borç verme ya da kasa programı. Şunun üzerine inşa edilir: [EVM'den Solana'yı çağırma](/tr/gelistirici-kilavuzlari/call-solana-from-evm.md) (ön derleme mekaniği) ve gerçek bir program karşı tarafta olduğunda ortaya çıkan soruları yanıtlar: *kim* imzalar, *nasıl* tokenlar girip çıkar ve *hangi* sınırlar tasarımı şekillendirir.

Burada kullanılan akış şudur: bir EVM hesabı USDC’yi programınıza taşır ("shield" ya da "deposit"), programınız bunu o kullanıcı adına tutar ve sonra daha sonra geri bırakır ("unshield" ya da "withdraw"). Fiilleri kendi adlarınızla değiştirin.

## 1. Her EVM adresinin bir Solana kimliği vardır

Rome, her EVM adresi için — kullanıcılar ve sözleşmeler dahil — bir Solana hesabı türetir; buna **harici yetki**:

```
external_auth(addr) = find_program_address(["EXTERNAL_AUTHORITY", addr_h160], rome_evm_program_id)
```

adlı adresin ilişkili token hesaplarına sahiptir (yani `wUSDC.balanceOf(addr)` buradan okunur) ve bu adres adına yapılan CPI’leri imzalayan anahtardır. Programınız 32 baytlık bir Solana pubkey görür; hiçbir zaman bir H160 görmez.

**Kimlerin imzalayacağına, ön derlemeyi kimin çağırdığı karar verir:**

| Ön derleme çağrılır                                                  | Solana imzalayıcısı                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
| -------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Bir **sözleşme**, normal bir `CALL`                                  | Bu **sözleşmenin kendi** harici yetkisi (`external_auth(contract)`), ayrıca ondan talep ettiği herhangi bir tuzlanmış alt-PDA ile birlikte                                                                                                                                                                                                                                                                                                                                                                                                                                                                                  |
| Bir **kullanıcı**doğrudan ön derleme adresine gönderilen bir işlemde | Bu **kullanıcının kendi** harici yetki                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                      |
| Bir sözleşme yoluyla `DELEGATECALL`                                  | Çıplak yetki reddedilir (`DelegatecallOwnerAuthority`). `invoke` imzasız olarak ve `invoke_signed` tuzlanmış alt-PDA’larla birlikte yine çalışır — ancak bu alt-PDA’lar çalışan sözleşmenin adresiyle ad alanına ayrılır (`["EXTERNAL_AUTHORITY", caller, running_contract, salt]`), bu yüzden `pda_with_salt` bunları türetmez. HelperProgram’da yalnızca oluşturma ve fonlama seçicileri geçer (`create_ata*`, `create_pda*`, `swap_gas_to_lamports`, `init_spl_mint`, `create_and_init_mint`); bunlar, hiçbir şey imzalamadıkları için değil, hedefleri çağırana bağlı ya da operatör tarafından fonlandığı için muaftır |

Sonuç, zaten bildiğiniz ERC-20 kuralıdır: **bir sözleşme bir kullanıcının varlıklarını kendi başına hareket ettiremez.** Kendi kimliği gibi davranır ve kullanıcı önce ona yetki verir. Solana tarafında hareket etmesi gereken tokenlar için bu yetki, kullanıcının token hesabı üzerindeki bir SPL delegasyonudur; sarmalayıcının ERC-20 `approve` işlevi ise yalnızca, sarmalayıcının kendi transferlerinin uyduğu bir EVM tarafı kullanım iznidir. Rome’un kendi token sarmalayıcılarının çalışması böyle olur ve adapter’ınız da böyle çalışır (bölüm 3).

Tuzlanmış alt-PDA’lar: `invoke_signed` bir `bytes32` tuz listesi alır ve Rome şu şekilde imzalar: `["EXTERNAL_AUTHORITY", caller_h160, salt]` her biri için (bump eklenir; doğrudan çağrıda çağıran, sözleşmedir). `HelperProgram.pda_with_salt(addr, salt)` adresini Solidity’den döndürür. Programınız pozisyon başına ayrı bir sahip hesabı istediğinde kullanıcı başına bir tuz kullanın (örneğin kullanıcının adresi).

Fonlama: bir external authority PDA’nın bir ATA’ya sahip olmak için var olması gerekmez (`create_ata` idempotenttir ve işlemin Solana fee payer’ı kirayı karşılar). Yalnızca instruction’ınızın oluşturduğu hesapları fonladığında var olmalı ve lamport tutmalıdır. `HelperProgram.create_pda(addr)` onu düz bir System `CreateAccount`olarak oluşturur, bu yüzden bir kez çağırın; idempotent değildir. `swap_gas_to_lamports(n)` adresin PDA’sına `n` lamport krediler; bunların bedelini çağıran Rome gas ile öder: bir legacy-track CPI’nin fee payer bakiyesi üzerindeki her etkisi işlem ücretine eklenir ve kullanıcıdan gas fiyatı üzerinden tahsil edilir; CPI’nin oluşturduğu hesaplar için kiralanan bedelin tahsil edilme şekli de aynıdır. Solana lane’inin sağlama adımı [Solana'dan EVM'yi çağırma](/tr/gelistirici-kilavuzlari/call-evm-from-solana.md)bölümünde anlatılır; bir sözleşme kendi PDA’sını constructor’ında ya da ilk çağrısında hazırlar.

## 2. Bir kullanıcının pozisyonunu tutmanın üç yolu

**A. Bir adapter sözleşmesi (yeniden kullanılabilir bir adapter için önerilir).** Tek bir Solidity sözleşmesi programınızın önünde durur. Kullanıcı adapter’ın yetkisine kendi token hesabı üzerinde bir SPL delegasyonu verir; adapter tokenları sahip olduğu bir token hesabına çeker, programınızı kendi kimliğiyle çağırır ve kullanıcının pozisyonunu programınız içinde kullanıcı başına bir alt-PDA ile ya da instruction verisine aktardığı bir tanımlayıcıyla anahtarlar. Çıkışta programınıza, kullanıcının kendi token hesabına bırakmasını söyler. Programınızın bilmesi gereken tek Solana kimliği adapter’dır. Verilen yetki bir SPL delegasyondur, ERC-20 `approve`değil; bunun nedenini ve kullanıcıya maliyetini bölüm 3 açıklar.

**B. Kullanıcının Solana imzalayıcısı olması.** Ön uç, kullanıcının EVM hesabından **doğrudan CpiProgram ön derlemesine** (`to = 0xff…08`, calldata = ABI ile kodlanmış `invoke` veya `invoke_signed`olacak şekilde bir işlem gönderir; böylece kullanıcının kendi harici yetkisi imzalar ve programınız pozisyonu onunla anahtarlayarak tutar. Adapter sözleşmesi yoktur ve delegasyon da yoktur, fakat her eylem cüzdanda opak bir calldata işlemi olur ve akışın CPI dışında ihtiyaç duyduğu her şey (ATA, önceden yapılmış bir transfer) ayrı bir işlemdir. Bu, tek seferlik yetkiler için (bir kullanıcının `approve_spl` bir sarmalayıcıya olan yetkisi) ve basit programlar için uygundur; çok adımlı akışlar için değildir. [Cardo](https://github.com/rome-protocol/cardo) bu yapıyı kullanır: ön yüzü `invoke` kullanıcının cüzdanından doğrudan ön derlemeye gönderir.

**C. Gözetimsiz bir yönlendirici.** Kullanıcının tokenlarını asla elinde tutmayan bir sözleşme. Kullanıcı yönlendiricinin yetkisine kendi token hesabı üzerinde bir SPL delegasyonu verir; yönlendirici, transfer yetkilisi olarak bu yetkiyle programınıza CPI yapar, böylece tokenlar kullanıcının token hesabından programınızın hesabına (veya geri kullanıcının hesabına) hareket eder ve yönlendirici çağrılar arasında hiçbir şey tutmaz. Yönlendirici, her kullanıcı tarafı hesabı `msg.sender`'dan türetir; böylece bir kullanıcının yetkisi başka bir kullanıcının hesabına yönlendirilemez ve genel bir `invoke` geçiş katmanı gibi davranmak yerine sabit instruction şekilleriyle tek bir sabit programı çağırır. `RomeDexRouter` içinde [rome-dex](https://github.com/rome-protocol/rome-dex) böyle yazılmıştır; rome-dex’in EVM lane’i ayrıca ham doğrudan `invoke` şekil B akışını da sunar. Aynı tek-delege maliyetiyle (bölüm 3) A ile aynı yetkiye ihtiyaç duyar ve çekme adımı yoktur.

Bu kılavuzun geri kalanı A’yı izler; C aynı yetkiyi ve aynı imzalama kuralını kullanır.

## 3. Tokenlar içeri, tokenlar dışarı

Rome üzerindeki USDC, iki taraftan görülen tek bir SPL mint’idir: EVM tarafındaki `wUSDC` ERC-20 sarmalayıcısı ve Solana tarafındaki harici yetkinin ATA’sı. Bir kullanıcının kendi adresi için bu ikisi aynı bakiyedir: `wUSDC.balanceOf(user)` kullanıcının ATA’sını okur. Arada bir köprü ya da sarmalama adımı yoktur.

**Bir sözleşmenin sarmalayıcı bakiyesi, sözleşmenin kontrol ettiği bir token hesabı değildir.** Fabrika, `SPL_ERC20_cached` normal bir mint için dağıtır ve Hadrian’ın `wUSDC` bunu yapar. O sarmalayıcı bir sözleşme adına imzalayamaz; bu yüzden `wUSDC.transferFrom(user, adapter, amount)` veya `transfer` bir sözleşmeye token gönderdiğinde, SPL tokenlar **sarmalayıcının kendi emanet token hesabına** (`escrow_ata()`), taşınır ve sarmalayıcı miktarı kendi depolamasında sözleşme başına kaydeder. `wUSDC.balanceOf(adapter)` o kaydı, bir emanet defterini döndürür; `external_auth(adapter)`ait bir token hesabının bakiyesi değildir. Adapter’ınız bu tokenları CPI ile programınıza veremez; onlar ancak tekrar sarmalayıcı üzerinden dışarı çıkabilir. Bu yüzden kendisini `transferFrom` ile fonlayan bir adapter’ın Solana tarafında harcayabileceği hiçbir şey kalmaz.

İşe yarayan yol bir SPL delegasyonudur:

* **Yetki verin.** Kullanıcı `approve_spl(adapter, amount, mint)` bir işlem olarak **doğrudan HelperProgram’a** (`to = 0xff…09`, burada `mint` sarmalayıcının `mint_id()`değeridir. Kullanıcının kendi yetkisi imzalar ve kullanıcının token hesabına ayarladığı delege, adapter’ın harici yetkisidir.
* **İçeri.** Adapter’ın `deposit(amount)` delege aşırı yüklemesiyle çeker `HelperProgram.transfer_spl(srcAta, dstAta, amount, mint)`, kaynak olarak kullanıcının ATA’sını ve hedef olarak adapter’ın kendi ATA’sını (`HelperProgram.ata(address(this), mint)`, bir kez `create_ata`ile oluşturulan) kullanır. Adapter’ın yetkisi delege olarak imzalar. Tokenlar artık `external_auth(adapter)`ait bir token hesabındadır; CPI’nızın adlandırdığı hesap budur, imzalayan ve kaynak adapter’ın kendi hesabıdır, bu yüzden başka bir izin gerekmez. Bunlar `wUSDC.balanceOf(adapter)`.
* **Dışarı.** Programınızın withdraw instruction’ı **kullanıcının** ATA’sına transfer eder, `HelperProgram.ata(user, mint)`. Alma işlemi için kullanıcıdan imza gerekmez ve bakiye hemen `wUSDC.balanceOf(user)`olarak görünür. ATA henüz olmayabilir ise önce `HelperProgram.create_ata(user, mint)` ile oluşturun (idempotent).

**Bir token hesabının tek bir delegesi vardır.** Yukarıdaki yetki, o hesap üzerindeki sarmalayıcının kendi yetkisinin yerini alır. Kullanıcı sarmalayıcıya yeniden yetki verene kadar, adreslerinden çıkan her işlem SPL hatası `wUSDC` `transfer` veya `transferFrom` ile geri alınır `0x4`ile. Bu yetkiyi kullanan herhangi bir akıştan sonra `wUSDC.isEnabled(user)`çağrısını yapın; `false`döndürürse kullanıcıdan tekrar `approve_spl(wrapper, 2^64-1, mint)` göndermesini isteyin; bu, sarmalayıcının etrafında tasarlandığı aynı azami yetkidir (bkz. [Tek seferlik: sarmalayıcıya yetki verin](/tr/gelistirici-kilavuzlari/dual-lane-app.md#one-time-grant-the-wrapper)). Sınırlı bir yetki, azaldığında kullanıcının olağan `wUSDC` transferlerini tekrar bozacaktır ve `isEnabled` kalmaya devam eder `true` onun bir kısmı kaldığı sürece, bu yüzden uygulama ne zaman tekrar soracağını bilemez.

Bir mint’in hangi sarmalayıcıya sahip olduğunu kontrol etmek için fabrikanın `wrapper_kind_by_mint(mint)` 'ini okuyun (fabrika adresi zincirin `contracts.json` içinde [registry](https://github.com/rome-protocol/rome-registry)). `1` bu bölümün anlattığı önbelleğe alınmış sarmalayıcıdır. `2` Token-2022 mint’i için etkinleştirilmiş bir transfer kancasıyla fabrikanın dağıttığı doğrudan-CPI sarmalayıcıdır; bu kılavuz bunu kapsamaz. Kayıt defterinin `tokens.json` sarmalayıcı adresini ve mint’i listeler, ancak hangi tür olduğunu belirtmez.

## 4. Sözleşme başına ve işlem başına bir hat

Rome’un Solana durumunu değiştiren iki ön derleme ailesi vardır ve **bir işlem bunlardan tam olarak birini kullanır** — çalışma zamanı, sözleşmeler arasında bile olsa her iki taraftan gelen değiştirici çağrıları karıştıran bir işlemi reddeder.

| Hat        | Ön derlemeler                                                                                       | Etkiler ulaşır                                                                              | Yinelemeli yürütmede çalışır                                                      |
| ---------- | --------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------- |
| **Legacy** | `CpiProgram` `0xff…08` (`invoke`, `invoke_signed`), `HelperProgram` `0xff…09`, `Çekim` `0x42…16`    | Hemen, EVM adımı içinde gerçek bir CPI olarak                                               | **Hayır** — yinelemeli bir işlem içindeki legacy CPI `CpiProhibitedInIterativeTx` |
| **Cached** | `SplCached` `0xff…05`, `ASplCached` `0xff…06`, `SystemCached` `0xff…04`, `WithdrawCached` `0xff…0b` | Bir katmanda sahnelenir ve işlemin sonunda CPI olarak işlenir; bir EVM revert’i onları atar | Evet                                                                              |

Bir program entegrasyonu için bunun anlamı şudur:

* **Kendi programınızın instruction’larını çağırmak yalnızca legacy-track’te mümkündür.** Önbelleğe alınmış hatta genel bir `invoke`yoktur; SPL transferlerini, ATA oluşturmayı, sistem programı işlemlerini ve gas çekimini kapsar.
* Bu yüzden adapter’ı fonlayan adım, CPI ile aynı işlemde çalışıyorsa legacy-track’te de olmalıdır. Önbelleğe alınmış sarmalayıcının `transferFrom` çağrısı cached-track’te bir çağrıdır; bu yüzden sizin CPI’nızla aynı işlemi paylaşamaz (ve bölüm 3’ün gösterdiği gibi, yalnızca bir emanet defterine kredi yazar). `HelperProgram.transfer_spl(userAta, adapterAta, amount, mint)` ile çekin; bunu, kullanıcı adapter’ı SPL delege yaptıktan sonra yapın (`approve_spl`), kullanıcı tarafından doğrudan HelperProgram’a gönderilir. Çekme ve CPI ikisi de legacy-track’tedir, bu yüzden tek bir işlemde çalışırlar.
* **Sarmalayıcıyı bu işlemin dışında tutun.** Sarmalayıcının değiştirici işlevlerini (`wUSDC.transfer`, `transferFrom`) aynı işlem içinde, legacy CPI ile birlikte adapter’dan çağırmayın. `isEnabled(user)` ve bakiyeleri ön uçtan `eth_call`.
* **İşlem de atomik olmak zorundadır.** Tasarımın altında bulunduğu sınır budur.

Okumalar bu kuralın dışındadır: `account_info`, `account_data_at`, `account_u64_at`, `account_lamports`, `pdas_batch_derive` ve `HelperProgram.user_balance` / `allowance_of` önceden yüklenmiş hesapların okumalarıdır (CPI yok), her iki hatta ve her iki yürütme kipinde de izinlidir. Ön kontrollerinizi bunlarla yapın. Tek bir sıralama kuralı vardır: bir işlemde önbelleğe alınmış bir değişiklik tetiklendikten sonra, legacy-track okumalar geri kalanı için engellenir — önce oku, sonra değiştir.

## 5. Atomiklik bütçedir

Atomik bir Rome işlemi tek bir Solana işlemidir: yaklaşık **1,4M compute unit**, **64 adresli** hesap listesi ve **4 KB** kablo boyutu (Solana v1 işlemleri). Rome programı ve sizin CPI’nız bu bütçeyi paylaşır. Bir sarmalayıcı transferi Hadrian üzerinde yaklaşık 170K CU çalışır ve instruction’ınız kendi payını ekler; ölçümü Solana fişindeki `computeUnitsConsumed`ile yapın, EVM ile değil `gasUsed`.

Emülasyon bir işlemin sığmadığına karar verdiğinde, Rome onu **yinelemeli olarak** birkaç Solana işlemi boyunca çalıştırır ve içindeki legacy CPI sonra başarısız olur. Hem deposit hem withdraw adımını tek bir token hareketi ve programınıza tek bir CPI ile sınırlı tutun ve etraflarındaki Solidity’yi küçük tutun. Daha büyük olan her şeyi iki kullanıcı işlemine bölün.

CPI derinliği: Solana 4 seviyeye izin verir ve Rome birini kullanır; bu yüzden instruction’ınız 2. seviyede, altında iki seviye olacak şekilde çalışır (sizin programınız → SPL Token bir seviye bırakır).

## 6. Hesap sağlama

Programınız çalışma zamanında hesaplarını Solidity’den almaz. Proxy **emüle eder** göndermeden önce her işlemi, CPI’ların dokunduğu tüm Solana hesaplarını kaydeder ve bunları Solana işlemine yerleştirir. Adapter’ınız hesapları `invoke_signed` hesap listesinde adlandırır; emülasyon bunların çözümlendiğini kanıtlar. Buradan üç sonuç çıkar:

* Instruction’ınızın dokunduğu her hesap, adapter’ın elindeki girdilerden türetilebilir olmalıdır (kendi PDA’sı ve alt-PDA’ları, program kimliğiniz, mint’ler, kullanıcının adresi). `SystemProgram.find_program_address` ve `CpiProgram.pdas_batch_derive` türetmeleri Solidity içinde yapar.
* Henüz var olmayan bir hesap (yeni bir pozisyon, yeni bir ATA) yine de hesap listesinde adlandırılmalıdır; Solana işlemine ulaşan şey onun adresidir.
* İşlemin dokunduğu her şey — kullanıcı, adapter ve sarmalayıcı için Rome’un kendi hesapları dahil — 64 adresin altında kalmalıdır. Tek bir çağrıda on piyasaya dokunan bir tasarım sığmaz.

Solana cüzdanı hattı için, `rome_emulateCallAccounts` aynı keşfi bir istemciye sunar; SDK bunu kullanır.

Bir CPI’nin asla adlandıramayacağı iki hesap vardır: işlemi gönderen Solana fee payer’ı (düz bir System transfer instruction’ı içi hariç) ve Rome programının kendisi. Rome programına geri dönen bir CPI reddedilir.

## 7. Solidity ile bir deposit ve bir withdraw

Legacy track üzerinde bir adapter için minimal bir taslak. Kullanıcı çoktan `approve_spl(adapter, amount, mint)` HelperProgram’a göndermiştir (bölüm 3). `PRIVACY_PROGRAM` program kimliğinizdir; `encodeDeposit` / `encodeWithdraw` instruction verinizi oluşturur (Borsh, little-endian); account meta’lar instruction’ınızın düzenini izler.

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

contract PrivacyAdapter {
    ICrossProgramInvocation constant Cpi    = ICrossProgramInvocation(0xFF00000000000000000000000000000000000008);
    IHelperProgram          constant Helper = IHelperProgram(0xFF00000000000000000000000000000000000009);
    bytes32 constant SPL_TOKEN = 0x06ddf6e1d765a193d9cbe146ceeb79ac1cb485ed5f5b37913a8cf5857eff00a9; // TokenkegQ...

    bytes32 immutable PRIVACY_PROGRAM;
    bytes32 immutable USDC_MINT;

    constructor(bytes32 program, bytes32 mint) {
        PRIVACY_PROGRAM = program; USDC_MINT = mint;
        Helper.create_pda(address(this));                 // adapter’ın kendi Solana kimliği
        Helper.create_ata(address(this), USDC_MINT);      // ve sahip olduğu bir USDC hesabı
    }

    function _salt(address user) internal pure returns (bytes32) { return bytes32(uint256(uint160(user))); }

    function deposit(uint64 amount) external {
        bytes32 self       = Helper.pda(address(this));                   // imzalayan: adapter’ın yetkisi
        bytes32 adapterAta = Helper.ata(address(this), USDC_MINT);
        bytes32 position   = Helper.pda_with_salt(address(this), _salt(msg.sender)); // kullanıcı başına alt-PDA, o da imzalar

        // Kullanıcının token hesabından çeker. Adapter’ın yetkisi SPL
        // delege olarak imzalar; bu aşağıdaki CPI gibi legacy-track bir çağrıdır.
        Helper.transfer_spl(Helper.ata(msg.sender, USDC_MINT), adapterAta, amount, USDC_MINT);

        ICrossProgramInvocation.AccountMeta[] memory accs = new ICrossProgramInvocation.AccountMeta[](5);
        accs[0] = ICrossProgramInvocation.AccountMeta(self,       true,  true);
        accs[1] = ICrossProgramInvocation.AccountMeta(position,   true,  true);
        accs[2] = ICrossProgramInvocation.AccountMeta(adapterAta, false, true);                          // kaynak: adapter’ın yetkisine aittir
        accs[3] = ICrossProgramInvocation.AccountMeta(_vaultFor(position), false, true);                 // programınızın kasası
        accs[4] = ICrossProgramInvocation.AccountMeta(SPL_TOKEN, false, false);

        bytes32[] memory salts = new bytes32[](1);
        salts[0] = _salt(msg.sender);
        Cpi.invoke_signed(PRIVACY_PROGRAM, accs, encodeDeposit(amount), salts);
    }

    function withdraw(uint64 amount) external {
        bytes32 position = Helper.pda_with_salt(address(this), _salt(msg.sender));
        bytes32 userAta  = Helper.ata(msg.sender, USDC_MINT);            // hedef: kullanıcının kendi hesabı
        // ... aynı şekil: programınız kasadan userAta’ya `amount` taşır, `position` tarafından imzalanır
        Cpi.invoke_signed(PRIVACY_PROGRAM, accs, encodeWithdraw(amount), salts);
    }
}
```

Adapter hiçbir zaman `wUSDC` sözleşmeyi çağırmaz. Çekme, kullanıcının delegasyonunu harcayan bir HelperProgram çağrısıdır ve tokenlar `external_auth(adapter)` sahip olduğu bir token hesabında durur; CPI’nın onları harcayabilmesinin nedeni budur.

İmzalayıcı üzerine notlar. Rome tam olarak iki tür hesap için imzalar: çağıran sözleşmenin çıplak yetkisi (`Helper.pda(address(this))`), bu hesap salts içinde listelenmeden imzalar, ve salts içindeki her giriş için bir tuzlanmış alt-PDA. Listelediğiniz her tuz, hesap listesinde imzalayıcı olarak görünmelidir; aksi halde çağrı `salts`için sağlanan tohumdan hesaplanan imzalayıcı hesabı bulunamadı `salts`. İmzalayıcı olarak işaretlenen diğer herhangi bir hesap, kullanıcının kendi yetkisi dahil, Rome’dan tohum almaz ve Solana çalışma zamanı CPI’yı reddeder. Kullanıcının tokenları üzerindeki hakları delegasyondan gelir, asla adapter’ın kullanıcı gibi imzalamasından gelmez. `sağlanan tohumdan hesaplanan imzalayıcı hesabı bulunamadı`. İmzalayıcı olarak işaretlenen diğer herhangi bir hesap, kullanıcının kendi yetkisi dahil, Rome’dan tohum almaz ve Solana çalışma zamanı CPI’yı reddeder. Kullanıcının tokenları üzerindeki hakları delegasyondan gelir, asla adapter’ın kullanıcı gibi imzalamasından gelmez.

Çekmeden delegasyon: eğer programınız doğrudan kullanıcının token hesabından harcama yapacaksa, kullanıcı `HelperProgram.approve_spl_raw_delegate(userAta, yourProgramPda, amount, mint, decimals)` işlevini doğrudan HelperProgram’a gönderir ve programınızın PDA’sını SPL delege olarak adlandırır. Rome köprüsü bunu Wormhole için kullanır. Bölüm 3’teki tek-delege kuralı burada da geçerlidir: yetki, sarmalayıcının yetkisini yerinden eder.

## 8. Test etme

* Şuna dağıtım yapın **Hadrian** (testnet, zincir 200010) önce; adresler ve RPC içinde [Sözleşme Adresleri](/tr/referans/contract-addresses.md) ve [registry](https://github.com/rome-protocol/rome-registry).
* `eth_call` ve `eth_estimateGas` proxy'nin gönderme için kullandığı aynı emülasyonu çalıştırın; böylece orada başarısız olan bir CPI, zincir üzerinde de aynı nedenle başarısız olur ve revert verisi temel Solana hatasını taşır (`evm dışı çağrı hatası: …` Solana program günlüğünde).
* Gerçekleşen bir EVM işleminin Solana tarafını şununla okuyun: `rome_solanaTxForEvmTx(hash)`; Solana fişi, CU ve programınızın günlüklerinin bulunduğu yerdir.
* şurada çalışan bir CPI `eth_call` ama gönderildiğinde reddedilen bir şey, genellikle emülasyonun bildirdiği bir sınırı aşmıştır: 64 adres sınırı, atomik CU bütçesi (işlem iteratif hale geldi) veya izleme kuralı.

## 9. Referans

* [Ön derleme referansı](/tr/referans/precompiles.md) — her precompile üzerindeki her seçici, dağıtım sınıfı ve delegatecall kuralı ile.
* [Kısıtlamalar](/tr/temel-kavramlar/constraints.md) — yukarıdaki sınırlar tek tabloda.
* [Token Uyumluluğu](/tr/temel-kavramlar/token-interop.md) — sarmalayıcılar, kanonik mint'ler, yatırma ve çekme.
* Genel depolardaki referans uygulamalar: [cardo](https://github.com/rome-protocol/cardo) (kullanıcı CPI precompile'ını doğrudan çağırır, şekil B), [rome-dex](https://github.com/rome-protocol/rome-dex) (doğrudan `invoke` artı emanetsiz bir yönlendirici, şekil C), ve [aerarium](https://github.com/rome-protocol/aerarium) (ortak bir piyasa üzerinde bir Compound III borç verme uygulaması; Solidity'den Solana programlarını çağırmaz (CPI yok), bu yüzden bir adaptör örneği değildir).


---

# 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/tr/gelistirici-kilavuzlari/integrate-solana-program.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.
