Skip to main content
هذه الصفحة مُترجَمة آليًا بواسطة الذكاء الاصطناعي. النسخة الإنجليزية هي المرجع المعتمد.عرض النسخة الإنجليزية →
PDAs (العناوين المشتقة من البرنامج) و CPIs (الاستدعاء عبر البرامج) هما البدائيتان اللتان تجعلان Raydium ممكنة. تسمح PDAs لبرنامج بـ “امتلاك” عناوين حتمية بدون مفاتيح خاصة — هكذا تعمل سلطات المجمعات والخزائن. تسمح CPIs لبرنامج واحد باستدعاء برنامج آخر — هكذا يقوم Raydium بمبادلة الرموز عبر برنامج SPL Token وكيف يدمج المدمجون Raydium في تدفقاتهم الخاصة. كلاهما يستحق الفهم قبل قراءة كود Raydium.

PDAs: عناوين بدون مفاتيح

العنوان المشتق من البرنامج هو مفتاح عام يتمتع بالخصائص التالية:
  • لا يقع على منحنى ed25519 (لا يوجد مفتاح خاص له).
  • مشتق بشكل حتمي من معرّف البرنامج ومجموعة من البذور.
  • يمكن التوقيع عليه من قبل فقط برنامج الاشتقاق، عبر invoke_signed.
كل سلطة مجمع Raydium، كل حساب حالة مجمع، كل خزينة، كل حالة مزرعة — كلها PDAs.

الاشتقاق

يتم حساب PDA بتجزئة معرّف البرنامج مع البذور، ثم إيجاد بايت “bump” يفرض النتيجة خارج المنحنى. أول bump (عادة يبدأ من 255 وينخفض) ينتج عنه عنوان خارج المنحنى يفوز؛ هذا هو الـ bump الكنسي.
يمكن أن تكون البذور أي شيء — سلاسل نصية، مفاتيح عامة أخرى، قيم u64 كبايتات little-endian. اتفاقية Raydium هي بادئة قابلة للقراءة من قبل الإنسان متبوعة بمعرّفات فريدة.

أنماط PDA في Raydium

PDAs الشائعة في برامج Raydium: يمكن للمستخدمين والمدمجين حساب هذه بدون جلب أي شيء — بالنظر إلى المدخلات العامة (معرّف المجمع، معرّف المزرعة، مفتاح المستخدم)، فإن PDA حتمي.

الـ bump الكنسي

على الرغم من أنه يمكن في المبدأ أن يكون هناك عدة bumps تنتج عناوين خارج المنحنى، تستخدم برامج Raydium دائمًا الـ bump الكنسي (الموجود بالتناقص من 255). يتم تخزين هذا في بيانات حساب PDA بحيث يمكن للمعاملات اللاحقة تمريره وتخطي حلقة الاشتقاق (المكلفة):
(يخزن PoolState في CLMM bump: [u8; 1] بدلاً من ذلك، لذا تحقق من struct البرنامج المحدد بدلاً من افتراض شكل واحد.) في المعاملات اللاحقة، يتم قراءة الـ bump من حالة المجمع بدلاً من إعادة حسابه.

CPIs: استدعاء برامج أخرى

الاستدعاء عبر البرامج يسمح لبرنامج باستدعاء تعليمات برنامج آخر بشكل مضمن ضمن معاملة واحدة. يستخدم Raydium CPIs على نطاق واسع:
  • تعليمات المبادلة تستدعي برنامج SPL Token لنقل الرموز.
  • يستدعي CLMM Metaplex لسك موضع NFT.
  • ينادي إنشاء المجمع برنامج النظام لتخصيص الحسابات.
  • يستدعي Farm v6 SPL Token لنقل المكافآت.
يستخدم المدمجون أيضًا CPIs للاستدعاء إلى Raydium — هكذا تعمل استراتيجيات الخزائن وبروتوكولات LP ذات الرافعة والمركبات التلقائية. انظر integration-guides/cpi-integration.

invoke مقابل invoke_signed

توفر وقت تشغيل Solana بدائيتي CPI:
  • invoke: استدعاء برنامج آخر؛ يرث البرنامج المستدعى الموقعين من المعاملة الخارجية.
  • invoke_signed: استدعاء برنامج آخر نيابة عن PDA؛ يتحقق وقت التشغيل من بذور PDA ويصرح بالتوقيع.
invoke_signed هو السحر الذي يسمح للبرامج بالاحتفاظ بالسلطة على الحسابات بدون إدارة المفاتيح الخاصة.

مثال: Raydium تنقل من خزينة المجمع

