Token con Permessi tramite Token ACL (sRFC37)

Token ACL (Access Control List) è un programma Solana che consente token conformi e con permessi senza sacrificare l'esperienza utente. Implementa sRFC37, permettendo alle aziende di creare token con funzionalità di lista di consenso/blocco mantenendo la UX fluida che gli utenti si aspettano.

Il Problema

Le aziende necessitano di token conformi in grado di:

  1. Applicare i requisiti KYC/AML
  2. Bloccare gli indirizzi sanzionati
  3. Limitare i trasferimenti di token alle parti approvate

L'approccio tradizionale utilizza l'estensione DefaultAccountState di Token-2022 per creare account in uno stato congelato, richiedendo un intervento manuale per scongelare ciascun account:

┌─────────────────────────────────────────────────────┐
│ TRADITIONAL FROZEN TOKENS │
├─────────────────────────────────────────────────────┤
│ │
│ 1. User creates token account │
│ └─> Account is FROZEN ❄️ │
│ │
│ 2. User contacts issuer support │
│ └─> "Please whitelist my wallet" │
│ │
│ 3. Issuer manually verifies KYC │
│ └─> Delays, friction, poor UX │
│ │
│ 4. Issuer thaws account │
│ └─> Finally can receive tokens │
│ │
│ ❌ Bad UX - users wait hours/days │
│ │
└─────────────────────────────────────────────────────┘

Questo crea attrito significativo e vanifica la promessa di transazioni blockchain istantanee e senza permessi.

La Soluzione

Token ACL abilita lo sblocco senza permessi - gli utenti possono scongelare automaticamente i propri account se soddisfano i criteri definiti da un Gate Program:

┌─────────────────────────────────────────────────────┐
│ TOKEN ACL FLOW │
├─────────────────────────────────────────────────────┤
│ │
│ 1. User creates token account │
│ └─> Account is FROZEN ❄️ │
│ │
│ 2. User calls permissionless thaw │
│ └─> Token ACL checks Gate Program │
│ │
│ 3. Gate Program validates user │
│ ├─> On allow list? ✅ THAW │
│ ├─> On block list? ❌ STAY FROZEN │
│ └─> AllowAllEoas mode? ✅ THAW │
│ │
│ 4. Account thawed instantly! │
│ └─> User can receive tokens immediately │
│ │
│ ✅ Great UX - instant, self-service │
│ │
└─────────────────────────────────────────────────────┘

Implementazione di Riferimento Educativa

Questa guida include un'implementazione funzionante completa che puoi eseguire localmente. Il codice sorgente fornisce implementazioni di riferimento per l'esplorazione e scopi educativi.

Il codice dei programmi ACL è disponibile nel repository token-acl e il Gate Program ABL è disponibile nel repository abl-gate-program.

Importante: Il Gate Program ABL (Allow Block List) utilizzato in questa guida è una implementazione di riferimento. Sebbene sia verificato e pronto per la produzione, gli emittenti sono liberi di creare Gate Program personalizzati che si adattino meglio alle loro specifiche esigenze di conformità. Sei vincolato solo dalla specifica Token ACL (sRFC37), non da questo particolare design del Gate Program.

NON utilizzare questo codice direttamente in produzione senza:

  • Audit di sicurezza completi
  • Sistemi adeguati di gestione delle chiavi
  • Revisione della conformità normativa
  • Consulenza legale

Perché Token ACL?

AspettoCongelamento TradizionaleToken ACL
Attivazione AccountManuale (minuti/giorni)Istantanea (self-service)
Esperienza UtenteScarsaFluida
Controllo della ConformitàCompletoCompleto
Blocco delle SanzioniManualeAutomatico tramite Gate Program
Sforzo di IntegrazioneAltoBasso (SDK disponibile)
ComponibilitàLimitataCompleta (compatibile con DeFi)

Token ACL vs Transfer Hooks

Sia Token ACL che i Transfer Hooks sono soluzioni Token-2022 per aggiungere logica personalizzata ai token, ma servono scopi diversi e presentano compromessi differenti:

AspettoToken ACLTransfer Hooks
Quando Viene Eseguita la LogicaSolo nelle operazioni di congelamento/scongelamentoAd ogni trasferimento
Overhead di TrasferimentoNessuno - i trasferimenti sono standardCU aggiuntive + account ad ogni trasferimento
Dipendenze dagli AccountSolo durante l'attivazione dell'accountRichieste ad ogni transazione di trasferimento
Componibilità DeFiCompleta - i protocolli funzionano normalmenteLimitata - molti protocolli li inseriscono in blacklist
Ideale PerKYC/AML, sanzioni, liste di consenso/bloccoRoyalty, validazione personalizzata dei trasferimenti
Complessità per gli UtentiBassa - operazione di scongelamento una tantumMaggiore - ogni trasferimento richiede dati aggiuntivi

Quando Usare Token ACL

