Token Berizin dengan Token ACL (sRFC37)

Token ACL (Access Control List) adalah program Solana yang memungkinkan token berizin dan patuh tanpa mengorbankan pengalaman pengguna. Program ini mengimplementasikan sRFC37, memungkinkan perusahaan membuat token dengan fungsionalitas daftar izin/blokir sambil mempertahankan UX yang mulus sesuai ekspektasi pengguna.

Masalah

Perusahaan membutuhkan token yang patuh yang dapat:

  1. Menerapkan persyaratan KYC/AML
  2. Memblokir alamat yang dikenai sanksi
  3. Membatasi transfer token kepada pihak yang disetujui

Pendekatan tradisional menggunakan ekstensi DefaultAccountState dari Token-2022 untuk membuat akun dalam status beku, yang memerlukan intervensi manual untuk mencairkan setiap akun:

┌─────────────────────────────────────────────────────┐
│ 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 │
│ │
└─────────────────────────────────────────────────────┘

Hal ini menciptakan hambatan yang signifikan dan menghilangkan manfaat dari transaksi blockchain yang instan dan tanpa izin.

Solusi

Token ACL memungkinkan pencairan tanpa izin - pengguna dapat secara otomatis mencairkan akun mereka sendiri jika memenuhi kriteria yang ditentukan oleh 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 │
│ │
└─────────────────────────────────────────────────────┘

Referensi Implementasi Edukatif

Panduan ini mencakup implementasi lengkap yang dapat Anda jalankan secara lokal. Kode sumber menyediakan referensi implementasi untuk eksplorasi dan tujuan edukatif.

Kode program ACL tersedia di repositori token-acl dan ABL Gate Program tersedia di repositori abl-gate-program.

Penting: ABL (Allow Block List) Gate Program yang digunakan dalam panduan ini adalah referensi implementasi. Meskipun telah diaudit dan siap untuk produksi, penerbit bebas membuat Gate Program kustom yang lebih sesuai dengan kebutuhan kepatuhan spesifik mereka. Anda hanya terikat oleh spesifikasi Token ACL (sRFC37), bukan desain Gate Program tertentu ini.

JANGAN gunakan kode ini langsung di produksi tanpa:

  • Audit keamanan yang komprehensif
  • Sistem manajemen kunci yang tepat
  • Tinjauan kepatuhan regulasi
  • Konsultasi hukum

Mengapa Token ACL?

AspekBeku TradisionalToken ACL
Aktivasi AkunManual (menit/hari)Instan (layanan mandiri)
Pengalaman PenggunaBurukMulus
Kontrol KepatuhanPenuhPenuh
Pemblokiran SanksiManualOtomatis melalui Gate Program
Upaya IntegrasiTinggiRendah (SDK tersedia)
KomposabilitasTerbatasPenuh (kompatibel dengan DeFi)

Token ACL vs Transfer Hooks

Baik Token ACL maupun Transfer Hooks adalah solusi Token-2022 untuk menambahkan logika kustom pada token, namun keduanya memiliki tujuan berbeda dan pertimbangan yang berbeda pula:

AspekToken ACLTransfer Hooks
Waktu Eksekusi LogikaHanya pada operasi freeze/thawPada setiap transfer
Overhead TransferTidak ada - transfer bersifat standarCU tambahan + akun pada setiap transfer
Ketergantungan AkunHanya saat aktivasi akunDiperlukan pada setiap transaksi transfer
Komposabilitas DeFiPenuh - protokol berjalan normalTerbatas - banyak protokol yang memblokir
Paling Cocok UntukKYC/AML, sanksi, daftar izin/blokirRoyalti, validasi transfer kustom
Kompleksitas bagi PenggunaRendah - operasi thaw satu kaliLebih tinggi - setiap transfer membutuhkan data tambahan

Kapan Menggunakan Token ACL

Pilih Token ACL ketika Anda perlu mengontrol siapa yang dapat memegang token Anda:

  • Kepatuhan KYC/AML - verifikasi pemegang sebelum mereka dapat menerima token
  • Pemeriksaan sanksi - blokir alamat tertentu
  • Pembatasan investor terakreditasi - batasi pemegang token kepada pihak terverifikasi
  • Pemblokiran PDA - cegah smart contract memegang token

Kapan Menggunakan Transfer Hooks

Pilih Transfer Hooks ketika Anda perlu mengontrol bagaimana token berpindah:

  • Royalti NFT - kenakan biaya pada setiap transfer
  • Pembatasan transfer - batasi jumlah atau frekuensi transfer
  • Logika transfer kustom - jalankan kode pada setiap perpindahan
  • Analitik onchain - lacak semua pergerakan token

