الرموز المرخّصة مع Token ACL (sRFC37)

Token ACL (قائمة التحكم في الوصول) هو برنامج سولانا يُتيح رموزاً متوافقة ومرخّصة دون المساس بتجربة المستخدم. يُطبّق sRFC37، مما يُمكّن المؤسسات من إنشاء رموز تدعم وظيفة قوائم السماح/الحظر مع الحفاظ على تجربة المستخدم السلسة التي يتوقعها المستخدمون.

المشكلة

تحتاج المؤسسات إلى رموز متوافقة قادرة على:

  1. تطبيق متطلبات KYC/AML
  2. حظر العناوين الخاضعة للعقوبات
  3. تقييد تحويلات الرموز على الأطراف المعتمدة

يعتمد النهج التقليدي على امتداد DefaultAccountState في Token-2022 لإنشاء حسابات في حالة مجمّدة، مما يستلزم تدخلاً يدوياً لإذابة كل حساب:

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

يُفضي ذلك إلى احتكاك كبير ويُقوّض وعد المعاملات الفورية الخالية من القيود على البلوكشين.

الحل

يُتيح Token ACL إذابة بلا إذن - يمكن للمستخدمين إذابة حساباتهم الخاصة تلقائياً إذا استوفوا المعايير التي يحددها 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 │
│ │
└─────────────────────────────────────────────────────┘

تطبيق مرجعي تعليمي

يتضمن هذا الدليل تطبيقاً كاملاً وقابلاً للتشغيل يمكنك تشغيله محلياً. الكود المصدري يوفر تطبيقات مرجعية للاستكشاف والأغراض التعليمية.

كود برامج ACL متاح في مستودع token-acl وبرنامج ABL Gate متاح في مستودع abl-gate-program.

مهم: برنامج ABL (قائمة السماح والحظر) Gate المستخدم في هذا الدليل هو تطبيق مرجعي. وعلى الرغم من أنه خضع للتدقيق وجاهز للإنتاج، فإن المُصدِرين أحرار في إنشاء Gate Programs مخصصة تناسب احتياجات الامتثال الخاصة بهم. أنت مُقيَّد فقط بمواصفات Token ACL (sRFC37)، وليس بتصميم هذا Gate Program بالتحديد.

لا تستخدم هذا الكود مباشرةً في الإنتاج دون:

  • عمليات تدقيق أمني شاملة
  • أنظمة إدارة مفاتيح مناسبة
  • مراجعة الامتثال التنظيمي
  • استشارة قانونية

لماذا Token ACL؟

الجانبالتجميد التقليديToken ACL
تفعيل الحسابيدوي (دقائق/أيام)فوري (خدمة ذاتية)
تجربة المستخدمضعيفةسلسة
التحكم في الامتثالكاملكامل
حظر العقوباتيدويتلقائي عبر Gate Program
جهد التكاملمرتفعمنخفض (SDK متاح)
قابلية التركيبمحدودةكاملة (متوافق مع DeFi)

Token ACL مقابل Transfer Hooks

كلٌّ من Token ACL وTransfer Hooks حلولٌ من Token-2022 لإضافة منطق مخصص إلى الرموز، غير أنهما يخدمان أغراضاً مختلفة ولهما مقايضات متباينة:

الجانبToken ACLTransfer Hooks
وقت تشغيل المنطقفقط عند عمليات التجميد/الإذابةعند كل تحويل
تكلفة التحويل الإضافيةلا شيء - التحويلات معياريةوحدات حوسبة إضافية + حسابات مع كل تحويل
اعتماديات الحسابفقط أثناء تفعيل الحسابمطلوبة مع كل معاملة تحويل
قابلية التركيب مع DeFiكاملة - البروتوكولات تعمل بشكل طبيعيمحدودة - كثير من البروتوكولات تُدرجها في القائمة السوداء
الأنسب لـKYC/AML، العقوبات، قوائم السماح/الحظرحقوق الملكية، التحقق المخصص من التحويلات
التعقيد على المستخدمينمنخفض - عملية إذابة لمرة واحدةأعلى - كل تحويل يحتاج بيانات إضافية

متى تستخدم Token ACL