Scegli Token ACL quando devi controllare chi può detenere il tuo token:

  • Conformità KYC/AML - verifica i titolari prima che possano ricevere token
  • Screening delle sanzioni - blocca indirizzi specifici
  • Restrizioni per investitori accreditati - limita i titolari di token a soggetti verificati
  • Blocco PDA - impedisce agli smart contract di detenere token

Quando Usare i Transfer Hooks

Scegli i Transfer Hooks quando devi controllare come si muovono i token:

  • Royalty NFT - addebita commissioni ad ogni trasferimento
  • Restrizioni di trasferimento - limita gli importi o la frequenza dei trasferimenti
  • Logica di trasferimento personalizzata - esegui codice ad ogni movimento
  • Analytics onchain - traccia tutti i movimenti dei token

Soluzioni Complementari

Token ACL e Transfer Hooks possono essere utilizzati insieme. Ad esempio, potresti usare Token ACL per controllare chi può detenere il tuo token (conformità) mentre usi i Transfer Hooks per l'applicazione delle royalty ad ogni trasferimento.

Panoramica dell'Architettura

Token ACL è composto da tre componenti principali:

  1. Token ACL Program: Il programma principale che gestisce la delega dell'autorità di congelamento e le operazioni senza permessi
  2. Gate Program: Logica personalizzata che determina chi può scongelare/congelare (es., ABL Gate Program per le liste di consenso/blocco)
  3. MintConfig: Configurazione per-mint che memorizza le impostazioni e delega l'autorità di congelamento
┌─────────────────────────────────────────────────────────────────┐
│ TOKEN ACL ARCHITECTURE │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ┌──────────────┐ delegates ┌─────────────────┐ │
│ │ Token Mint │ ──────────────────→ │ MintConfig │ │
│ │ (Token-22) │ freeze authority │ (Token ACL) │ │
│ └──────────────┘ └────────┬────────┘ │
│ │ │
│ │ calls │
│ ▼ │
│ ┌──────────────┐ validates ┌─────────────────┐ │
│ │ User │ ◄─────────────────── │ Gate Program │ │
│ │ (wallet) │ │ (ABL/Custom) │ │
│ └──────────────┘ └─────────────────┘ │
│ │ │
│ ┌────────┴────────┐ │
│ │ │ │
│ ┌────▼────┐ ┌─────▼───┐ │
│ │ Allow │ │ Block │ │
│ │ Lists │ │ Lists │ │
│ └─────────┘ └─────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘

Concetti Chiave

  1. Delega dell'Autorità di Congelamento: Quando crei una configurazione Token ACL, l'autorità di congelamento del mint viene trasferita al PDA MintConfig. Ciò consente a Token ACL di gestire le operazioni di congelamento/scongelamento.

  2. Gate Program: Programmi esterni che implementano la logica di consenso/blocco. Il Gate Program ABL (Allow Block List) è un'implementazione di riferimento - gli emittenti possono costruire Gate Program personalizzati con logica diversa (es., verifica KYC onchain, controlli di sanzioni basati su oracle, o integrazione con protocolli di identità).

  3. Operazioni Senza Permessi: Gli utenti possono scongelare i propri account senza l'intervento dell'emittente, purché il Gate Program lo approvi.

  4. Integrazione TokenMetadata: L'aggiunta di un campo token_acl ai metadati del tuo mint consente il rilevamento automatico da parte di wallet e SDK come @solana/token-helpers.

Rilevamento Automatico con TokenMetadata

Quando aggiungi un campo token_acl all'estensione TokenMetadata del tuo mint puntando all'indirizzo del Gate Program, gli SDK come @solana/token-helpers possono rilevare automaticamente i mint Token ACL e includere le istruzioni di scongelamento durante la creazione degli account token.

Modalità del Gate Program ABL

ABL è un'Implementazione di Riferimento

Il Gate Program ABL mostrato qui è un'implementazione di riferimento che copre i casi d'uso comuni di liste di consenso/blocco. Tuttavia, non sei vincolato a questo design. La specifica Token ACL (sRFC37) definisce solo l'interfaccia tra Token ACL e i Gate Program - puoi creare Gate Program personalizzati con:

  • Integrazione con protocolli di identità/KYC onchain
  • Screening delle sanzioni in tempo reale basato su oracle
  • Flussi di approvazione multi-sig
  • Regole di accesso temporali o condizionali
  • Qualsiasi altra logica di conformità personalizzata

L'unico requisito è implementare l'interfaccia del Gate Program definita in sRFC37.

Il Gate Program ABL (Allow Block List) supporta diverse modalità:

ModalitàDescrizioneCaso d'Uso
AllowAllEoasTutti i wallet normali (non-PDA) possono scongelareToken aperti con blocco PDA
AllowSolo i wallet nella lista di consenso possono scongelareToken con KYC obbligatorio
BlockTutti i wallet ECCETTO quelli nella lista di blocco possono scongelareConformità alle sanzioni
CompositoCombina liste di consenso e bloccoConfigurazione di conformità completa

