Inviare fondi a un indirizzo errato può comportare una perdita permanente. La verifica dell'indirizzo garantisce che tu e i tuoi utenti inviate solo a indirizzi in grado di ricevere e accedere correttamente ai fondi. Se gestisci un exchange, si consiglia di eseguire questi controlli e di far verificare l'indirizzo all'utente prima dell'invio.
La validazione dipende da ciò che si invia:
- I token SPL sono in parte auto-protetti. Il Token Program rifiuta un trasferimento i cui account non corrispondono al mint previsto, quindi un trasferimento di token indirizzato erroneamente fallisce senza perdita di fondi. La maggior parte di questa pagina riguarda l'invio di token SPL.
- SOL nativo non dispone di tale protezione. Un trasferimento tramite System Program ha successo in qualsiasi account, quindi un destinatario errato blocca permanentemente i SOL. Vedi Invio di SOL nativo.
Vedi Come funzionano i pagamenti su Solana per i concetti fondamentali sui pagamenti.
Comprendere gli indirizzi Solana
Gli account Solana hanno due tipi di indirizzi: on-curve e off-curve.
Indirizzi On-Curve
Gli indirizzi standard sono le chiavi pubbliche dei keypair Ed25519. Questi indirizzi:
- Hanno una chiave privata corrispondente in grado di firmare le transazioni
- Vengono utilizzati come indirizzi di wallet
Indirizzi Off-Curve (PDA)
I Program Derived Address sono derivati deterministicamente da un ID di programma e da seed. Questi indirizzi:
- Non hanno una chiave privata corrispondente
- Possono essere firmati solo dal programma da cui l'indirizzo è stato derivato
I wallet controllati da programmi, comunemente noti come smart wallet o smart account, hanno indirizzi off-curve. Questa guida utilizza il termine "smart wallet" in tutto il documento.
Tipi di account nei pagamenti
Usa l'indirizzo per recuperare un account dalla rete, controlla il proprietario del programma e il tipo di account per determinare come gestire l'indirizzo.
Sapere se un indirizzo è on-curve o off-curve non indica il tipo di account, il programma che lo possiede, né se esiste un account a quell'indirizzo. È necessario recuperare l'account dalla rete per determinare questi dettagli.
System Program Accounts (Portafogli)
Gli account di proprietà del System Program sono portafogli standard. Per inviare token SPL a un portafoglio, è necessario derivare e utilizzare il suo Associated Token Account (ATA).
Dopo aver derivato l'indirizzo ATA, verifica se il token account esiste onchain. Se l'ATA non esiste, puoi includere un'istruzione per creare il token account del destinatario nella stessa transazione del trasferimento. Tuttavia, questo richiede il pagamento del rent per il nuovo token account. Poiché il destinatario è il proprietario dell'ATA, il SOL pagato per il rent non può essere recuperato dal mittente.
Gli account di sistema possono esistere off-curve. Se il tuo utente desidera inviare token a un indirizzo off-curve, si consiglia di invitare l'utente a verificare che intenda davvero inviare fondi a uno smart wallet.
Senza adeguate misure di sicurezza, il finanziamento della creazione degli ATA può essere sfruttato a scopo malevolo. Un utente malintenzionato potrebbe richiedere un trasferimento, far creare il proprio ATA a tue spese, chiudere l'ATA per recuperare il rent SOL e ripetere l'operazione.
Token Accounts
I token account sono di proprietà del Token Program o del Token-2022 Program e contengono i saldi dei token. Se l'indirizzo che ricevi è di proprietà di un token program, dovresti verificare che l'account sia un token account (e non un mint account) e che corrisponda al mint account del token atteso prima di procedere all'invio.
I Token Programs verificano automaticamente che entrambi i token account coinvolti in un trasferimento contengano token dello stesso mint. Se la verifica fallisce, la transazione viene rifiutata e nessun fondo viene perso.
Mint Accounts
I mint account tracciano la fornitura di token e i metadati di un token specifico. I mint account sono anch'essi di proprietà dei Token Program, ma non sono destinatari validi per i trasferimenti di token. Il tentativo di inviare token a un indirizzo mint comporta il fallimento della transazione, ma nessun fondo viene perso.
Altri Account
Gli account di proprietà di altri programmi sono validi, ma sono regolati dalle regole di autorità stabilite dal rispettivo programma proprietario. Si consiglia di invitare l'utente a verificare che intenda inviare fondi a uno smart wallet.
Invio di SOL nativo
La classificazione sopra indicata determina dove possono essere inviati i token SPL. Il SOL nativo è più restrittivo: l'unico destinatario sicuro è un portafoglio System Program (o un indirizzo non finanziato sulla curva che ne diventa uno).
Un trasferimento tramite System Program aggiunge lamport a qualsiasi account, inclusi mint, token account, program account e PDA. I lamport possono essere prelevati solo dal programma proprietario dell'account, quindi inviare SOL a un destinatario errato può comportare la perdita permanente dei fondi.
A differenza di un trasferimento di token SPL, la transazione non fallisce quando il destinatario è un indirizzo inatteso.
Quando si invia SOL nativo, è accettabile solo un risultato IS_WALLET.
IS_TOKEN_ACCOUNT non lo è: un token account contiene token SPL e il SOL
inviato lì è fuori dal controllo del mittente.
Questo è un modo comune in cui il SOL viene perso: un utente incolla l'indirizzo mint di un token (o un indirizzo di programma) in un prelievo SOL. Il trasferimento va a buon fine e il SOL è irrecuperabile. Classificare sempre il destinatario prima di firmare un trasferimento SOL.
Flusso di Verifica
Il diagramma seguente mostra un albero decisionale di riferimento per la validazione di un indirizzo:
Recupera account
Utilizza l'indirizzo per recuperare i dettagli dell'account dalla rete.
Account inesistente
Se non esiste alcun account a questo indirizzo, verifica se l'indirizzo è on-curve o off-curve:
-
Off-curve (PDA): Richiedi una verifica esplicita del destinatario prima di creare un ATA o inviare token SPL. In assenza di un account esistente, non è possibile determinare dall'indirizzo soltanto quale programma ha derivato questo PDA o se il programma del destinatario può accedere al suo ATA.
-
On-curve: Si tratta di un indirizzo wallet valido (chiave pubblica) che non è ancora stato finanziato. Deriva l'ATA, verifica se esiste e invia i token. Devi prendere una decisione di policy se finanziare la creazione dell'ATA qualora non esistesse.
Account esistente
Se esiste un account, verifica quale programma ne è proprietario:
-
System Program: Si tratta di un wallet standard. Deriva l'ATA, verifica se esiste e invia i token. Devi prendere una decisione di policy se finanziare la creazione dell'ATA qualora non esistesse.
-
Token Program / Token-2022: Verifica che l'account sia un token account (non un mint account) e che contenga il token (mint) che intendi inviare. Se valido, invia i token direttamente a questo indirizzo. Se si tratta di un mint account o di un token account per un mint diverso, rifiuta l'indirizzo.
-
Altro Programma: Programmi come i wallet multisig sono proprietari accettabili di token account. Richiedi all'utente di confermare che intende inviare a uno smart wallet.
Alcuni smart wallet comuni:
| Wallet | Indirizzo Programma |
|---|---|
| Squads | SQDS4ep65T869zMMBKyuUq6aD6EgTu8psMjkvj52pCf |
| Swig | swigypWHEksbC64pWKwah1WTeh9JXwx8H1rJHLdbQMB |
Demo
L'esempio seguente mostra solo la logica di validazione dell'indirizzo. Si tratta di codice di riferimento a scopo illustrativo.
La demo non mostra come derivare un ATA o costruire una transazione per inviare token. Consulta la documentazione sul token account e sul trasferimento di token per esempi di codice.
La demo seguente utilizza tre possibili risultati:
| Risultato | Significato | Azione |
|---|---|---|
IS_WALLET | Indirizzo wallet valido | Deriva e invia all'associated token account |
IS_TOKEN_ACCOUNT | Token account valido | Invia i token direttamente a questo indirizzo |
USER_VERIFICATION | L'indirizzo richiede la conferma del destinatario | Richiedi una revisione esplicita prima di inviare token SPL o finanziare un ATA |
REJECT | Indirizzo non valido | Non inviare |
Mappa quindi ogni risultato all'accettabilità per singolo asset con canReceiveNativeSol
(solo wallet) e canReceiveSplToken (wallet o token account). Un risultato
USER_VERIFICATION non viene accettato automaticamente; la tua applicazione
dovrebbe far confermare all'utente le proprie intenzioni prima di inviare token SPL.
Un token account restituisce IS_TOKEN_ACCOUNT, quindi può ricevere token SPL ma
non SOL nativo — la distinzione che impedisce che SOL venga bloccato.
/*** Validates an input address and classifies it as a wallet, token account,* address requiring recipient verification, 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* - USER_VERIFICATION: Require explicit review before sending SPL tokens* - 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) {// An unfunded PDA may belong to a smart wallet, but the address// alone cannot prove that its program can access a newly-created ATA.if (isOffCurveAddress(inputAddress)) {return {type: "USER_VERIFICATION",reason:"Unfunded PDA: confirm the recipient is using a smart wallet and controls this address"};}// On-curve = valid keypair address, treat as unfunded walletreturn { type: "IS_WALLET" };}// Account exists, check program ownerconst owner = account.programAddress;// A System Program account can be a standard wallet or an off-curve smart// wallet. Require verification before automatically sending to the// latter.if (owner === SYSTEM_PROGRAM) {if (isOffCurveAddress(inputAddress)) {return {type: "USER_VERIFICATION",reason:"Off-curve System Program account: confirm recipient is using a smart wallet"};}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"};}// An account owned by another program can be a smart wallet.return {type: "USER_VERIFICATION",reason:"Program-owned account: confirm the recipient is using a smart wallet"};}/*** 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?