اختر Token ACL عندما تحتاج إلى التحكم في من يمكنه امتلاك رمزك:

  • امتثال KYC/AML - التحقق من المالكين قبل أن يتمكنوا من استلام الرموز
  • فحص العقوبات - حظر عناوين بعينها
  • قيود المستثمرين المعتمدين - تقييد مالكي الرموز على الأطراف الموثّقة
  • حظر PDA - منع العقود الذكية من امتلاك الرموز

متى تستخدم Transfer Hooks

اختر Transfer Hooks عندما تحتاج إلى التحكم في كيفية تحرك الرموز:

  • عوائد NFT - فرض رسوم على كل تحويل
  • قيود التحويل - تحديد مبالغ أو تكرار التحويلات
  • منطق تحويل مخصص - تنفيذ كود عند كل حركة
  • تحليلات على السلسلة - تتبع جميع حركات الرموز

حلول تكاملية

يمكن استخدام Token ACL وTransfer Hooks معاً. على سبيل المثال، يمكنك استخدام Token ACL للتحكم في من يمكنه امتلاك رمزك (الامتثال) بينما تستخدم Transfer Hooks لتطبيق حقوق الملكية على كل تحويل.

نظرة عامة على البنية

يتكون Token ACL من ثلاثة مكونات رئيسية:

  1. برنامج Token ACL: البرنامج الأساسي الذي يدير تفويض صلاحية التجميد والعمليات غير المقيّدة بالأذونات
  2. Gate Program: منطق مخصص يحدد من يمكنه الإذابة/التجميد (مثل برنامج ABL Gate لقوائم السماح/الحظر)
  3. MintConfig: إعداد لكل mint يحفظ الإعدادات ويُفوّض صلاحية التجميد
┌─────────────────────────────────────────────────────────────────┐
│ 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 │ │
│ └─────────┘ └─────────┘ │
│ │
└─────────────────────────────────────────────────────────────────┘

المفاهيم الأساسية

  1. تفويض صلاحية التجميد: عند إنشاء إعداد Token ACL، تُنقل صلاحية التجميد الخاصة بالـ mint إلى MintConfig PDA. يُتيح ذلك لـ Token ACL إدارة عمليات التجميد/الإذابة.

  2. Gate Programs: برامج خارجية تُطبّق منطق السماح/الحظر. برنامج ABL (قائمة السماح والحظر) Gate هو تطبيق مرجعي - يمكن للمُصدِرين بناء Gate Programs مخصصة بمنطق مختلف (مثل التحقق من KYC على السلسلة، فحص العقوبات المستند إلى الأوراكل، أو التكامل مع بروتوكولات الهوية).

  3. العمليات غير المقيّدة بالأذونات: يمكن للمستخدمين إذابة حساباتهم الخاصة دون تدخل المُصدِر، طالما أن Gate Program يوافق على ذلك.

  4. تكامل TokenMetadata: إضافة حقل token_acl إلى بيانات mint الوصفية يُتيح الاكتشاف التلقائي من قِبَل المحافظ وحزم SDK مثل @solana/token-helpers.

الاكتشاف التلقائي مع TokenMetadata

عند إضافة حقل token_acl إلى امتداد TokenMetadata الخاص بـ mint مشيراً إلى عنوان Gate Program، يمكن لحزم SDK مثل @solana/token-helpers اكتشاف منتجات Token ACL تلقائياً وتضمين تعليمات الإذابة عند إنشاء حسابات الرموز.

أوضاع ABL Gate Program

ABL هو تطبيق مرجعي

برنامج ABL Gate المعروض هنا هو تطبيق مرجعي يغطي حالات الاستخدام الشائعة لقوائم السماح/الحظر. ومع ذلك، أنت لست مقيداً بهذا التصميم. تحدد مواصفات Token ACL (sRFC37) فقط الواجهة بين Token ACL وGate Programs - يمكنك إنشاء Gate Programs مخصصة تشمل:

  • التكامل مع بروتوكولات الهوية/KYC على السلسلة
  • فحص العقوبات في الوقت الفعلي المستند إلى الأوراكل
  • سير عمل الموافقة متعددة التوقيعات
  • قواعد الوصول المستندة إلى الوقت أو الشروط
  • أي منطق امتثال مخصص آخر

المتطلب الوحيد هو تطبيق واجهة Gate Program المحددة في sRFC37.

