Yanlış adrese fon göndermek kalıcı kayba yol açabilir. Adres doğrulama, yalnızca fonları düzgün şekilde alıp erişebilecek adreslere göndermenizi sağlar.
Doğrulama, ne gönderdiğinize bağlıdır:
- SPL token'ları kısmen kendi kendini korur. Token Program, hesapları beklenen mint ile eşleşmeyen bir transferi reddeder; bu nedenle yanlış yönlendirilmiş bir token transferi fon kaybı olmadan başarısız olur. Bu sayfanın büyük bölümü SPL token gönderimleri ile ilgilidir.
- Yerel SOL için böyle bir koruma yoktur. System Program transferi herhangi bir hesaba başarıyla gerçekleşir; bu nedenle yanlış bir alıcı SOL'u kalıcı olarak kilitler. Bkz. Yerel SOL Gönderimi.
Temel ödeme kavramları için bkz. Solana'da Ödemeler Nasıl Çalışır.
Solana Adreslerini Anlamak
Solana hesaplarının iki tür adresi vardır: eğri üzerinde (on-curve) ve eğri dışında (off-curve).
Eğri Üzerindeki Adresler (On-Curve)
Standart adresler, Ed25519 keypair'lerinden elde edilen açık anahtarlardır. Bu adresler:
- İşlemleri imzalayabilen karşılık gelen bir özel anahtara sahiptir
- Cüzdan adresi olarak kullanılır
Eğri Dışı Adresler (PDA'lar)
Program Derived Address'ler, bir program kimliği ve tohumlardan deterministik olarak türetilir. Bu adresler:
- Karşılık gelen bir özel anahtara sahip değildir
- Yalnızca adresin türetildiği program tarafından imzalanabilir
Ödemelerde Hesap Türleri
Ağdan bir hesap çekmek için adresi kullanın; adresi nasıl işleyeceğinizi belirlemek için program sahibini ve hesap türünü kontrol edin.
Bir adresin eğri üzerinde mi yoksa eğri dışında mı olduğunu bilmek, hesabın türünü, hangi programın sahibi olduğunu veya o adreste bir hesabın var olup olmadığını söylemez. Bu ayrıntıları belirlemek için hesabı ağdan çekmeniz gerekir.
System Program Hesapları (Cüzdanlar)
System Program tarafından sahip olunan hesaplar standart cüzdanlardır. Bir cüzdana SPL token göndermek için, onun Associated Token Account (ATA)'ını türetip kullanmanız gerekir.
ATA adresini türettikten sonra, token account'ın zincir üzerinde var olup olmadığını kontrol edin. ATA mevcut değilse, transfer işlemiyle aynı işlem içinde alıcının token account'ını oluşturmak için bir talimat ekleyebilirsiniz. Ancak bu, yeni token account için rent ödenmesini gerektirir. Alıcı ATA'ya sahip olduğundan, rent için ödenen SOL gönderici tarafından geri alınamaz.
Güvenlik önlemleri olmadan, ATA oluşturma maliyetinin karşılanması istismar edilebilir. Kötü niyetli bir kullanıcı transfer talep edebilir, ATA'sını sizin hesabınıza oluşturabilir, rent SOL'unu geri almak için ATA'yı kapatabilir ve bunu tekrarlayabilir.
Token Hesapları
Token account'lar, Token Program veya Token-2022 Program tarafından sahiplenilir ve token bakiyelerini tutar. Aldığınız adres bir token programına aitse, token göndermeden önce hesabın bir token account olduğunu (mint account değil) ve beklenen token mint account ile eşleştiğini doğrulamalısınız.
Token Program'lar, bir transferdeki her iki token account'ın da aynı mint'e ait token tuttuğunu otomatik olarak doğrular. Doğrulama başarısız olursa işlem reddedilir ve hiçbir varlık kaybolmaz.
Mint Hesapları
Mint account'lar, belirli bir tokenın arzını ve meta verilerini takip eder. Mint account'lar da Token Program'lar tarafından sahiplenilir, ancak token transferleri için geçerli alıcılar değildir. Bir mint adresine token göndermeye çalışmak başarısız bir işlemle sonuçlanır, ancak hiçbir varlık kaybolmaz.
Diğer Hesaplar
Diğer programlara ait hesaplar için bir politika kararı gerekmektedir. Bazı hesaplar (örn. multisig cüzdanlar) geçerli token account sahipleri olabilirken, diğerleri reddedilmelidir.
Yerel SOL Gönderimi
Yukarıdaki sınıflandırma, SPL tokenlarının nereye gönderebileceğini belirler. Yerel SOL daha kısıtlıdır: tek güvenli alıcı, bir System Program cüzdanı (ya da bir System Program cüzdanına dönüşen, fonlanmamış eğri üzeri bir adres) olmalıdır.
Bir System Program transferi, mintler, token accountlar, programlar ve PDA'lar dahil olmak üzere herhangi bir hesaba lamport ekler. Lamportlar yalnızca hesabın sahibi olan program tarafından çıkarılabilir; bu nedenle SOL'un yanlış bir alıcıya gönderilmesi, fonların kalıcı olarak kaybedilmesine yol açabilir.
Bir SPL token transferinin aksine, alıcı beklenmedik bir adres olduğunda işlem başarısız olmaz.
Yerel SOL gönderilirken yalnızca IS_WALLET sonucu kabul edilebilirdir.
IS_TOKEN_ACCOUNT ise kabul edilemez: bir token account, SPL tokenları
barındırır ve oraya gönderilen SOL, gönderenin kontrolü dışına çıkar.
Bu, SOL'un kaybolmasının yaygın bir yoludur: bir kullanıcı, token'ın mint adresini (veya bir program adresini) SOL çekme işlemine yapıştırır. Transfer başarıyla tamamlanır ve SOL kurtarılamaz. Bir SOL transferini imzalamadan önce her zaman alıcıyı sınıflandırın.
Doğrulama Akışı
Aşağıdaki diyagram, bir adresi doğrulamak için referans karar ağacını göstermektedir:
Hesabı Getir
Ağdan hesap ayrıntılarını getirmek için adresi kullanın.
Hesap Mevcut Değil
Bu adreste herhangi bir hesap yoksa, adresin eğri üzerinde mi yoksa eğri dışında mı olduğunu kontrol edin:
-
Eğri dışı (PDA): Erişilemeyen bir ATA'ya gönderim yapmaktan kaçınmak için adresi ihtiyatlı bir şekilde reddedin. Mevcut bir hesap olmadan, yalnızca adresten bu PDA'nın hangi program tarafından türetildiğini veya adresin bir ATA için olup olmadığını belirleyemezsiniz. Token göndermek amacıyla bu adres için bir ATA türetmek, fonların erişilemeyen bir token account içinde kilitlenmesine yol açabilir.
-
Eğri üzerinde: Bu, henüz fonlanmamış geçerli bir cüzdan adresidir (public key). ATA'yı türetin, var olup olmadığını kontrol edin ve token'ları gönderin. ATA mevcut değilse oluşturulmasını finanse edip etmeyeceğinize dair bir politika kararı vermeniz gerekir.
Hesap mevcut
Bir hesap mevcutsa, hangi programın sahibi olduğunu kontrol edin:
-
System Program: Bu standart bir cüzdandır. ATA'yı türetin, var olup olmadığını kontrol edin ve token'ları gönderin. ATA mevcut değilse oluşturulmasını finanse edip etmeyeceğinize dair bir politika kararı vermeniz gerekir.
-
Token Program / Token-2022: Hesabın bir token account olduğunu (mint account değil) ve göndermek istediğiniz token'ı (mint) barındırdığını doğrulayın. Geçerliyse, token'ları doğrudan bu adrese gönderin. Eğer bu bir mint account veya farklı bir mint'e ait bir token account ise adresi reddedin.
-
Diğer Programlar: Bu bir politika kararı gerektirir. Multisig cüzdanlar gibi bazı programlar, token account'larının kabul edilebilir sahipleri olabilir. Politikanız izin veriyorsa ATA'yı türetin ve gönderin. Aksi takdirde adresi reddedin.
Demo
Aşağıdaki örnek yalnızca adres doğrulama mantığını göstermektedir. Bu, yalnızca açıklama amacıyla hazırlanmış referans kodudur.
Demo, bir ATA türetmeyi veya token göndermek için bir işlem oluşturmayı göstermemektedir. Örnek kod için token account ve token transfer belgelerine başvurun.
Aşağıdaki demo üç olası sonucu kullanmaktadır:
| Sonuç | Anlam | İşlem |
|---|---|---|
IS_WALLET | Geçerli cüzdan adresi | associated token account'a türet ve gönder |
IS_TOKEN_ACCOUNT | Geçerli token account | Token'ları doğrudan bu adrese gönder |
REJECT | Geçersiz adres | Gönderme |
Ardından her sonucu, canReceiveNativeSol (yalnızca cüzdanlar) ve
canReceiveSplToken (cüzdanlar veya token account'lar) ile varlık başına kabul
edilebilirlik olarak eşler. Bir token account, IS_TOKEN_ACCOUNT döndürür; bu
nedenle SPL token'larını alabilir ancak yerel SOL'u alamaz — bu ayrım,
SOL'un kilitlenmesini önler.
/*** Validates an input address and classifies it as a wallet, token account, or invalid.** @param inputAddress - The address to validate* @param rpc - Optional RPC client (defaults to mainnet)* @returns Classification result:* - IS_WALLET: Valid wallet address* - IS_TOKEN_ACCOUNT: Valid token account* - REJECT: Invalid address for transfers*/export async function validateAddress(inputAddress: Address,rpc: Rpc<GetAccountInfoApi> = defaultRpc): Promise<ValidationResult> {const account = await fetchJsonParsedAccount(rpc, inputAddress);// Log the account data for democonsole.log("\nAccount:", account);// Account doesn't exist onchainif (!account.exists) {// Off-curve = PDA that doesn't exist as an account// Reject conservatively to avoid sending to an address that may be inaccessible.if (isOffCurveAddress(inputAddress)) {return { type: "REJECT", reason: "PDA doesn't exist as an account" };}// On-curve = valid keypair address, treat as unfunded walletreturn { type: "IS_WALLET" };}// Account exists, check program ownerconst owner = account.programAddress;// System Program = walletif (owner === SYSTEM_PROGRAM) {return { type: "IS_WALLET" };}// Token Program or Token-2022, check if token accountif (owner === TOKEN_PROGRAM || owner === TOKEN_2022_PROGRAM) {const accountType = (account.data as { parsedAccountMeta?: { type?: string } }).parsedAccountMeta?.type;if (accountType === "account") {return { type: "IS_TOKEN_ACCOUNT" };}// Reject if not a token account (mint account)return {type: "REJECT",reason: "Not a token account"};}// Unknown program ownerreturn { type: "REJECT", reason: "Unknown program owner" };}/*** Native SOL is only safe to send to a wallet. Any other account locks it.*/function canReceiveNativeSol(result: ValidationResult): boolean {return result.type === "IS_WALLET";}/*** SPL tokens can go to a wallet (via its ATA) or directly to a token account.*/function canReceiveSplToken(result: ValidationResult): boolean {return result.type === "IS_WALLET" || result.type === "IS_TOKEN_ACCOUNT";}// =============================================================================// Examples// =============================================================================
Is this page helpful?