Відправлення коштів на неправильну адресу може призвести до їх безповоротної втрати. Перевірка адреси гарантує, що ви надсилаєте кошти лише на адреси, які можуть їх належним чином отримати та використати.
Перевірка залежить від того, що ви надсилаєте:
- SPL-токени частково захищені самостійно. Token Program відхиляє переказ, якщо акаунти не відповідають очікуваному mint, тому неправильно спрямований переказ токенів завершується невдачею без втрати коштів. Більша частина цієї сторінки присвячена відправленню SPL-токенів.
- Нативний SOL не має такого захисту. Переказ через System Program виконується на будь-який акаунт, тому SOL, надісланий на неправильного отримувача, блокується назавжди. Дивіться Відправлення нативного SOL.
Дивіться Як працюють платежі в Solana, щоб ознайомитися з основними концепціями платежів.
Розуміння адрес Solana
Акаунти Solana мають два типи адрес: on-curve та off-curve.
On-Curve адреси
Стандартні адреси — це публічні ключі з Ed25519 keypairs. Ці адреси:
- Мають відповідний приватний ключ, який може підписувати транзакції
- Використовуються як адреси гаманців
Off-Curve адреси (PDA)
Program Derived Addresses детерміновано виводяться з ідентифікатора програми та seeds. Ці адреси:
- Не мають відповідного приватного ключа
- Можуть підписуватися лише програмою, з якої було виведено адресу
Типи акаунтів у платежах
Використовуйте адресу для отримання акаунту з мережі, перевірте власника програми та тип акаунту, щоб визначити, як обробляти цю адресу.
Знання того, чи є адреса on-curve або off-curve, не вказує на тип акаунту, яка програма ним володіє або чи існує акаунт за цією адресою. Необхідно отримати акаунт з мережі, щоб з'ясувати ці деталі.
Акаунти System Program (Гаманці)
Акаунти, якими володіє System Program, є стандартними гаманцями. Щоб надіслати SPL-токени на гаманець, необхідно визначити та використати його Associated Token Account (ATA).
Після визначення адреси ATA перевірте, чи існує token account в мережі. Якщо ATA не існує, ви можете включити інструкцію зі створення token account отримувача в ту саму транзакцію, що й переказ. Однак це вимагає сплати rent за новий token account. Оскільки отримувач є власником ATA, SOL, сплачені за rent, не можуть бути повернені відправником.
Без належного захисту субсидування створення ATA може бути використане зловмисно. Недобросовісний користувач може запросити переказ, створити свій ATA за ваш рахунок, закрити ATA, щоб повернути rent SOL, і повторювати це знову.
Token Accounts
Token accounts знаходяться у власності Token Program або Token-2022 Program та зберігають баланси токенів. Якщо адреса, яку ви отримали, належить token program, слід перевірити, що акаунт є token account (а не mint account) і відповідає очікуваному token mint account перед надсиланням.
Token Programs автоматично перевіряють, що обидва token accounts у переказі містять токени одного й того самого mint. Якщо перевірка не проходить, транзакція відхиляється і жодні кошти не втрачаються.
Mint Accounts
Mint accounts відстежують постачання токенів та метадані конкретного токена. Mint accounts також належать Token Programs, але не є дійсними отримувачами для переказу токенів. Спроба надіслати токени на adresu mint призводить до невдалої транзакції, але жодні кошти не втрачаються.
Інші акаунти
Акаунти, якими володіють інші програми, потребують окремого рішення щодо політики. Деякі акаунти (наприклад, мультипідписні гаманці) можуть бути законними власниками token account, тоді як інші слід відхиляти.
Надсилання нативного SOL
Наведена вище класифікація визначає, куди можуть надходити SPL-токени. З нативним SOL все суворіше: єдиним безпечним одержувачем є гаманець System Program (або незаповнена адреса на кривій, яка ним стає).
Переказ через System Program додає lamport до будь-якого акаунту, включно з мінтами, token accounts, програмами та PDA. Lamport може виводити лише програма-власник акаунту, тому надсилання SOL на неправильну адресу може призвести до безповоротної втрати коштів.
На відміну від переказу SPL-токенів, транзакція не відхиляється, якщо одержувач є неочікуваною адресою.
При надсиланні нативного SOL прийнятним результатом є лише IS_WALLET.
IS_TOKEN_ACCOUNT не є таким: token account зберігає SPL-токени, і SOL,
надісланий туди, виходить з-під контролю відправника.
Це поширена причина втрати SOL: користувач вставляє адресу мінту токена (або адресу програми) у поле виведення SOL. Переказ виконується успішно, але SOL не підлягає поверненню. Завжди перевіряйте одержувача перед підписанням SOL-переказу.
Процес перевірки
На наступній діаграмі показано еталонне дерево рішень для перевірки адреси:
Отримання акаунту
Використайте адресу для отримання деталей акаунту з мережі.
Акаунт не існує
Якщо за цією адресою не існує жодного акаунту, перевірте, чи знаходиться адреса на кривій чи поза нею:
-
Поза кривою (PDA): З міркувань безпеки відхиліть адресу, щоб уникнути надсилання на ATA, який може бути недоступним. За відсутності наявного акаунту неможливо визначити лише за адресою, якою програмою було виведено цей PDA або чи є адреса ATA. Виведення ATA для цієї адреси з метою надсилання токенів може призвести до блокування коштів у недоступному token account.
-
На кривій: Це дійсна адреса гаманця (публічний ключ), яка ще не поповнена. Отримайте ATA, перевірте, чи він існує, і надішліть токени на нього. Ви повинні прийняти політичне рішення щодо фінансування створення ATA, якщо він не існує.
Акаунт існує
Якщо акаунт існує, перевірте, якій програмі він належить:
-
System Program: Це стандартний гаманець. Отримайте ATA, перевірте, чи він існує, і надішліть токени на нього. Ви повинні прийняти політичне рішення щодо фінансування створення ATA, якщо він не існує.
-
Token Program / Token-2022: Переконайтеся, що акаунт є token account (а не mint account), і що він містить токен (mint), який ви збираєтеся надіслати. Якщо все коректно, надішліть токени безпосередньо на цю адресу. Якщо це mint account або token account для іншого mint, відхиліть адресу.
-
Інша програма: Це вимагає прийняття політичного рішення. Деякі програми, наприклад мультипідписні гаманці, можуть бути допустимими власниками token accounts. Якщо ваша політика це дозволяє, отримайте ATA і надішліть. В іншому разі відхиліть адресу.
Демо
Наступний приклад демонструє лише логіку перевірки адреси. Це довідковий код для ілюстративних цілей.
Демо не показує, як отримати ATA або побудувати транзакцію для надсилання токенів. Зверніться до документації token account та передачі токенів для прикладів коду.
Демо нижче використовує три можливих результати:
| Результат | Значення | Дія |
|---|---|---|
IS_WALLET | Дійсна адреса гаманця | Отримати та надіслати на associated token account |
IS_TOKEN_ACCOUNT | Дійсний token account | Надіслати токени безпосередньо на цю адресу |
REJECT | Недійсна адреса | Не надсилати |
Потім він зіставляє кожен результат із прийнятністю для кожного активу за
допомогою canReceiveNativeSol (лише гаманці) та canReceiveSplToken (гаманці
або token accounts). token account повертає IS_TOKEN_ACCOUNT, тому може
отримувати SPL-токени, але не нативний SOL — саме ця відмінність запобігає
блокуванню SOL.
/*** 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?