Precedenza della Lista di Blocco

Quando si utilizzano liste composite, la lista di blocco ha sempre la precedenza. Un wallet presente sia nella lista di consenso CHE in quella di blocco NON sarà in grado di scongelare.

Indirizzi dei Programmi

Per facilità d'uso, i programmi sono già distribuiti su devnet. Puoi utilizzare i seguenti indirizzi. Il rilascio su mainnet seguirà dopo gli audit.

ProgrammaIndirizzo
Token ACLTACLkU6CiCdkQN2MjoyDkVg2yAH9zkxiHDsiztQ52TP
ABL Gate ProgramGATEzzqxhJnsWF6vHRsgtixxSB8PaQdcqGEVTEHWiULz

Prerequisiti

Per eseguire gli esempi localmente, assicurati di clonare i programmi nel tuo validator locale:

  1. Solana CLI

    (Per eseguirlo localmente usa la 2.x, NON la 3.x - c'è un problema noto con i metadati Token-2022 al momento, che causerebbe un errore nel passaggio di aggiunta di metadati aggiuntivi)

    solana --version
  2. Node.js 18+ e pnpm

  3. validator locale con i programmi richiesti:

    solana-test-validator \
    --clone TACLkU6CiCdkQN2MjoyDkVg2yAH9zkxiHDsiztQ52TP \
    --clone GEC5tu9eaZQrNS7ohERwZRqyvLvV8k2iVZqqt6VuwvJu \
    --clone GATEzzqxhJnsWF6vHRsgtixxSB8PaQdcqGEVTEHWiULz \
    --clone D2GUvBwbnkFu3R5s1rz5dcBJ81UsqY3nvHbLdeJLtSx5 \
    --url devnet \
    --reset

Implementazione Completa

Passo 1: Installa le Dipendenze

pnpm add @solana/kit @solana-program/token-2022 @solana-program/system \
@solana-program/compute-budget @token-acl/sdk @token-acl/abl-sdk \
@solana/spl-token-metadata @solana/web3.js ws

Passo 2: Crea un Token con Token ACL

Ecco un esempio completo che crea un token conforme con Token ACL:

import {
createSolanaRpc,
createSolanaRpcSubscriptions,
sendAndConfirmTransactionFactory,
getSignatureFromTransaction,
generateKeyPairSigner,
pipe,
createTransactionMessage,
setTransactionMessageFeePayer,
setTransactionMessageLifetimeUsingBlockhash,
appendTransactionMessageInstructions,
signTransactionMessageWithSigners,
lamports
} from "@solana/kit";
import { getCreateAccountInstruction } from "@solana-program/system";
import { getSetComputeUnitLimitInstruction } from "@solana-program/compute-budget";
import {
TOKEN_2022_PROGRAM_ADDRESS,
getInitializeMintInstruction,
getInitializeTokenMetadataInstruction,
getUpdateTokenMetadataFieldInstruction,
tokenMetadataField,
AccountState,
getMintSize,
getPreInitializeInstructionsForMintExtensions,
extension
} from "@solana-program/token-2022";
import { pack } from "@solana/spl-token-metadata";
import { PublicKey } from "@solana/web3.js";
// Token ACL SDK
import {
getCreateConfigInstruction,
findMintConfigPda,
getTogglePermissionlessInstructionsInstruction,
findThawExtraMetasAccountPda
} from "@token-acl/sdk";
// ABL Gate Program SDK
import {
getCreateListInstruction,
getSetupExtraMetasInstruction,
getAddWalletInstruction,
findListConfigPda,
findWalletEntryPda,
ABL_PROGRAM_ADDRESS,
Mode
} from "@token-acl/abl-sdk";
// TLV sizes for Token-2022 extensions
const TYPE_SIZE = 2;
const LENGTH_SIZE = 2;
async function createTokenACLMint() {
// Setup RPC
const rpc = createSolanaRpc("http://localhost:8899");
const rpcSubscriptions = createSolanaRpcSubscriptions("ws://localhost:8900");
const sendAndConfirm = sendAndConfirmTransactionFactory({
rpc,
rpcSubscriptions
});
// Load your payer keypair
const payer = await loadKeypair("~/.config/solana/id.json");
// Generate mint keypair
const mint = await generateKeyPairSigner();
console.log(`🪙 Mint: ${mint.address}`);
// TokenMetadata config - includes 'token_acl' for auto-detection
const TOKEN_NAME = "Compliant Token";
const TOKEN_SYMBOL = "COMP";
const TOKEN_URI = "";
const TOKEN_ACL_KEY = "token_acl";
// Define extensions
const defaultAccountStateExtension = extension("DefaultAccountState", {
state: AccountState.Frozen
});
const metadataPointerExtension = extension("MetadataPointer", {
authority: payer.address,
metadataAddress: mint.address
});
const extensions = [defaultAccountStateExtension, metadataPointerExtension];
// Calculate mint size
const baseMintSize = getMintSize(extensions);
const metadataForSizing = {
mint: new PublicKey(mint.address),
name: TOKEN_NAME,
symbol: TOKEN_SYMBOL,
uri: TOKEN_URI,
additionalMetadata: [[TOKEN_ACL_KEY, ABL_PROGRAM_ADDRESS]] as [
string,
string
][]
};
const metadataLen = pack(metadataForSizing).length;
const totalSpace = baseMintSize + metadataLen + TYPE_SIZE + LENGTH_SIZE;
// Get rent
const mintRent = await rpc
.getMinimumBalanceForRentExemption(BigInt(totalSpace))
.send();
// Get extension pre-initialization instructions
const extensionInstructions = getPreInitializeInstructionsForMintExtensions(
mint.address,
extensions
);
// Build transaction
const { value: blockhash } = await rpc.getLatestBlockhash().send();
const createMintTx = pipe(
createTransactionMessage({ version: 0 }),
(tx) => setTransactionMessageFeePayer(payer.address, tx),
(tx) => setTransactionMessageLifetimeUsingBlockhash(blockhash, tx),
(tx) =>
appendTransactionMessageInstructions(
[
getSetComputeUnitLimitInstruction({ units: 400_000 }),
getCreateAccountInstruction({
payer,
newAccount: mint,
lamports: lamports(mintRent),
space: baseMintSize,
programAddress: TOKEN_2022_PROGRAM_ADDRESS
}),
...extensionInstructions,
getInitializeMintInstruction({
mint: mint.address,
decimals: 6,
mintAuthority: payer.address,
freezeAuthority: payer.address
}),
getInitializeTokenMetadataInstruction({
metadata: mint.address,
updateAuthority: payer.address,
mint: mint.address,
mintAuthority: payer,
name: TOKEN_NAME,
symbol: TOKEN_SYMBOL,
uri: TOKEN_URI
}),
getUpdateTokenMetadataFieldInstruction({
metadata: mint.address,
updateAuthority: payer,
field: tokenMetadataField("Key", [TOKEN_ACL_KEY]),
value: ABL_PROGRAM_ADDRESS
})
],
tx
)
);
// Sign and send
const signedTx = await signTransactionMessageWithSigners(createMintTx);
await sendAndConfirm(signedTx, { commitment: "confirmed" });
console.log("✅ Mint created with TokenMetadata");
return mint.address;
}

Passo 3: Crea la Configurazione Token ACL

Dopo aver creato il mint, crea la configurazione Token ACL:

async function createTokenACLConfig(
mintAddress: Address,
payer: TransactionSigner
) {
const [mintConfigPda] = await findMintConfigPda({ mint: mintAddress });
console.log(`📋 MintConfig PDA: ${mintConfigPda}`);
const createConfigIx = getCreateConfigInstruction({
payer: payer.address,
authority: payer,
mint: mintAddress,
mintConfig: mintConfigPda,
gatingProgram: ABL_PROGRAM_ADDRESS
});
const { value: blockhash } = await rpc.getLatestBlockhash().send();
const tx = pipe(
createTransactionMessage({ version: 0 }),
(tx) => setTransactionMessageFeePayer(payer.address, tx),
(tx) => setTransactionMessageLifetimeUsingBlockhash(blockhash, tx),
(tx) => appendTransactionMessageInstructions([createConfigIx], tx)
);
const signedTx = await signTransactionMessageWithSigners(tx);
await sendAndConfirm(signedTx, { commitment: "confirmed" });
console.log("✅ Token ACL config created");
console.log(" Freeze authority transferred to MintConfig PDA");
return mintConfigPda;
}

Passo 4: Configura il Gate Program ABL

Crea una lista ABL e configura i meta aggiuntivi:

// AllowAllEoas - All regular wallets can thaw automatically
async function setupAllowAllEoas(
mintAddress: Address,
mintConfigPda: Address,
payer: TransactionSigner
) {
const listSeed = mintAddress; // Use mint as seed
const [listConfigPda] = await findListConfigPda({
authority: payer.address,
seed: listSeed
});
const createListIx = getCreateListInstruction({
authority: payer,
listConfig: listConfigPda,
mode: Mode.AllowAllEoas, // All EOAs can thaw
seed: listSeed
});
const [thawExtraMetasPda] = await findThawExtraMetasAccountPda(
{ mint: mintAddress },
{ programAddress: ABL_PROGRAM_ADDRESS }
);
const setupMetasIx = getSetupExtraMetasInstruction({
authority: payer,
tokenAclMintConfig: mintConfigPda,
mint: mintAddress,
extraMetas: thawExtraMetasPda,
lists: [listConfigPda]
});
// Send transaction with both instructions...
console.log("✅ ABL list created with AllowAllEoas mode");
}

Passo 5: Abilita lo Scongelamento Senza Permessi

Consenti agli utenti di scongelare i propri account:

async function enablePermissionlessThaw(
mintConfigPda: Address,
authority: TransactionSigner
) {
const toggleIx = getTogglePermissionlessInstructionsInstruction({
authority,
mintConfig: mintConfigPda,
thawEnabled: true,
freezeEnabled: false // Optional: enable permissionless freeze too
});
// Send transaction...
console.log("✅ Permissionless thaw enabled");
}

Passo 6: L'Utente Scongela il Proprio Account

Gli utenti possono ora scongelare i propri account utilizzando l'SDK:

import {
createThawPermissionlessIdempotentInstructionWithExtraMetas,
TOKEN_ACL_PROGRAM_ADDRESS
} from "@token-acl/sdk";
import { fetchEncodedAccount } from "@solana/kit";
async function userThawsAccount(
mintAddress: Address,
userAta: Address,
userAddress: Address,
payer: TransactionSigner
) {
// Account retriever function for the SDK
const accountRetriever = async (addr: Address) => {
return await fetchEncodedAccount(rpc, addr);
};
// The SDK handles all the complexity of fetching extra metas
const thawIx =
await createThawPermissionlessIdempotentInstructionWithExtraMetas(
payer, // authority (signer)
userAta, // token account to thaw
mintAddress, // mint
userAddress, // token account owner
TOKEN_ACL_PROGRAM_ADDRESS, // Token ACL program
accountRetriever // account fetcher
);
// Send transaction signed by payer...
console.log("✅ Account thawed permissionlessly!");
}

Utilizzo di @solana/token-helpers per lo Scongelamento Automatico

L'SDK @solana/token-helpers può rilevare automaticamente i mint Token ACL e includere le istruzioni di scongelamento:

import { createAndConfirmAssociatedTokenAccount } from "@solana/token-helpers";
// This automatically includes thaw instruction if mint has 'token_acl' metadata
const { signature, associatedTokenAddress } =
await createAndConfirmAssociatedTokenAccount(
rpc,
rpcSubscriptions,
payer,
user.address,
mintAddress,
true // idempotent
);
console.log(`✅ Account created AND thawed automatically!`);
console.log(` ATA: ${associatedTokenAddress}`);

Requisito TokenMetadata

Affinché il rilevamento automatico di @solana/token-helpers funzioni, il tuo mint deve avere:

  1. L'estensione TokenMetadata inizializzata
  2. Un campo additionalMetadata con chiave token_acl e valore impostato sull'indirizzo del Gate Program

Liste Composite di Consenso e Blocco

Per il massimo controllo della conformità, combina le liste di consenso e blocco:

async function setupCompositeLists(
mintAddress: Address,
mintConfigPda: Address,
payer: TransactionSigner
) {
// Create ALLOW list
const allowListSeed = /* unique seed for allow list */;
const [allowListPda] = await findListConfigPda({
authority: payer.address,
seed: allowListSeed,
});
const createAllowListIx = getCreateListInstruction({
authority: payer,
listConfig: allowListPda,
mode: Mode.Allow,
seed: allowListSeed,
});
// Create BLOCK list
const blockListSeed = /* unique seed for block list */;
const [blockListPda] = await findListConfigPda({
authority: payer.address,
seed: blockListSeed,
});
const createBlockListIx = getCreateListInstruction({
authority: payer,
listConfig: blockListPda,
mode: Mode.Block,
seed: blockListSeed,
});
// Setup extra metas with BOTH lists
const [thawExtraMetasPda] = await findThawExtraMetasAccountPda(
{ mint: mintAddress },
{ programAddress: ABL_PROGRAM_ADDRESS }
);
const setupMetasIx = getSetupExtraMetasInstruction({
authority: payer,
tokenAclMintConfig: mintConfigPda,
mint: mintAddress,
extraMetas: thawExtraMetasPda,
lists: [allowListPda, blockListPda], // Both lists!
});
// Send transaction...
console.log("✅ Composite lists created");
console.log(" - Allow list: Only whitelisted users can thaw");
console.log(" - Block list: Blocked users can NEVER thaw");
}

Comportamento delle Liste Composite

┌─────────────────────────────────────────────────────┐
│ COMPOSITE LIST LOGIC │
├─────────────────────────────────────────────────────┤
│ │
│ User tries to thaw: │
│ │
│ 1. Check BLOCK list first │
│ └─> On block list? ❌ DENY (always) │
│ │
│ 2. Check ALLOW list │
│ └─> On allow list? ✅ ALLOW │
│ └─> Not on allow list? ❌ DENY │
│ │
│ Key insight: Block list ALWAYS wins! │
│ │
└─────────────────────────────────────────────────────┘

Casi d'Uso

1. Security Token (KYC Obbligatorio)

Usa una lista di consenso per garantire che solo gli investitori con KYC verificato possano detenere token:

// Create allow list
const createListIx = getCreateListInstruction({
authority: issuer,
listConfig: allowListPda,
mode: Mode.Allow,
seed: mintAddress
});
// After KYC verification, add investor
await addToAllowList(allowListPda, kycVerifiedInvestor, issuer);

2. Conformità alle Sanzioni

Usa una lista di blocco per impedire agli indirizzi sanzionati di ricevere token:

// Create block list
const createListIx = getCreateListInstruction({
authority: complianceOfficer,
listConfig: blockListPda,
mode: Mode.Block,
seed: mintAddress
});
// Block sanctioned address
await addToBlockList(blockListPda, sanctionedAddress, complianceOfficer);

3. Token Aperto con Protezione PDA

Usa AllowAllEoas per consentire a tutti i wallet normali bloccando i PDA (smart contract):

const createListIx = getCreateListInstruction({
authority: payer,
listConfig: listConfigPda,
mode: Mode.AllowAllEoas, // Regular wallets OK, PDAs blocked
seed: mintAddress
});

4. Conformità Aziendale Completa

Combina lista di consenso + lista di blocco per un controllo completo:

  • Lista di consenso: investitori con KYC verificato
  • Lista di blocco: indirizzi sanzionati, dipendenti cessati, ecc.

Considerazioni per la Produzione

Prima di distribuire in produzione:

  1. Audit di Sicurezza: Ottieni audit di sicurezza professionali della tua implementazione e di eventuali Gate Program personalizzati

  2. Gestione delle Chiavi: Utilizza soluzioni di custodia adeguate per le chiavi di autorità. Considera il multi-sig per le operazioni sensibili

  3. Conformità Normativa: Consulta esperti legali sulle normative sui titoli, i requisiti KYC/AML e la conformità alle sanzioni

  4. Gestione delle Liste: Costruisci sistemi robusti per la gestione delle liste di consenso/blocco, inclusi:

    • Integrazione automatizzata dello screening delle sanzioni
    • Integrazione con provider KYC
    • Registrazione degli audit
  5. Monitoraggio: Implementa il monitoraggio per:

    • Tentativi di scongelamento falliti (potenziali problemi di conformità)
    • Modifiche alle liste
    • Utilizzo delle chiavi di autorità
  6. Disaster Recovery: Pianifica la rotazione delle chiavi, il ripristino delle liste e le procedure di congelamento di emergenza

Versione Solana CLI

Token ACL con TokenMetadata richiede Solana CLI 2.x. C'è un problema noto con CLI 3.x che compromette la funzionalità di espansione automatica di TokenMetadata. Verifica sempre la versione della tua CLI prima di distribuire.

Interfaccia a Riga di Comando (CLI)

Sia Token ACL che il Gate Program ABL forniscono CLI per gestire configurazioni e liste senza scrivere codice. Questo è utile per i team operativi.

Token ACL CLI

La Token ACL CLI gestisce le configurazioni dei mint e le operazioni di congelamento/scongelamento.

Installazione

# Install from crates.io
cargo install token-acl-cli
# Verify installation
token-acl --version

Comandi Token ACL

ComandoDescrizione
create-configCrea una nuova configurazione mint (trasferisce l'autorità di congelamento)
delete-configElimina una configurazione mint
set-authorityImposta l'autorità di una configurazione mint
set-gating-programImposta il programma di gating per una configurazione di mint
set-instructionsAbilita/disabilita il thaw/freeze senza permessi
thawScongela un token account (autorità richiesta)
freezeBlocca un token account (autorità richiesta)
thaw-permissionlessScongela un token account senza permessi
freeze-permissionlessBlocca un token account senza permessi
create-ata-and-thaw-permissionlessCrea un associated token account e scongela in un unico comando

Creare una Configurazione Token ACL

# Create a mint config (delegates freeze authority to Token ACL)
token-acl create-config <MINT_ADDRESS> \
--gating-program GATEzzqxhJnsWF6vHRsgtixxSB8PaQdcqGEVTEHWiULz

Abilitare il Thaw Senza Permessi

# Enable permissionless thaw only (recommended for most use cases)
# - Users can self-service unfreeze after passing gate checks
# - Only authority can freeze accounts (security best practice)
token-acl set-instructions --enable-thaw --disable-freeze <MINT_ADDRESS>
# Enable both permissionless thaw AND freeze
# Use case: Allow anyone to freeze blocked users, or users to self-freeze
token-acl set-instructions --enable-thaw --enable-freeze <MINT_ADDRESS>
# Disable all permissionless operations (authority-only mode)
token-acl set-instructions --disable-thaw --disable-freeze <MINT_ADDRESS>

Operazioni di Thaw/Freeze

# Thaw an account permissionlessly (user self-service)
token-acl thaw-permissionless <MINT_ADDRESS> <TOKEN_ACCOUNT_ADDRESS>
# Thaw using authority (issuer operation)
token-acl thaw <MINT_ADDRESS> <TOKEN_ACCOUNT_ADDRESS>
# Freeze using authority (compliance enforcement)
token-acl freeze <MINT_ADDRESS> <TOKEN_ACCOUNT_ADDRESS>

Creare un ATA e Scongelare in un Unico Comando

# Creates associated token account and thaws it automatically
token-acl create-ata-and-thaw-permissionless --mint <MINT_ADDRESS> --owner <WALLET_ADDRESS>

ABL Gate CLI (allow-block-list)

L'ABL Gate CLI gestisce le liste di permessi/blocco e le voci dei wallet.

Installazione

# Install from crates.io
cargo install token-acl-gate-cli
# Verify installation (binary is named 'allow-block-list')
allow-block-list --version

Comandi ABL Gate

ComandoDescrizione
create-listCrea una nuova lista di permessi/blocco
delete-listElimina una lista
add-walletAggiunge un wallet a una lista
remove-walletRimuove un wallet da una lista
apply-lists-to-mintConfigura quali liste si applicano a un mint

Creare una Lista

# Create an ALLOW list (only whitelisted wallets can thaw)
allow-block-list create-list --mode allow
# Create a BLOCK list (blocked wallets cannot thaw)
allow-block-list create-list --mode block
# Create an ALLOW-ALL-EOAs list (all regular wallets can thaw)
allow-block-list create-list --mode allow-all-eoas

Il comando restituisce l'indirizzo PDA list_config e il seed - salvali!

Gestire i Wallet nelle Liste

# Add wallet to a list (works for both allow and block lists)
allow-block-list add-wallet <LIST_ADDRESS> <WALLET_ADDRESS>
# Remove wallet from a list
allow-block-list remove-wallet <LIST_ADDRESS> <WALLET_ADDRESS>

Applicare le Liste a un Mint

# Apply a single list to a mint
allow-block-list apply-lists-to-mint <MINT_ADDRESS> <LIST_ADDRESS>
# Apply multiple lists (e.g., allow + block for composite compliance)
allow-block-list apply-lists-to-mint <MINT_ADDRESS> <ALLOW_LIST> <BLOCK_LIST>

Opzioni Globali della CLI

Entrambe le CLI supportano queste opzioni:

OpzioneDescrizione
-u, --url <URL>URL RPC (predefinito: dalla configurazione Solana)
-k, --payer <KEYPAIR>File keypair del pagante o hardware wallet
-C, --config <PATH>Percorso del file di configurazione Solana
-v, --verboseMostra informazioni aggiuntive

Esempio di Flusso di Lavoro Completo con la CLI

Ecco un flusso di lavoro completo che utilizza tutte le CLI per configurare un token conforme da zero:

# ============================================================================
# STEP 1: Configure Solana CLI
# ============================================================================
solana config set --url localhost
# ============================================================================
# STEP 2: Create Token22 Mint with Metadata + DefaultAccountState Extensions
# ============================================================================
# Create the mint with:
# - Token-2022 program
# - Freeze authority enabled
# - Default account state = frozen (all new accounts start frozen)
# - Metadata extension with token_acl field for auto-detection
spl-token create-token \
--program-id TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb \
--enable-freeze \
--default-account-state frozen \
--enable-metadata
# Output:
# Creating token 7KzLwpXMzKa8JiqYr2ookFjxLx1xMF4xM4YhVqPJpump
# Address: 7KzLwpXMzKa8JiqYr2ookFjxLx1xMF4xM4YhVqPJpump
# Save the mint address for use in subsequent commands
MINT=7KzLwpXMzKa8JiqYr2ookFjxLx1xMF4xM4YhVqPJpump
# Initialize the token metadata
spl-token initialize-metadata $MINT "Compliant Token" "COMP" "https://example.com/metadata.json"
# Add the token_acl field for wallet auto-detection
# This tells wallets/SDKs which gate program to use for thaw
spl-token update-metadata $MINT token_acl GATEzzqxhJnsWF6vHRsgtixxSB8PaQdcqGEVTEHWiULz
# Verify the token was created correctly
spl-token display $MINT
# ============================================================================
# STEP 3: Create Token ACL Config
# ============================================================================
# This transfers freeze authority from your wallet to the Token ACL MintConfig PDA
token-acl create-config $MINT \
--gating-program GATEzzqxhJnsWF6vHRsgtixxSB8PaQdcqGEVTEHWiULz
# Output:
# ✅ Config created for mint 7KzLwpXMzKa8JiqYr2ookFjxLx1xMF4xM4YhVqPJpump
# MintConfig PDA: 9xYzAbCdEfGhIjKlMnOpQrStUvWxYz123456789abc
# ============================================================================
# STEP 4: Create ABL Lists
# ============================================================================
# Create a block list for sanctions compliance
allow-block-list create-list --mode block
# Output:
# list_config: 5HnJkLmNoPqRsTuVwXyZ987654321defghijk
# seed: 3AbCdEfGhIjKlMnOpQrStUvWxYz123456789
# Save the block list address
BLOCK_LIST=5HnJkLmNoPqRsTuVwXyZ987654321defghijk
# ============================================================================
# STEP 5: Apply Lists to Mint
# ============================================================================
# Configure the block list to be used for this mint's permissionless operations
allow-block-list apply-lists-to-mint $MINT $BLOCK_LIST
# ============================================================================
# STEP 6: Enable Permissionless Thaw
# ============================================================================
# Allow users to thaw their own accounts (if not on block list)
# --enable-thaw: Users can self-service unfreeze after passing gate checks
# --disable-freeze: Only authority can freeze
token-acl set-instructions --enable-thaw --disable-freeze $MINT
# ============================================================================
# STEP 7: Manage Block List (Compliance Operations)
# ============================================================================
# To fully block a user, you need TWO steps:
# 1. Add to block list (prevents future thawing)
# 2. Freeze their token account (stops current usage)
# Step 7a: Add wallet to block list
# Replace with actual wallet address to block (must be valid base58 pubkey)
allow-block-list add-wallet $BLOCK_LIST <WALLET_TO_BLOCK>
# Step 7b: Freeze their existing token account (if they have one)
# This requires the token account address, not the wallet address
# spl-token address --verbose --token $MINT to get the token account address
# token-acl freeze <TOKEN_ACCOUNT_ADDRESS>
# Note: Adding to block list alone only prevents them from THAWING.
# If their account is already thawed, they can still use it until you freeze it!
# Later, if sanctions are lifted:
# 1. Remove from block list
# allow-block-list remove-wallet $BLOCK_LIST <WALLET_ADDRESS>
# 2. User can then thaw their account again
# ============================================================================
# STEP 8: User Creates Account and Thaws
# ============================================================================
# A user can now create their token account and thaw it in one command
# Use your own wallet or generate one: solana-keygen new --no-outfile
USER_WALLET=$(solana address) # Uses your configured wallet
token-acl create-ata-and-thaw-permissionless --mint $MINT --owner $USER_WALLET
# Output:
# ✅ Created ATA: 8AbCdEfGhIjKlMnOpQrStUvWxYz123456789xyz
# ✅ Thawed successfully!
# ============================================================================
# STEP 9: Mint Tokens to User
# ============================================================================
# Now the issuer can mint tokens to the user's thawed account
spl-token mint $MINT 1000 --recipient-owner $USER_WALLET
# Verify balance
spl-token balance $MINT

Metadati del Token per il Rilevamento Automatico

Aggiungere il campo di metadati token_acl è fondamentale per l'integrazione con i wallet. Quando wallet come Phantom o SDK come @solana/token-helpers rilevano questo campo, includono automaticamente le istruzioni di thaw durante la creazione dei token account.

spl-token update-metadata $MINT token_acl GATEzzqxhJnsWF6vHRsgtixxSB8PaQdcqGEVTEHWiULz

Prossimi Passi

  1. Prova il Workshop: Clona il repository token-acl ed esegui gli esempi dimostrativi. Leggi l'implementazione dell' ACL e dell' ABL Gate Program.

  2. Crea Programmi Gate Personalizzati: L'ABL Gate Program è solo un'implementazione di riferimento. Costruisci il tuo Gate Program per integrarti con la tua infrastruttura di conformità esistente, i provider di identità, o per implementare logiche personalizzate adatte ai tuoi requisiti specifici

  3. Integrazione con la DeFi: I token Token ACL sono completamente componibili con i protocolli DeFi

  4. Leggi la Specifica: Consulta sRFC37 per la specifica tecnica completa e partecipa alla discussione sRFC37

Conclusione

Token ACL (sRFC37) offre una soluzione potente per le imprese che necessitano di token conformi e con permessi senza rinunciare all'esperienza utente che rende preziosa la blockchain. Vantaggi principali:

  • Attivazione Immediata: Gli utenti possono scongelare autonomamente i propri account
  • Controllo Completo della Conformità: Liste di permessi, liste di blocco o logica personalizzata
  • Programmi Gate Flessibili: Utilizza l'implementazione ABL di riferimento o crea Gate Program personalizzati che si integrano con la tua infrastruttura di conformità
  • Integrazione Trasparente: Gli SDK gestiscono automaticamente la complessità
  • Componibile: Compatibile con i protocolli DeFi esistenti
  • Verificato: Programmi pronti per la produzione distribuiti sulla mainnet

La combinazione dell'estensione DefaultAccountState di Token-2022 con le operazioni senza permessi di Token ACL crea un nuovo paradigma per l'emissione di token conformi su Solana.

Is this page helpful?

© 2026 Solana Foundation. Tutti i diritti riservati.