Solusi yang Saling Melengkapi

Token ACL dan Transfer Hooks dapat digunakan bersamaan. Misalnya, Anda dapat menggunakan Token ACL untuk mengontrol siapa yang dapat memegang token Anda (kepatuhan) sekaligus menggunakan Transfer Hooks untuk penerapan royalti pada setiap transfer.

Gambaran Arsitektur

Token ACL terdiri dari tiga komponen utama:

  1. Token ACL Program: Program inti yang mengelola delegasi otoritas freeze dan operasi tanpa izin
  2. Gate Program: Logika kustom yang menentukan siapa yang dapat thaw/freeze (misalnya, ABL Gate Program untuk daftar izin/blokir)
  3. MintConfig: Konfigurasi per-mint yang menyimpan pengaturan dan mendelegasikan otoritas freeze
┌─────────────────────────────────────────────────────────────────┐
│ 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 │ │
│ └─────────┘ └─────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘

Konsep Utama

  1. Delegasi Otoritas Freeze: Saat Anda membuat konfigurasi Token ACL, otoritas freeze mint dipindahkan ke MintConfig PDA. Ini memungkinkan Token ACL mengelola operasi freeze/thaw.

  2. Gate Programs: Program eksternal yang mengimplementasikan logika izin/blokir. ABL (Allow Block List) Gate Program adalah referensi implementasi - penerbit dapat membangun Gate Program kustom dengan logika berbeda (misalnya, verifikasi KYC onchain, pemeriksaan sanksi berbasis oracle, atau integrasi dengan protokol identitas).

  3. Operasi Tanpa Izin: Pengguna dapat mencairkan akun mereka sendiri tanpa intervensi penerbit, selama Gate Program menyetujuinya.

  4. Integrasi TokenMetadata: Menambahkan field token_acl ke metadata mint Anda memungkinkan deteksi otomatis oleh wallet dan SDK seperti @solana/token-helpers.

Deteksi Otomatis dengan TokenMetadata

Saat Anda menambahkan field token_acl ke ekstensi TokenMetadata mint Anda yang mengarah ke alamat Gate Program, SDK seperti @solana/token-helpers dapat secara otomatis mendeteksi mint Token ACL dan menyertakan instruksi thaw saat membuat token accounts.

Mode ABL Gate Program

ABL adalah Referensi Implementasi

ABL Gate Program yang ditampilkan di sini adalah referensi implementasi yang mencakup kasus penggunaan daftar izin/blokir yang umum. Namun, Anda tidak terikat pada desain ini. Spesifikasi Token ACL (sRFC37) hanya mendefinisikan antarmuka antara Token ACL dan Gate Programs - Anda dapat membuat Gate Program kustom dengan:

  • Integrasi dengan protokol identitas/KYC onchain
  • Pemeriksaan sanksi real-time berbasis oracle
  • Alur kerja persetujuan multi-sig
  • Aturan akses berbasis waktu atau kondisional
  • Logika kepatuhan kustom lainnya

Satu-satunya persyaratan adalah mengimplementasikan antarmuka Gate Program yang didefinisikan dalam sRFC37.

ABL (Allow Block List) Gate Program mendukung beberapa mode:

ModeDeskripsiKasus Penggunaan
AllowAllEoasSemua wallet reguler (non-PDA) dapat melakukan thawToken terbuka dengan pemblokiran PDA
AllowHanya wallet dalam daftar izin yang dapat melakukan thawToken yang memerlukan KYC
BlockSemua wallet KECUALI yang ada di daftar blokir dapat melakukan thawKepatuhan sanksi
KompositGabungkan daftar izin + blokirPengaturan kepatuhan penuh

Prioritas Daftar Blokir

Saat menggunakan daftar komposit, daftar blokir selalu mendapat prioritas. Wallet yang ada di daftar izin DAN daftar blokir TIDAK akan dapat melakukan thaw.

Alamat Program

Untuk memudahkan, program-program ini sudah di-deploy di devnet. Anda dapat menggunakan alamat berikut. Rilis Mainnet akan menyusul setelah audit selesai.

ProgramAlamat
Token ACLTACLkU6CiCdkQN2MjoyDkVg2yAH9zkxiHDsiztQ52TP
ABL Gate ProgramGATEzzqxhJnsWF6vHRsgtixxSB8PaQdcqGEVTEHWiULz

Prasyarat