يدعم برنامج ABL (قائمة السماح والحظر) Gate عدة أوضاع:

الوضعالوصفحالة الاستخدام
AllowAllEoasجميع المحافظ العادية (غير PDAs) يمكنها الإذابةرموز مفتوحة مع حظر PDA
Allowفقط المحافظ الموجودة في قائمة السماح يمكنها الإذابةرموز تستلزم KYC
Blockجميع المحافظ باستثناء المدرجة في قائمة الحظر يمكنها الإذابةالامتثال للعقوبات
مركّبدمج قوائم السماح والحظرإعداد امتثال كامل

أولوية قائمة الحظر

عند استخدام القوائم المركّبة، تأخذ قائمة الحظر الأولوية دائماً. المحفظة الموجودة في كلٍّ من قائمة السماح وقائمة الحظر لن تتمكن من الإذابة.

عناوين البرامج

لتسهيل الأمر، البرامج مُنشرة بالفعل على devnet. يمكنك استخدام العناوين التالية. سيتبع الإصدار على Mainnet بعد اكتمال عمليات التدقيق.

البرنامجالعنوان
Token ACLTACLkU6CiCdkQN2MjoyDkVg2yAH9zkxiHDsiztQ52TP
ABL Gate ProgramGATEzzqxhJnsWF6vHRsgtixxSB8PaQdcqGEVTEHWiULz

المتطلبات الأساسية

لتشغيل الأمثلة محلياً، تأكد من استنساخ البرامج في validator المحلي الخاص بك:

  1. Solana CLI

    (للتشغيل المحلي استخدم الإصدار 2.x، وليس 3.x - هناك مشكلة معروفة في بيانات Token-2022 الوصفية في الوقت الحالي، مما سيُفشل خطوة إضافة البيانات الوصفية الإضافية)

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

  3. validator محلي مع البرامج المطلوبة:

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

التطبيق الكامل

الخطوة 1: تثبيت التبعيات

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

الخطوة 2: إنشاء رمز مع Token ACL

إليك مثال كامل لإنشاء رمز متوافق مع 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;
}

الخطوة 3: إنشاء إعداد Token ACL

بعد إنشاء الـ mint، أنشئ إعداد 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;
}

الخطوة 4: إعداد ABL Gate Program

أنشئ قائمة ABL وإعداد 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");
}

الخطوة 5: تفعيل الإذابة بلا إذن

مكّن المستخدمين من إذابة حساباتهم الخاصة:

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

الخطوة 6: يُذيب المستخدم حسابه

يمكن للمستخدمين الآن إذابة حساباتهم الخاصة باستخدام 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!");
}

استخدام @solana/token-helpers للإذابة التلقائية

يمكن لحزمة SDK الخاصة بـ @solana/token-helpers اكتشاف منتجات Token ACL تلقائياً وتضمين تعليمات الإذابة:

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

متطلب TokenMetadata

لكي يعمل الاكتشاف التلقائي في @solana/token-helpers، يجب أن يمتلك mint الخاص بك:

  1. امتداد TokenMetadata مُهيَّأً
  2. حقل additionalMetadata بمفتاح token_acl وقيمة مضبوطة على عنوان Gate Program

قوائم السماح + الحظر المركّبة

للحصول على أقصى قدر من التحكم في الامتثال، ادمج قوائم السماح والحظر:

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

سلوك القائمة المركّبة

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

حالات الاستخدام

1. رموز الأوراق المالية (KYC مطلوب)

استخدم قائمة السماح لضمان أن المستثمرين المتحقق منهم بـ KYC فقط يمكنهم امتلاك الرموز:

// 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. الامتثال للعقوبات

استخدم قائمة الحظر لمنع العناوين الخاضعة للعقوبات من استلام الرموز:

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

3. رمز مفتوح مع حماية PDA

استخدم AllowAllEoas للسماح لجميع المحافظ العادية مع حظر PDAs (العقود الذكية):

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

4. امتثال مؤسسي كامل

ادمج قائمة السماح + قائمة الحظر للتحكم الكامل:

  • قائمة السماح: المستثمرون المتحقق منهم بـ KYC
  • قائمة الحظر: العناوين الخاضعة للعقوبات، الموظفون المُنهَى عقودهم، إلخ.

