Wysłanie tokenów na nieprawidłowy adres może skutkować trwałą utratą środków. Weryfikacja adresu zapewnia, że wysyłasz tokeny tylko na adresy, które mogą je poprawnie odebrać i uzyskać do nich dostęp.
Zobacz Jak działają płatności w Solana, aby poznać podstawowe pojęcia dotyczące płatności.
Zrozumienie adresów Solana
Konta Solana mają dwa typy adresów: on-curve i off-curve.
Adresy on-curve
Standardowe adresy to klucze publiczne z par kluczy Ed25519. Te adresy:
- Mają odpowiadający im klucz prywatny, który może podpisywać transakcje
- Służą jako adresy portfeli
Adresy off-curve (PDA)
Program Derived Addresses (adresy pochodne programu) są deterministycznie wyprowadzane z ID programu i seedów. Te adresy:
- Nie mają odpowiadającego im klucza prywatnego
- Mogą być podpisywane tylko przez program, z którego zostały wyprowadzone
Typy kont w płatnościach
Użyj adresu, aby pobrać konto z sieci, sprawdź właściciela programu i typ konta, aby określić, jak obsłużyć dany adres.
Wiedza o tym, czy adres jest on-curve czy off-curve, nie mówi, jaki to typ konta, jaki program jest jego właścicielem ani czy konto istnieje pod tym adresem. Musisz pobrać konto z sieci, aby poznać te szczegóły.
Konta System Program (portfele)
Konta należące do System Program to standardowe portfele. Aby wysłać tokeny SPL do portfela, należy wyznaczyć i użyć jego associated token account (ATA).
Po wyznaczeniu adresu ATA sprawdź, czy token account istnieje on-chain. Jeśli ATA nie istnieje, możesz dodać instrukcję utworzenia token account odbiorcy w tej samej transakcji co transfer. Wymaga to jednak opłacenia rent za nowe token account. Ponieważ odbiorca jest właścicielem ATA, SOL zapłacone za rent nie może zostać odzyskane przez nadawcę.
Bez odpowiednich zabezpieczeń subsydiowanie tworzenia ATA może zostać wykorzystane w nieuczciwy sposób. Złośliwy użytkownik może zlecić transfer, utworzyć swoje ATA na Twój koszt, zamknąć ATA, aby odzyskać rent SOL, i powtarzać ten proces.
Konta tokenów
Konta tokenów są własnością Token Program lub Token-2022 Program i przechowują salda tokenów. Jeśli otrzymany adres należy do programu tokenów, należy zweryfikować, czy konto jest kontem tokena (a nie mint account) i czy odpowiada oczekiwanemu mint account tokena przed wysłaniem.
Token Programs automatycznie sprawdzają, czy oba konta tokenów w transferze przechowują tokeny tego samego mint. Jeśli weryfikacja się nie powiedzie, transakcja zostaje odrzucona i żadne środki nie zostają utracone.
Konta mint
Konta mint śledzą podaż tokena i metadane konkretnego tokena. Konta mint są również własnością Token Programs, ale nie są prawidłowymi odbiorcami transferów tokenów. Próba wysłania tokenów na adres mint kończy się nieudaną transakcją, ale środki nie zostają utracone.
Inne konta
Konta należące do innych programów wymagają decyzji politycznej. Niektóre konta (np. portfele multisig) mogą być prawidłowymi właścicielami kont tokenów, podczas gdy inne powinny zostać odrzucone.
Przebieg weryfikacji
Poniższy diagram przedstawia przykładowe drzewo decyzyjne do weryfikacji adresu:
Pobierz konto
Użyj adresu, aby pobrać szczegóły konta z sieci.
Konto nie istnieje
Jeśli pod tym adresem nie istnieje konto, sprawdź, czy adres jest on-curve czy off-curve:
-
Poza krzywą (PDA): Ostrożnie odrzuć ten adres, aby uniknąć wysyłania do ATA, który może być niedostępny. Bez istniejącego konta nie da się określić na podstawie samego adresu, który program wygenerował ten PDA ani czy adres jest ATA. Utworzenie ATA dla tego adresu i wysłanie tokenów może spowodować zablokowanie środków na niedostępnym token account.
-
Na krzywej: To poprawny adres portfela (klucz publiczny), który nie został jeszcze zasilony. Wygeneruj ATA, sprawdź, czy istnieje, i wyślij na niego tokeny. Musisz podjąć decyzję, czy finansować utworzenie ATA, jeśli jeszcze nie istnieje.
Konto istnieje
Jeśli konto istnieje, sprawdź, który program jest jego właścicielem:
-
System Program: To standardowy portfel. Wygeneruj ATA, sprawdź, czy istnieje, i wyślij na niego tokeny. Musisz podjąć decyzję, czy finansować utworzenie ATA, jeśli jeszcze nie istnieje.
-
Token Program / Token-2022: Zweryfikuj, czy konto jest token account (a nie mint account) i czy posiada token (mint), który chcesz wysłać. Jeśli tak, wyślij tokeny bezpośrednio na ten adres. Jeśli to mint account lub token account dla innego mint, odrzuć adres.
-
Inny program: Wymaga decyzji politycznej. Niektóre programy, jak portfele multisig, mogą być akceptowalnymi właścicielami token account. Jeśli polityka na to pozwala, wygeneruj ATA i wyślij. W przeciwnym razie odrzuć adres.
Demo
Poniższy przykład pokazuje wyłącznie logikę walidacji adresu. To kod referencyjny służący do celów ilustracyjnych.
Demo nie pokazuje, jak wyprowadzić ATA ani jak zbudować transakcję do wysyłania tokenów. Zobacz dokumentację dotyczącą token account oraz przesyłania tokenów, aby znaleźć przykładowy kod.
Poniższa demonstracja wykorzystuje trzy możliwe wyniki:
| Wynik | Znaczenie | Działanie |
|---|---|---|
IS_WALLET | Prawidłowy adres portfela | Wyprowadź i wyślij na associated token account |
IS_TOKEN_ACCOUNT | Prawidłowy token account | Wyślij tokeny bezpośrednio na ten adres |
REJECT | Nieprawidłowy adres | Nie wysyłaj |
/*** 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 on-chainif (!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" };}// =============================================================================// Examples// =============================================================================
Is this page helpful?