Das Senden von Geldern an eine falsche Adresse kann zu einem dauerhaften Verlust führen. Die Adressverifizierung stellt sicher, dass Sie nur an Adressen senden, die die Gelder ordnungsgemäß empfangen und darauf zugreifen können.
Die Validierung hängt davon ab, was Sie senden:
- SPL-Token sind teilweise selbstschützend. Das Token Program lehnt eine Überweisung ab, bei der die Konten nicht mit der erwarteten Mint übereinstimmen, sodass eine fehlgeleitete Token-Überweisung fehlschlägt, ohne dass Gelder verloren gehen. Der Großteil dieser Seite behandelt SPL-Token-Sendungen.
- Natives SOL verfügt über keinen solchen Schutz. Eine System Program-Überweisung gelingt in jedes Konto, sodass ein falscher Empfänger das SOL dauerhaft sperrt. Siehe Natives SOL senden.
Siehe Wie Zahlungen auf Solana funktionieren für grundlegende Zahlungskonzepte.
Solana-Adressen verstehen
Solana-Konten haben zwei Arten von Adressen: On-Curve und Off-Curve.
On-Curve-Adressen
Standardadressen sind die öffentlichen Schlüssel aus Ed25519-keypairs. Diese Adressen:
- Haben einen entsprechenden privaten Schlüssel, der Transaktionen signieren kann
- Werden als Wallet-Adressen verwendet
Off-Curve-Adressen (PDAs)
Program Derived Addresses werden deterministisch aus einer Programm-ID und Seeds abgeleitet. Diese Adressen:
- Haben keinen entsprechenden privaten Schlüssel
- Können nur vom Programm signiert werden, aus dem die Adresse abgeleitet wurde
Kontotypen bei Zahlungen
Verwenden Sie die Adresse, um ein Konto aus dem Netzwerk abzurufen, und überprüfen Sie den Programmeigentümer sowie den Kontotyp, um zu bestimmen, wie die Adresse zu behandeln ist.
Ob eine Adresse On-Curve oder Off-Curve ist, sagt Ihnen nicht, welchen Typ das Konto hat, welches Programm es besitzt oder ob an dieser Adresse überhaupt ein Konto existiert. Sie müssen das Konto aus dem Netzwerk abrufen, um diese Details zu ermitteln.
System Program Konten (Wallets)
Konten, die dem System Program gehören, sind Standard-Wallets. Um SPL-Token an eine Wallet zu senden, leiten Sie die zugehörige Associated Token Account (ATA) ab und verwenden Sie diese.
Nach dem Ableiten der ATA-Adresse prüfen Sie, ob das token account bereits onchain existiert. Falls die ATA nicht existiert, können Sie eine Anweisung zum Erstellen des token account des Empfängers in dieselbe Transaktion wie die Überweisung aufnehmen. Dies erfordert jedoch die Zahlung von rent für das neue token account. Da der Empfänger die ATA besitzt, kann der für die rent gezahlte SOL vom Sender nicht zurückgefordert werden.
Ohne Schutzmaßnahmen kann die Subventionierung der ATA-Erstellung ausgenutzt werden. Ein böswilliger Nutzer könnte eine Überweisung anfordern, seine ATA auf Ihre Kosten erstellen lassen, die ATA schließen, um den rent SOL zurückzuerhalten, und diesen Vorgang wiederholen.
Token Accounts
Token accounts gehören dem Token Program oder Token-2022 Program und speichern Token-Guthaben. Wenn die Adresse, die Sie erhalten, einem Token-Programm gehört, sollten Sie überprüfen, ob das Konto ein token account ist (kein mint account) und mit dem erwarteten token mint account übereinstimmt, bevor Sie senden.
Die Token Programs validieren automatisch, dass beide token accounts in einer Überweisung Token desselben Mint halten. Schlägt die Validierung fehl, wird die Transaktion abgelehnt und es gehen keine Mittel verloren.
Mint Accounts
Mint accounts verfolgen das Token-Angebot und die Metadaten eines bestimmten Tokens. Mint accounts gehören ebenfalls Token Programs, sind aber keine gültigen Empfänger für Token-Überweisungen. Der Versuch, Token an eine Mint-Adresse zu senden, führt zu einer fehlgeschlagenen Transaktion, es gehen jedoch keine Mittel verloren.
Andere Konten
Konten, die anderen Programmen gehören, erfordern eine Grundsatzentscheidung. Einige Konten (z. B. Multisig-Wallets) können gültige token account-Inhaber sein, während andere abgelehnt werden sollten.
Natives SOL senden
Die obige Klassifizierung bestimmt, wohin SPL-Token gesendet werden können. Natives SOL ist strenger: Der einzige sichere Empfänger ist eine System Program-Wallet (oder eine nicht finanzierte On-Curve-Adresse, die zu einer wird).
Eine System Program-Überweisung fügt lamports zu jedem Konto hinzu, einschließlich Mints, token accounts, Programmen und PDAs. Lamports können nur vom eigenen Programm des Kontos abgebucht werden. Daher kann das Senden von SOL an einen falschen Empfänger dazu führen, dass Gelder dauerhaft verloren gehen.
Im Gegensatz zu einer SPL-Token-Überweisung schlägt die Transaktion nicht fehl, wenn der Empfänger eine unerwartete Adresse ist.
Beim Senden von nativem SOL ist nur ein IS_WALLET-Ergebnis akzeptabel.
IS_TOKEN_ACCOUNT ist es nicht: Ein token account enthält SPL-Token, und
dorthin gesendetes SOL liegt außerhalb der Kontrolle des Absenders.
Dies ist eine häufige Ursache für den Verlust von SOL: Ein Benutzer fügt die Mint-Adresse eines Tokens (oder eine Programm-Adresse) in eine SOL-Auszahlung ein. Die Überweisung wird erfolgreich durchgeführt und das SOL ist nicht wiederherstellbar. Klassifizieren Sie den Empfänger immer, bevor Sie eine SOL-Überweisung unterzeichnen.
Verifizierungsablauf
Das folgende Diagramm zeigt einen Referenz-Entscheidungsbaum zur Validierung einer Adresse:
Konten abrufen
Verwenden Sie die Adresse, um die Kontendetails aus dem Netzwerk abzurufen.
Konten existieren nicht
Wenn unter dieser Adresse kein Konto existiert, prüfen Sie, ob die Adresse On-Curve oder Off-Curve ist:
-
Off-Curve (PDA): Lehnen Sie die Adresse vorsichtshalber ab, um das Senden an eine ATA zu vermeiden, die möglicherweise nicht zugänglich ist. Ohne ein bestehendes Konto können Sie anhand der Adresse allein nicht bestimmen, welches Programm diese PDA abgeleitet hat oder ob die Adresse für eine ATA ist. Das Ableiten einer ATA für diese Adresse zum Senden von Token könnte dazu führen, dass Gelder in einem nicht zugänglichen token account gesperrt werden.
-
On-curve: Dies ist eine gültige Wallet-Adresse (öffentlicher Schlüssel), die noch nicht finanziert wurde. Leiten Sie den ATA ab, prüfen Sie, ob er existiert, und senden Sie Token daran. Sie müssen eine Grundsatzentscheidung treffen, ob Sie die Erstellung des ATA finanzieren möchten, falls er nicht existiert.
Konto existiert
Wenn ein Konto existiert, prüfen Sie, welches Programm es besitzt:
-
System Program: Dies ist ein Standard-Wallet. Leiten Sie den ATA ab, prüfen Sie, ob er existiert, und senden Sie Token daran. Sie müssen eine Grundsatzentscheidung treffen, ob Sie die Erstellung des ATA finanzieren möchten, falls er nicht existiert.
-
Token Program / Token-2022: Überprüfen Sie, ob das Konto ein token account (kein mint account) ist und dass es den Token (Mint) enthält, den Sie senden möchten. Wenn gültig, senden Sie Token direkt an diese Adresse. Wenn es sich um ein mint account oder ein token account für einen anderen Mint handelt, lehnen Sie die Adresse ab.
-
Anderes Programm: Dies erfordert eine Grundsatzentscheidung. Einige Programme wie Multisig-Wallets können akzeptable Eigentümer von token accounts sein. Wenn Ihre Richtlinie es erlaubt, leiten Sie den ATA ab und senden Sie. Andernfalls lehnen Sie die Adresse ab.
Demo
Das folgende Beispiel zeigt nur die Adressvalidierungslogik. Dies ist Referenzcode zu Illustrationszwecken.
Die Demo zeigt nicht, wie ein ATA abgeleitet oder eine Transaktion zum Senden von Token erstellt wird. Für Beispielcode verweisen Sie auf die Dokumentation zu token account und token transfer.
Die folgende Demo verwendet drei mögliche Ergebnisse:
| Ergebnis | Bedeutung | Aktion |
|---|---|---|
IS_WALLET | Gültige Wallet-Adresse | ATA ableiten und Token daran senden |
IS_TOKEN_ACCOUNT | Gültiger token account | Token direkt an diese Adresse senden |
REJECT | Ungültige Adresse | Nicht senden |
Anschließend wird jedes Ergebnis mit canReceiveNativeSol (nur Wallets) und
canReceiveSplToken (Wallets oder token accounts) auf die Akzeptierbarkeit pro
Asset geprüft. Ein token account gibt IS_TOKEN_ACCOUNT zurück, sodass er
SPL-Token empfangen kann, aber nicht natives SOL — die Unterscheidung, die
verhindert, dass SOL gesperrt wird.
/*** 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?