Untuk menjalankan contoh secara lokal, pastikan untuk mengkloning program ke dalam validator lokal Anda:

  1. Solana CLI

    (Untuk menjalankannya secara lokal gunakan versi 2.x, BUKAN 3.x - ada masalah yang diketahui dengan metadata Token-2022 saat ini, yang akan gagal pada langkah penambahan metadata tambahan)

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

  3. validator lokal dengan program yang diperlukan:

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

Implementasi Lengkap

Langkah 1: Instal Dependensi

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

Langkah 2: Buat Token dengan Token ACL

Berikut adalah contoh lengkap yang membuat token patuh dengan 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;
}

Langkah 3: Buat Konfigurasi Token ACL

Setelah membuat mint, buat konfigurasi 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;
}

Langkah 4: Siapkan ABL Gate Program

Buat daftar ABL dan siapkan extra metas:

// 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");
}

Langkah 5: Aktifkan Thaw Tanpa Izin

Aktifkan pengguna untuk mencairkan akun mereka sendiri:

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");
}

Langkah 6: Pengguna Mencairkan Akun Mereka

Pengguna kini dapat mencairkan akun mereka sendiri menggunakan 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!");
}

Menggunakan @solana/token-helpers untuk Auto-Thaw

SDK @solana/token-helpers dapat secara otomatis mendeteksi mint Token ACL dan menyertakan instruksi thaw:

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}`);

Persyaratan TokenMetadata

Agar deteksi otomatis @solana/token-helpers berfungsi, mint Anda harus memiliki:

  1. Ekstensi TokenMetadata yang telah diinisialisasi
  2. Field additionalMetadata dengan kunci token_acl dan nilai yang diatur ke alamat Gate Program

Daftar Izin + Blokir Komposit

Untuk kontrol kepatuhan maksimum, gabungkan daftar izin dan blokir:

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");
}

Perilaku Daftar Komposit

┌─────────────────────────────────────────────────────┐
│ 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! │
│ │
└─────────────────────────────────────────────────────┘

Kasus Penggunaan

1. Token Sekuritas (KYC Diperlukan)

Gunakan daftar Izin untuk memastikan hanya investor terverifikasi KYC yang dapat memegang 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. Kepatuhan Sanksi

Gunakan daftar Blokir untuk mencegah alamat yang dikenai sanksi menerima 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 Terbuka dengan Perlindungan PDA

Gunakan AllowAllEoas untuk mengizinkan semua wallet reguler sekaligus memblokir PDA (smart contract):

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

4. Kepatuhan Enterprise Penuh

Gabungkan daftar Izin + daftar Blokir untuk kontrol lengkap:

  • Daftar izin: Investor terverifikasi KYC
  • Daftar blokir: Alamat yang dikenai sanksi, karyawan yang diberhentikan, dll.

Pertimbangan Produksi

Sebelum men-deploy ke produksi:

  1. Audit Keamanan: Dapatkan audit keamanan profesional untuk implementasi Anda dan Gate Program kustom apa pun

  2. Manajemen Kunci: Gunakan solusi penyimpanan yang tepat untuk kunci otoritas. Pertimbangkan multi-sig untuk operasi sensitif

  3. Kepatuhan Regulasi: Konsultasikan dengan pakar hukum mengenai regulasi sekuritas, persyaratan KYC/AML, dan kepatuhan sanksi

  4. Manajemen Daftar: Bangun sistem yang kuat untuk mengelola daftar izin/blokir, termasuk:

    • Integrasi pemeriksaan sanksi otomatis
    • Integrasi penyedia KYC
    • Pencatatan audit
  5. Pemantauan: Terapkan pemantauan untuk:

    • Percobaan thaw yang gagal (potensi masalah kepatuhan)
    • Modifikasi daftar
    • Penggunaan kunci otoritas
  6. Pemulihan Bencana: Rencanakan rotasi kunci, pemulihan daftar, dan prosedur freeze darurat

Versi Solana CLI

Token ACL dengan TokenMetadata memerlukan Solana CLI 2.x. Ada masalah yang diketahui dengan CLI 3.x yang merusak fitur auto-ekspansi TokenMetadata. Selalu verifikasi versi CLI Anda sebelum melakukan deployment.

Command-Line Interface (CLI)

Baik Token ACL maupun ABL Gate Program menyediakan CLI untuk mengelola konfigurasi dan daftar tanpa menulis kode. Ini berguna bagi tim operasional.

CLI Token ACL

CLI Token ACL mengelola konfigurasi mint serta operasi freeze/thaw.

Instalasi

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

Perintah Token ACL

PerintahDeskripsi
create-configMembuat konfigurasi mint baru (mengalihkan otoritas freeze)
delete-configMenghapus konfigurasi mint
set-authorityMengatur otoritas konfigurasi mint
set-gating-programMenetapkan gating program untuk mint config
set-instructionsMengaktifkan/menonaktifkan thaw/freeze tanpa izin
thawMencairkan token account (memerlukan otoritas)
freezeMembekukan token account (memerlukan otoritas)
thaw-permissionlessMencairkan token account tanpa izin
freeze-permissionlessMembekukan token account tanpa izin
create-ata-and-thaw-permissionlessMembuat ATA dan mencairkan dalam satu perintah

Membuat Token ACL Config

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

Mengaktifkan Thaw Tanpa Izin

# 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>

Operasi 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>

Membuat ATA dan Thaw dalam Satu Perintah

# 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)

ABL Gate CLI mengelola daftar izin/blokir dan entri dompet.

Instalasi

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

Perintah ABL Gate

PerintahDeskripsi
create-listMembuat daftar izin/blokir baru
delete-listMenghapus sebuah daftar
add-walletMenambahkan dompet ke daftar
remove-walletMenghapus dompet dari daftar
apply-lists-to-mintMengonfigurasi daftar mana yang diterapkan pada mint

Membuat Daftar

# 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

Perintah ini menghasilkan alamat PDA list_config dan seed - simpan informasi ini!

Mengelola Dompet pada Daftar

# 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>

Menerapkan Daftar ke 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>

Opsi Global CLI

Kedua CLI mendukung opsi berikut:

OpsiDeskripsi
-u, --url <URL>RPC URL (default: dari konfigurasi Solana)
-k, --payer <KEYPAIR>File keypair pembayar atau hardware wallet
-C, --config <PATH>Path file konfigurasi Solana
-v, --verboseTampilkan informasi tambahan

Contoh Alur Kerja CLI Lengkap

Berikut adalah alur kerja lengkap menggunakan semua CLI untuk menyiapkan token yang patuh dari awal:

# ============================================================================
# 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

Metadata Token untuk Deteksi Otomatis

Menambahkan kolom metadata token_acl sangat penting untuk integrasi dompet. Ketika dompet seperti Phantom atau SDK seperti @solana/token-helpers mendeteksi kolom ini, mereka secara otomatis menyertakan instruksi thaw saat membuat token account.

spl-token update-metadata $MINT token_acl GATEzzqxhJnsWF6vHRsgtixxSB8PaQdcqGEVTEHWiULz

Langkah Selanjutnya

  1. Coba Workshop: Clone repositori token-acl dan jalankan contoh demo. Baca implementasi dari ACL dan ABL Gate Program.

  2. Bangun Gate Program Kustom: ABL Gate Program hanyalah implementasi referensi. Bangun Gate Program Anda sendiri untuk berintegrasi dengan infrastruktur kepatuhan yang ada, penyedia identitas, atau terapkan logika kustom yang sesuai dengan kebutuhan spesifik Anda

  3. Integrasikan dengan DeFi: Token ACL sepenuhnya dapat dikomposisikan dengan protokol DeFi

  4. Baca Spesifikasi: Tinjau sRFC37 untuk spesifikasi teknis lengkap dan bergabunglah dalam diskusi sRFC37

Kesimpulan

Token ACL (sRFC37) menyediakan solusi yang powerful bagi perusahaan yang membutuhkan token yang patuh dan berbasis izin tanpa mengorbankan pengalaman pengguna yang membuat blockchain bernilai. Manfaat utama:

  • Aktivasi Instan: Pengguna dapat mencairkan akun mereka sendiri secara mandiri
  • Kontrol Kepatuhan Penuh: Daftar izin, daftar blokir, atau logika kustom
  • Gate Program yang Fleksibel: Gunakan implementasi referensi ABL atau bangun Gate Program kustom yang terintegrasi dengan infrastruktur kepatuhan Anda
  • Integrasi yang Mulus: SDK menangani kompleksitas secara otomatis
  • Dapat Dikomposisikan: Bekerja dengan protokol DeFi yang sudah ada
  • Telah Diaudit: Program siap produksi yang telah di-deploy di mainnet

Kombinasi ekstensi DefaultAccountState dari Token-2022 dengan operasi tanpa izin milik Token ACL menciptakan paradigma baru untuk penerbitan token yang patuh di Solana.

Is this page helpful?

© 2026 Yayasan Solana. Semua hak dilindungi.