اعتبارات الإنتاج

قبل النشر في بيئة الإنتاج:

  1. عمليات التدقيق الأمني: احصل على عمليات تدقيق أمني احترافية لتطبيقك وأي Gate Programs مخصصة

  2. إدارة المفاتيح: استخدم حلول حضانة مناسبة لمفاتيح الصلاحيات. فكّر في التوقيع المتعدد للعمليات الحساسة

  3. الامتثال التنظيمي: استشر خبراء قانونيين بشأن لوائح الأوراق المالية، متطلبات KYC/AML، وامتثال العقوبات

  4. إدارة القوائم: ابنِ أنظمة متينة لإدارة قوائم السماح/الحظر، بما فيها:

    • تكامل فحص العقوبات التلقائي
    • تكامل مزوّد KYC
    • سجلات التدقيق
  5. المراقبة: طبّق مراقبة لـ:

    • محاولات الإذابة الفاشلة (مشكلات امتثال محتملة)
    • تعديلات القوائم
    • استخدام مفاتيح الصلاحيات
  6. التعافي من الكوارث: خطّط لتدوير المفاتيح، واستعادة القوائم، وإجراءات التجميد الطارئة

إصدار Solana CLI

يتطلب Token ACL مع TokenMetadata Solana CLI 2.x. هناك مشكلة معروفة في CLI 3.x تُعطّل ميزة التوسيع التلقائي لـ TokenMetadata. تحقق دائماً من إصدار CLI الخاص بك قبل النشر.

واجهة سطر الأوامر (CLI)

يوفر كلٌّ من Token ACL وABL Gate Program واجهات CLI لإدارة الإعدادات والقوائم دون كتابة كود. هذا مفيد لفرق العمليات.

Token ACL CLI

يُدير Token ACL CLI إعدادات الـ mint وعمليات التجميد/الإذابة.

التثبيت

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

أوامر Token ACL

الأمرالوصف
create-configينشئ إعداد mint جديداً (ينقل صلاحية التجميد)
delete-configيحذف إعداد mint
set-authorityيضبط صلاحية إعداد mint
set-gating-programيضبط برنامج البوابة لإعداد الإصدار
set-instructionsتمكين/تعطيل الإذابة/التجميد بدون إذن
thawيُذيب token account (يتطلب صلاحية)
freezeيجمّد token account (يتطلب صلاحية)
thaw-permissionlessيُذيب token account بدون إذن
freeze-permissionlessيجمّد token account بدون إذن
create-ata-and-thaw-permissionlessينشئ associated token account ويُذيبه في أمر واحد

إنشاء إعداد ACL للرمز

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

تمكين الإذابة بدون إذن

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

عمليات الإذابة/التجميد

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

إنشاء associated token account وإذابته في أمر واحد

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

واجهة CLI لبوابة ABL (allow-block-list)

تُدير واجهة CLI لبوابة ABL قوائم السماح/الحظر وإدخالات المحافظ.

التثبيت

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

أوامر بوابة ABL

الأمرالوصف
create-listينشئ قائمة سماح/حظر جديدة
delete-listيحذف قائمة
add-walletيضيف محفظة إلى قائمة
remove-walletيزيل محفظة من قائمة
apply-lists-to-mintيُهيّئ القوائم المطبّقة على عملية الإصدار

إنشاء قائمة

# 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

يُخرج الأمر عنوان PDA الخاص بـ list_config والـ seed - احفظهما!

إدارة المحافظ في القوائم

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

تطبيق القوائم على عملية الإصدار

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

الخيارات العامة لواجهة CLI

تدعم كلتا واجهتَي CLI هذه الخيارات:

الخيارالوصف
-u, --url <URL>رابط RPC (الافتراضي: من إعداد سولانا)
-k, --payer <KEYPAIR>ملف keypair الدافع أو المحفظة المادية
-C, --config <PATH>مسار ملف إعداد سولانا
-v, --verboseعرض معلومات إضافية

مثال على سير عمل كامل باستخدام واجهة CLI

إليك سير عمل كامل يستخدم جميع واجهات CLI لإعداد رمز متوافق من الصفر:

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

البيانات الوصفية للرمز للكشف التلقائي