خزينة المجمع هي حساب Token تكون سلطته PDA من برنامج المجمع. لنقل الرموز أثناء المبادلة، يجب على برنامج المجمع التوقيع كـ PDA:
يرى وقت التشغيل أن invoke_signed يتم استدعاؤه من قبل برنامج CPMM، يتحقق من أن vault_and_lp_mint_auth_seed + bump مشتق إلى عنوان pool_authority عند تجزئته مع معرّف برنامج CPMM، ويسمح بتوقيع السلطة على نقل الرمز. لا يوجد مفتاح خاص متورط.

مثال: المدمج يستدعي Raydium CPMM

يمكن لبرنامج المدمج (على سبيل المثال، escrow) استدعاء swap_base_input في Raydium عبر CPI:
هذا هو نمط التكامل الكنسي — انظر integration-guides/cpi-integration للحصول على مثال escrow كامل.

حد عمق CPI

يحد Solana عمق CPI عند 4 مستويات. تعليمة المستوى الأعلى للمعاملة تحسب كعمق 0؛ كل استدعاء CPI يزيد العمق. الآثار العملية: المبادلة الخاصة بـ Raydium بالفعل تستخدم 1-2 مستويات من CPI (Raydium → SPL Token). يستخدم المدمج الذي يستدعي Raydium 2. إذا تم استدعاء هذا المدمج من قبل مدمج آخر، فهو 3. المستوى الرابع هو الحد. تبقى معظم التركيبات تحت هذا بسهولة، لكن التداخل العميق (aggregator → router → Raydium → hook) يمكن أن يصل إليه. صمم بشكل مسطح بدلاً من عميق.

الحسابات المتبقية

عندما تحتاج تعليمة Raydium إلى عدد متغير من الحسابات (على سبيل المثال، مبادلة CLMM تعبر عددًا غير معروف من مصفوفات tick)، يتم تمرير الحسابات الإضافية كـ حسابات متبقية — مُلحقة بقائمة الحسابات الثابتة، يتم تفسيرها حسب الموضع. يستخدم SwapV2 في CPMM الحسابات المتبقية لحسابات البرامج الإضافية المطلوبة من transfer-hook. يجلب العملاء الحسابات المطلوبة ويلحقونها:
على مستوى CPI، يجب على المدمجين إعادة توجيه الحسابات المتبقية من خلال تعليماتهم الخاصة:

مخاطر PDA

البذور الخاطئة → عنوان خاطئ

خطأ حيث تكون البذور بترتيب خاطئ أو ترميز خاطئ أو تتضمن/تستبعد بايت إضافي ينتج بصمت PDA مختلف. تفشل المعاملة بشكل غامض (يحاول البرنامج قراءة حساب غير موجود). اختبر دائمًا اشتقاق البذور مقابل قيم ذهبية معروفة.

عدم تخزين الـ bump

إذا أعدت اشتقاق الـ bump في كل معاملة، فأنت تدفع حسابًا لحلقة الاشتقاق. خزّن الـ bump الكنسي في بيانات PDA واقرأه من هناك.

الخلط بين الـ bump الكنسي وغير الكنسي

يُسمح بـ bumps غير الكنسية (إذا وجد أحد واحدًا ينتج عنه خارج المنحنى) بواسطة invoke_signed لكن يتم رفضها من قبل برامج Raydium عبر assert_eq!(bump, canonical_bump). إذا حاول شخص ما المطالبة بـ PDA مع bump غير كنسي، فإن المعاملة تفشل.

تمرير PDA كموقع عندما لا تكون برنامج المالك

فقط البرنامج الذي معرّفه في اشتقاق PDA يمكنه invoke_signed مع بذوره. إذا حاولت، يرفض وقت التشغيل.

مخاطر CPI

نسيان إعادة توجيه remaining_accounts

إذا مررت تعليماتك الخارجية حسابات transfer-hook في remaining_accounts لكن CPI إلى Raydium لا يعيد توجيهها، فإن Raydium يفشل لأنه لا يمكنه العثور على حسابات hook. ضمّن دائمًا with_remaining_accounts في CPIs التي تحتاجها.

عدم تطابق أعلام قابلة للكتابة

يجب أن يكون الحساب الذي تحدده التعليمات الخارجية كقابل للكتابة أيضًا قابلاً للكتابة في استدعاء CPI إذا كان البرنامج المستدعى ينوي كتابته. عدم التطابق → رفض وقت التشغيل.

عدم حساب الإيجار

CPI لبرنامج ينشئ حسابًا (على سبيل المثال، إنشاء ATA) يتطلب من الدافع أن يكون لديه SOL كافٍ للإيجار. فحوصات الإيجار الفاشلة تظهر كأخطاء غامضة.

مثال عملي: حساب PDAs Raydium CPMM

هذا بالضبط ما يفعله Raydium SDK تحت الغطاء عند استدعاء getPoolInfoFromRpc({ poolId }) — فهو يشتق PDAs المرتبطة بدون رحلة ذهاب وإياب.

مؤشرات

المصادر: