Mengirim dana ke alamat yang salah dapat mengakibatkan kehilangan permanen. Verifikasi alamat memastikan Anda hanya mengirim ke alamat yang dapat menerima dan mengakses dana dengan benar.
Validasi bergantung pada apa yang Anda kirim:
- Token SPL sebagian bersifat melindungi diri sendiri. Token Program menolak transfer yang akunnya tidak sesuai dengan mint yang diharapkan, sehingga transfer token yang salah arah gagal tanpa kehilangan dana. Sebagian besar halaman ini membahas pengiriman token SPL.
- SOL native tidak memiliki perlindungan seperti itu. Transfer System Program berhasil masuk ke akun mana pun, sehingga penerima yang salah akan mengunci SOL secara permanen. Lihat Mengirim SOL native.
Lihat Cara Pembayaran Bekerja di Solana untuk konsep pembayaran inti.
Memahami Alamat Solana
Akun Solana memiliki dua jenis alamat, yaitu on-curve dan off-curve.
Alamat On-Curve
Alamat standar adalah kunci publik dari keypair Ed25519. Alamat-alamat ini:
- Memiliki kunci privat yang dapat menandatangani transaksi
- Digunakan sebagai alamat dompet
Alamat Off-Curve (PDA)
Program Derived Address diturunkan secara deterministik dari ID program dan seed. Alamat-alamat ini:
- Tidak memiliki kunci privat yang sesuai
- Hanya dapat ditandatangani oleh program tempat alamat tersebut diturunkan
Jenis Akun dalam Pembayaran
Gunakan alamat untuk mengambil akun dari jaringan, periksa pemilik program dan jenis akunnya untuk menentukan cara menangani alamat tersebut.
Mengetahui apakah suatu alamat berada on-curve atau off-curve tidak memberi tahu Anda jenis akun apa itu, program apa yang memilikinya, atau apakah akun ada di alamat tersebut. Anda harus mengambil akun dari jaringan untuk menentukan detail ini.
Akun System Program (Dompet)
Akun yang dimiliki oleh System Program adalah dompet standar. Untuk mengirim token SPL ke sebuah dompet, Anda perlu menurunkan dan menggunakan Associated Token Account (ATA)-nya.
Setelah menurunkan alamat ATA, periksa apakah token account tersebut sudah ada di onchain. Jika ATA belum ada, Anda dapat menyertakan instruksi untuk membuat token account penerima dalam transaksi yang sama dengan transfer. Namun, hal ini mengharuskan pembayaran rent untuk token account baru tersebut. Karena penerima yang memiliki ATA, SOL yang dibayarkan untuk rent tidak dapat dikembalikan kepada pengirim.
Tanpa pengamanan yang memadai, subsidi pembuatan ATA dapat dieksploitasi. Pengguna yang berniat jahat dapat meminta transfer, membuat ATA mereka atas biaya Anda, menutup ATA untuk mengklaim kembali SOL dari rent, lalu mengulanginya.
Token Accounts
Token accounts dimiliki oleh Token Program atau Token-2022 Program dan menyimpan saldo token. Jika alamat yang Anda terima dimiliki oleh token program, Anda harus memverifikasi bahwa akun tersebut adalah token account (bukan mint account) dan sesuai dengan mint account token yang diharapkan sebelum mengirim.
Token Programs secara otomatis memvalidasi bahwa kedua token account dalam sebuah transfer menyimpan token dari mint yang sama. Jika validasi gagal, transaksi akan ditolak dan tidak ada dana yang hilang.
Mint Accounts
Mint accounts melacak pasokan token dan metadata dari token tertentu. Mint accounts juga dimiliki oleh Token Programs, tetapi tidak dapat menjadi penerima yang valid untuk transfer token. Mencoba mengirim token ke alamat mint akan menghasilkan transaksi yang gagal, namun tidak ada dana yang hilang.
Akun Lainnya
Akun yang dimiliki oleh program lain memerlukan keputusan kebijakan. Beberapa akun (misalnya dompet multisig) mungkin merupakan pemilik token account yang valid, sementara yang lain sebaiknya ditolak.
Mengirim SOL Native
Klasifikasi di atas menentukan ke mana token SPL dapat dikirim. SOL native lebih ketat: satu-satunya penerima yang aman adalah dompet System Program (atau alamat on-curve yang belum didanai yang nantinya menjadi satu).
Transfer System Program menambahkan lamport ke akun mana pun, termasuk mint, token account, program, dan PDA. Lamport hanya dapat dipindahkan keluar oleh program pemilik akun, sehingga mengirim SOL ke penerima yang salah dapat mengakibatkan dana hilang secara permanen.
Tidak seperti transfer token SPL, transaksi tidak gagal ketika penerima adalah alamat yang tidak terduga.
Saat mengirim SOL native, hanya hasil IS_WALLET yang dapat diterima.
IS_TOKEN_ACCOUNT tidak: sebuah token account menyimpan token SPL, dan SOL
yang dikirim ke sana berada di luar kendali pengirim.
Ini adalah cara umum SOL hilang: pengguna menempel alamat mint token (atau alamat program) ke dalam penarikan SOL. Transfer berhasil dan SOL tidak dapat dipulihkan. Selalu klasifikasikan penerima sebelum menandatangani transfer SOL.
Alur Verifikasi
Diagram berikut menunjukkan pohon keputusan referensi untuk memvalidasi sebuah alamat:
Ambil Akun
Gunakan alamat untuk mengambil detail akun dari jaringan.
Akun Tidak Ada
Jika tidak ada akun di alamat ini, periksa apakah alamat tersebut berada on-curve atau off-curve:
-
Off-curve (PDA): Tolak alamat secara konservatif untuk menghindari pengiriman ke ATA yang mungkin tidak dapat diakses. Tanpa akun yang sudah ada, Anda tidak dapat menentukan hanya dari alamat tersebut program mana yang menurunkan PDA ini atau apakah alamat tersebut untuk sebuah ATA. Menurunkan ATA untuk alamat ini guna mengirim token dapat mengakibatkan dana terkunci di dalam token account yang tidak dapat diakses.
-
On-curve: Ini adalah alamat dompet valid (kunci publik) yang belum didanai. Turunkan ATA, periksa apakah ada, dan kirim token ke sana. Anda harus membuat keputusan kebijakan apakah akan mendanai pembuatan ATA jika belum ada.
Akun ada
Jika akun ada, periksa program mana yang memilikinya:
-
System Program: Ini adalah dompet standar. Turunkan ATA, periksa apakah ada, dan kirim token ke sana. Anda harus membuat keputusan kebijakan apakah akan mendanai pembuatan ATA jika belum ada.
-
Token Program / Token-2022: Verifikasi bahwa akun tersebut adalah token account (bukan mint account) dan bahwa akun tersebut menyimpan token (mint) yang ingin Anda kirim. Jika valid, kirim token langsung ke alamat ini. Jika itu adalah mint account atau token account untuk mint yang berbeda, tolak alamat tersebut.
-
Program Lain: Ini memerlukan keputusan kebijakan. Beberapa program seperti dompet multisig mungkin merupakan pemilik token account yang dapat diterima. Jika kebijakan Anda mengizinkannya, turunkan ATA dan kirim. Jika tidak, tolak alamat tersebut.
Demo
Contoh berikut hanya menampilkan logika validasi alamat. Ini adalah kode referensi untuk tujuan ilustrasi.
Demo tidak menampilkan cara menurunkan ATA atau membangun transaksi untuk mengirim token. Lihat dokumentasi token account dan transfer token untuk contoh kode.
Demo di bawah ini menggunakan tiga kemungkinan hasil:
| Result | Meaning | Action |
|---|---|---|
IS_WALLET | Alamat dompet valid | Turunkan dan kirim ke associated token account |
IS_TOKEN_ACCOUNT | Token account valid | Kirim token langsung ke alamat ini |
REJECT | Alamat tidak valid | Jangan kirim |
Kemudian memetakan setiap hasil ke akseptabilitas per aset dengan
canReceiveNativeSol (khusus dompet) dan canReceiveSplToken (dompet atau
token account). Sebuah associated token account mengembalikan
IS_TOKEN_ACCOUNT, sehingga dapat menerima token SPL tetapi tidak SOL
native — perbedaan yang mencegah SOL terkunci.
/*** 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?