يُعدّ إضافة حقل البيانات الوصفية token_acl أمراً بالغ الأهمية لتكامل المحافظ. عندما ترى المحافظ كـ Phantom أو حزم SDK كـ @solana/token-helpers هذا الحقل، فإنها تُدرج تعليمات الإذابة تلقائياً عند إنشاء token accounts.

spl-token update-metadata $MINT token_acl GATEzzqxhJnsWF6vHRsgtixxSB8PaQdcqGEVTEHWiULz

الخطوات التالية

  1. جرّب الورشة: استنسخ مستودع token-acl وشغّل أمثلة العرض التوضيحي. اقرأ تفاصيل تنفيذ ACL و برنامج بوابة ABL.

  2. بناء برامج بوابة مخصصة: برنامج بوابة ABL هو مجرد تنفيذ مرجعي. ابنِ برنامج بوابتك الخاص للتكامل مع البنية التحتية للامتثال الموجودة لديك، أو موفري الهوية، أو لتنفيذ منطق مخصص يناسب متطلباتك المحددة

  3. التكامل مع DeFi: رموز Token ACL قابلة للتركيب بالكامل مع بروتوكولات DeFi

  4. اقرأ المواصفات: راجع sRFC37 للاطلاع على المواصفات التقنية الكاملة وانضم إلى نقاش sRFC37

الخاتمة

يوفر Token ACL (sRFC37) حلاً فعّالاً للمؤسسات التي تحتاج إلى رموز متوافقة وخاضعة للتحكم دون التضحية بتجربة المستخدم التي تمنح سلاسل الكتل قيمتها. الفوائد الرئيسية:

  • التفعيل الفوري: يمكن للمستخدمين إذابة حساباتهم بأنفسهم
  • تحكم كامل في الامتثال: قوائم السماح، وقوائم الحظر، أو المنطق المخصص
  • برامج بوابة مرنة: استخدم تنفيذ ABL المرجعي أو ابنِ برامج بوابة مخصصة تتكامل مع بنيتك التحتية للامتثال
  • تكامل سلس: تتعامل حزم SDK مع التعقيد تلقائياً
  • قابل للتركيب: يعمل مع بروتوكولات DeFi الحالية
  • مُدقَّق: برامج جاهزة للإنتاج ومنشورة على الشبكة الرئيسية

يُنشئ الجمع بين امتداد DefaultAccountState الخاص بـ Token-2022 وعمليات Token ACL بدون إذن نموذجاً جديداً لإصدار الرموز المتوافقة على سولانا.

Is this page helpful?

جدول المحتويات

المشكلةالحللماذا Token ACL؟Token ACL مقابل Transfer Hooksمتى تستخدم Token ACLمتى تستخدم Transfer Hooksنظرة عامة على البنيةالمفاهيم الأساسيةأوضاع ABL Gate Programعناوين البرامجالمتطلبات الأساسيةالتطبيق الكاملالخطوة 1: تثبيت التبعياتالخطوة 2: إنشاء رمز مع Token ACLالخطوة 3: إنشاء إعداد Token ACLالخطوة 4: إعداد ABL Gate Programالخطوة 5: تفعيل الإذابة بلا إذنالخطوة 6: يُذيب المستخدم حسابهاستخدام @solana/token-helpers للإذابة التلقائيةقوائم السماح + الحظر المركّبةسلوك القائمة المركّبةحالات الاستخدام1. رموز الأوراق المالية (KYC مطلوب)2. الامتثال للعقوبات3. رمز مفتوح مع حماية PDA4. امتثال مؤسسي كاملاعتبارات الإنتاجواجهة سطر الأوامر (CLI)Token ACL CLIالتثبيتأوامر Token ACLإنشاء إعداد ACL للرمزتمكين الإذابة بدون إذنعمليات الإذابة/التجميدإنشاء associated token account وإذابته في أمر واحدواجهة CLI لبوابة ABL (allow-block-list)التثبيتأوامر بوابة ABLإنشاء قائمةإدارة المحافظ في القوائمتطبيق القوائم على عملية الإصدارالخيارات العامة لواجهة CLIمثال على سير عمل كامل باستخدام واجهة CLIالخطوات التاليةالخاتمة
تعديل الصفحة