الانتقال إلى المحتوى الرئيسي

Documentation Index

Fetch the complete documentation index at: https://docs.raydium.io/llms.txt

Use this file to discover all available pages before exploring further.

هذه الصفحة مُترجَمة آليًا بواسطة الذكاء الاصطناعي. النسخة الإنجليزية هي المرجع المعتمد.عرض النسخة الإنجليزية →

رسمان مستقلان، أربع وجهات

يفرض CPMM رسمين بمعدلات منفصلة على كل مبادلة:
  1. رسم التداول — يُحتسب بـ AmmConfig.trade_fee_rate وينقسم إلى ثلاث وجهات:
    • حصة مزود السيولة (LP) — تبقى في الخزينة وتزيد k. يتم المطالبة بها ضمنيًا بحرق رموز LP.
    • حصة البروتوكول — تُستحق على PoolState.protocol_fees_token*؛ يتم جمعها بواسطة protocol_owner عبر CollectProtocolFee.
    • حصة الصندوق — تُستحق على PoolState.fund_fees_token*؛ يتم جمعها بواسطة fund_owner عبر CollectFundFee.
  2. رسم المنشئ (اختياري، لكل pool) — يُحتسب بـ AmmConfig.creator_fee_rate بشكل مستقل عن رسم التداول، يُستحق على PoolState.creator_fees_token*، يتم جمعه بواسطة pool_state.pool_creator عبر CollectCreatorFee. يكون نشطًا فقط عندما تم إنشاء pool باستخدام enable_creator_fee = true.
رسم المنشئ ليس جزءًا من رسم التداول. يتم إضافة المعدلين معًا عند حساب الرسم على مدخل التبادل، لكن كل واحد منهما يبقى في سلة خاصة به — حصص البروتوكول والصندوق تُشتق دائمًا من trade_fee فقط، لا من creator_fee. يفرض pool بـ creator_fee_rate = 1000 (0.10%) و trade_fee_rate = 2500 (0.25%) رسمًا مجمعًا بنسبة 0.35% من المدخل على مبادلة “creator-fee-on-input”، منها يحتفظ المنشئ بـ 0.10% وتحصل سلة رسم التداول على 0.25%. معدلات رسم التداول (trade_fee_rate, protocol_fee_rate, fund_fee_rate) و creator_fee_rate موجودة جميعها على AmmConfig. العلم لكل pool enable_creator_fee وموضع creator_fee_on (أي جانب من التداول يتم أخذ رسم المنشئ منه) موجودان على PoolState. انظر products/cpmm/accounts.

المعدلات والوحدات

جميع المعدلات u64s موصوفة بوحدات 1 / FEE_RATE_DENOMINATOR حيث FEE_RATE_DENOMINATOR = 1_000_000.
  • trade_fee_rate هو جزء من حجم المبادلة. 2500 ⇒ 0.25% من الجانب ذي الصلة (مدخل أو مخرج، حسب creator_fee_on — انظر “أي جانب من التداول يتم أخذ الرسوم منه” أدناه).
  • creator_fee_rate هو جزء من حجم المبادلة، يتم أخذه بشكل منفصل عن رسم التداول. 1000 ⇒ 0.10% من الجانب ذي الصلة.
  • protocol_fee_rate و fund_fee_rate هما نسبتان من رسم التداول، وليس من الحجم. 120_000 ⇒ 12% من رسم التداول.
معاملات افتراضية لـ AmmConfig[index=0] (pool “المعياري” 0.25%) على mainnet، للمرجعية:
الحقلالقيمةالنسبة المئوية الفعلية
trade_fee_rate25000.25% من الحجم (سلة رسم التداول)
protocol_fee_rate12000012% من رسم التداول ≈ 0.030% من الحجم
fund_fee_rate400004% من رسم التداول ≈ 0.010% من الحجم
creator_fee_rate0 (افتراضي)0% (سلة منفصلة)
→ حصة LP الفعلية0.210% من الحجم
لذا على مبادلة بقيمة $1,000 مقابل AmmConfig[0] مع enable_creator_fee = false: $2.50 إجمالي رسم التداول، منها $2.10 تبقى مع مزودي السيولة، $0.30 تذهب للبروتوكول، $0.10 للصندوق. سلة المنشئ هي 0 لأن رسم المنشئ معطّل. إذا كان نفس pool به enable_creator_fee = true و creator_fee_rate = 1000 (0.10%)، يدفع المستخدم إضافي $1.00 لسلة المنشئ — يتم أخذه من نفس جانب التداول المُعدّ بواسطة creator_fee_on — لإجمالي $3.50 من الرسوم. سلة رسم التداول وانقساماتها بين البروتوكول والصندوق تبقى دون تغيير. تأكد من القيم الحالية على mainnet مقابل GET https://api-v3.raydium.io/main/cpmm-config — المعدلات قابلة للتغيير من قبل المسؤول وينبغي قراءتها بشكل طازج بدلاً من برمجتها.

الانقسام، في الكود

// معاد صياغة من raydium-cp-swap/programs/cp-swap/src/curve/{calculator,fees}.rs.
// الكود الفعلي يتفرع على `is_creator_fee_on_input`؛ كلا الفرعين يحافظان على
// الثابت أن creator_fee هو معدله الخاص، وليس أبدًا جزءًا من trade_fee.

const FEE_RATE_DENOMINATOR_VALUE: u64 = 1_000_000;

pub struct FeeBreakdown {
    pub amount_in_after_fees: u64,    // المدخل بعد خصم جميع الرسوم من جانب المدخل
    pub amount_out_after_fees: u64,   // المخرج بعد طرح أي رسم منشئ من جانب المخرج
    pub trade_fee:    u64,            // → ينقسم إلى سلات LP / بروتوكول / صندوق أدناه
    pub protocol_fee: u64,            // حصة من trade_fee
    pub fund_fee:     u64,            // حصة من trade_fee
    pub creator_fee:  u64,            // سلة مستقلة (جانب المدخل أو المخرج)
}

fn take_fees_on_input(
    amount_in: u64,
    trade_rate: u64,
    creator_rate: u64,
    protocol_rate: u64,
    fund_rate: u64,
) -> (u64 /* trade_fee */, u64 /* creator_fee */, u64 /* amount_in_after_fees */) {
    // يتم إضافة المعدلين لذا نقرب مرة واحدة على الرسم المجمع، ثم ننقسم
    // بناءً على التناسب — هذا مجرد خدعة تقريب/كفاءة. الانقسام
    // يحترم المعدلات بدقة: creator_fee/trade_fee == creator_rate/trade_rate.
    let total_fee = ((amount_in as u128) * ((trade_rate + creator_rate) as u128))
        .div_ceil(FEE_RATE_DENOMINATOR_VALUE as u128) as u64;

    let creator_fee = ((total_fee as u128) * (creator_rate as u128)
                       / ((trade_rate + creator_rate) as u128)) as u64;
    let trade_fee   = total_fee - creator_fee;

    (trade_fee, creator_fee, amount_in - total_fee)
}

fn take_creator_fee_on_output(amount_out_swapped: u64, creator_rate: u64) -> (u64, u64) {
    // عندما يوجه creator_fee_on رسم المنشئ إلى جانب المخرج،
    // يتم أخذ trade_fee من المدخل كمعدل واحد، و creator_fee
    // يُحسب ضد مخرج المنحنى.
    let creator_fee = ((amount_out_swapped as u128) * (creator_rate as u128))
        .div_ceil(FEE_RATE_DENOMINATOR_VALUE as u128) as u64;
    (amount_out_swapped - creator_fee, creator_fee)
}

fn split_trade_fee(
    trade_fee: u64,
    protocol_rate: u64,
    fund_rate: u64,
) -> (u64 /* protocol_fee */, u64 /* fund_fee */) {
    let protocol_fee = (trade_fee as u128 * protocol_rate as u128
                        / FEE_RATE_DENOMINATOR_VALUE as u128) as u64;
    let fund_fee     = (trade_fee as u128 * fund_rate as u128
                        / FEE_RATE_DENOMINATOR_VALUE as u128) as u64;
    (protocol_fee, fund_fee)
}
ملاحظات:
  • إجمالي الرسم على المدخل يقرّب لأعلى بحيث لا يقل البروتوكول أبدًا.
  • الانقسامات الفرعية لـ trade_fee (بروتوكول، صندوق) تقرّب لأسفل بحيث لا يتجاوز مجموعهما trade_fee؛ البقية هي حصة LP.
  • lp_share = trade_fee − protocol_fee − fund_fee (creator_fee لا يُطرح هنا لأنه سلة خاصة به).
  • يتم أخذ رسم المنشئ من المدخل أو المخرج حسب PoolState.creator_fee_on (انظر القسم التالي). المعدل لا يتغير في كلا الحالتين.

أي جانب من التداول يتم أخذ الرسوم منه

يحتوي CPMM على إعداد لكل pool يسمى creator_fee_on (BothToken / OnlyToken0 / OnlyToken1) يحدد ما إذا كان رسم المنشئ يتم أخذه من جانب المدخل أو جانب المخرج من مبادلة معينة. دالة المساعد في وقت التشغيل is_creator_fee_on_input(direction) تختصرها إلى قيمة منطقية لكل مبادلة:
creator_fee_onمبادلة 0 → 1مبادلة 1 → 0
BothToken (0)جانب المدخلجانب المدخل
OnlyToken0 (1)جانب المدخلجانب المخرج
OnlyToken1 (2)جانب المخرججانب المدخل
عندما يكون رسم المنشئ على جانب المدخل، يتم خصم رسم التداول ورسم المنشئ معًا من amount_in قبل تشغيل المنحنى. رياضيات الاقتباس: أزل trade_rate + creator_rate من المدخل. عندما يكون رسم المنشئ على جانب المخرج، يتم خصم رسم التداول فقط من amount_in؛ ينتج المنحنى مخرجًا بدون رسم، ثم يتم خصم رسم المنشئ من هذا المخرج. رياضيات الاقتباس: أزل trade_rate من المدخل؛ أزل creator_rate من المخرج. رسم التداول نفسه يتم أخذه دائمًا من جانب المدخل (نمط Uniswap-V2 المعياري). فقط رسم المنشئ يمكن أن ينتقل إلى المخرج.

كيف تتفاعل رسوم “المستحقة” مع المنحنى

دقة مهمة: رسوم البروتوكول والصندوق والمنشئ تبقى فيزيائيًا في الخزينة حتى يتم استدعاء تعليمة Collect* الخاصة بها. لكن يتم استبعادها من رؤية المنحنى لرصيد الخزينة. صورة ملموسة بعد مبادلة واحدة:
raw_vault_0_balance = getTokenAccountBalance(vault_0).amount
                    = lp_entitled + protocol_fees_token0
                      + fund_fees_token0 + creator_fees_token0

curve_x = raw_vault_0_balance − (protocol_fees_token0
                                  + fund_fees_token0
                                  + creator_fees_token0)
يستخدم البرنامج curve_x (والمثيل المماثل curve_y) عند فرض k' ≥ k. هذه هي الطريقة التي تصل بها رسوم غير LP إلى وجهاتها بدون تضخيم حصة LP من البركة. العواقب التي يجب أن تصمم حولها:
  • الاقتباس من الأرصدة الخام خطأ. إذا بنيت quoter على getTokenAccountBalance، ستبالغ باستمرار في سعر البركة. اطرح دائمًا الرسوم المستحقة، أو محاكي عبر SwapBaseInput / الـ API.
  • CollectProtocolFee لا يحرك السعر. ينقل الرموز خارج الخزينة و يصفر عدادات protocol_fees_token*، لذا curve_x و curve_y لم تتغير.
  • رسوم LP لا تستحق على عداد. إنها ضمنية في رصيد الخزينة. استحقاق LP للرسوم LP المتراكمة يتم ممارسته بحرق رموز LP (أي عبر Withdraw) — لا يوجد CollectLpFee.

التفاعل مع رسوم نقل Token-2022

يتم تطبيق رسوم نقل Token-2022 من قبل الرموز، وليس من قبل CPMM. تعمل على كل نقل رموز — مبادلة، إيداع، سحب، وعمليات جمع Collect*. يتم حساب رياضيات رسم التداول في CPMM مقابل المبلغ الذي وصل فعلاً إلى الخزينة، أي بعد خصم رسم نقل مدخل الرموز (إن وجد). لذا في أسوأ الحالات يدفع المستخدم ثلاث ضرائب متميزة على مبادلة input-exact:
  1. رسم نقل مدخل الرموز على amount_in (لسلطة رسوم الرموز).
  2. trade_fee البركة على البقية (مقسم كما هو أعلاه).
  3. رسم نقل مخرج الرموز على amount_out (لسلطة رسوم الرموز).
يحسب quoter في SDK جميع الثلاثة لذا minimum_amount_out موصوف بما يستقبله المستخدم فعلاً. إذا كنت تكتب quoter خاص بك، اعكس هذا السلوك، أو ستكون عمليات فحص الانزلاق لديك متساهلة بشكل منهجي. انظر algorithms/token-2022-transfer-fees للاشتقاق التفصيلي.

رسم المنشئ

رسم المنشئ اختياري ولكل pool. المعدل موجود على AmmConfig.creator_fee_rate؛ العلم التفعيل و الجانب (creator_fee_on) موجودان على PoolState:
  • تفعيل عند إنشاء البركة. Initialize يعيّن enable_creator_fee = false افتراضيًا؛ يمكن للبرك المنشأة عبر InitializeWithPermission (المستخدمة بواسطة تخرجات LaunchLab والطرق المحمية الأخرى) أن تمرر enable_creator_fee = true واختيار creator_fee_on.
  • المعدل مشترك مع طبقة الرسم. المعدل نفسه هو AmmConfig.creator_fee_rate، نفس القيمة عبر كل بركة مرتبطة بهذا التكوين. يقرر كل pool بعد ذلك ما إذا كان سيفرضه (enable_creator_fee) وأي جانب من المبادلة سيفرضه عليه (creator_fee_on). عندما enable_creator_fee = false، معدل رسم المنشئ الفعلي للبركة هو صفر بغض النظر عن قيمة التكوين (انظر PoolState::adjust_creator_fee_rate في المصدر).
  • مستقل عن رسم التداول. رسم المنشئ لا يقلل أبدًا من حصص LP / البروتوكول / الصندوق — إنه معدله الخاص، يُطبق بشكل منفصل، يُستحق في عدادات خاصة به.
  • يتم جمعه عبر CollectCreatorFee، موقّع من قبل PoolState.pool_creator.
  • لا يمكن إعادة تفعيله أو إعادة توجيهه بعد الإنشاء. بركة مهيأة مع enable_creator_fee = false لن تفرض أبدًا رسم منشئ؛ واحدة مهيأة مع creator_fee_on معين لا يمكنها تبديل الجوانب.
رسوم المنشئ هي الآلية وراء نمط Raydium “Burn & Earn”: يتم قفل رموز LP تحت برنامج LP Lock بحيث لا يمكن للمنشئ سحب السيولة، لكن يمكنه المطالبة بـ CollectCreatorFee إلى الأبد.

تدفق جمع العمليات

الموقّعالتعليمةعدادات المصدر المصفرةالوتيرة المعتادة
amm_config.protocol_ownerCollectProtocolFeeprotocol_fees_token{0,1}أسبوعيًا أو برمجيًا
amm_config.fund_ownerCollectFundFeefund_fees_token{0,1}أسبوعيًا أو برمجيًا
pool_state.pool_creatorCollectCreatorFeecreator_fees_token{0,1}في أي وقت
مالكو البروتوكول والصندوق هم مجموعة Raydium متعددة التوقيع على mainnet؛ انظر security/admin-and-multisig. الموقّع المنشئ هو الحساب الذي شغّل Initialize.

تغيير طبقة رسم

يمكن تغيير معدلات الرسوم من قبل المسؤول عبر UpdateAmmConfig (انظر products/cpmm/instructions). تدخل التغييرات حيز التنفيذ على المبادلة التالية لكل بركة مرتبطة بـ AmmConfig — لا توجد هجرة، لأن البرك تحمل التكوين في كل مبادلة. ما لا يستطيع المسؤول فعله:
  • نقل بركة من AmmConfig إلى آخر.
  • إعادة تسعير الرسوم المستحقة بأثر رجعي.
  • جمع الرسوم بدون موقّع protocol_owner / fund_owner.

قراءة الرسوم من بركة تعمل

// خارج السلسلة: الرسوم المستحقة الحالية في كل سلة
const pool = await connection.getAccountInfo(poolStatePda);
const decoded = PoolState.decode(pool.data);
console.log(
  "Protocol accrued:",
  decoded.protocolFeesToken0.toString(),
  decoded.protocolFeesToken1.toString(),
);
console.log(
  "Fund accrued:",
  decoded.fundFeesToken0.toString(),
  decoded.fundFeesToken1.toString(),
);
console.log(
  "Creator accrued:",
  decoded.creatorFeesToken0.toString(),
  decoded.creatorFeesToken1.toString(),
);

// خارج السلسلة: المعدلات الفعلية اليوم.
// trade_fee_rate, creator_fee_rate هما نسب من الحجم (مقسوم 1e6).
// protocol_fee_rate, fund_fee_rate هما نسب من *رسم التداول* (نفس المقسوم).
const config = await fetch("https://api-v3.raydium.io/main/cpmm-config")
  .then((r) => r.json());
const tier = config.data.find((t) => t.index === decoded.ammConfigIndex);

const tradeFeeOfVolume   = tier.tradeFeeRate / 1_000_000;
const protocolOfTradeFee = tier.protocolFeeRate / 1_000_000;
const fundOfTradeFee     = tier.fundFeeRate / 1_000_000;
const lpOfTradeFee       = 1 - protocolOfTradeFee - fundOfTradeFee;

console.log("LP fee effective:",       (tradeFeeOfVolume * lpOfTradeFee * 100).toFixed(4), "%");
console.log("Protocol fee effective:", (tradeFeeOfVolume * protocolOfTradeFee * 100).toFixed(4), "%");
console.log("Fund fee effective:",     (tradeFeeOfVolume * fundOfTradeFee * 100).toFixed(4), "%");
console.log(
  "Creator fee effective:",
  decoded.enableCreatorFee
    ? ((tier.creatorFeeRate / 1_000_000) * 100).toFixed(4) + " %"
    : "0 % (disabled on this pool)",
);

مقارنة مع CLMM و AMM v4

انظر reference/fee-comparison للحصول على مصفوفة جنبًا إلى جنب. الملخص:
  • AMM v4 يستخدم رسم تداول ثابت بنسبة 0.25% مع انقسام LP/بروتوكول مختلف وبدون رسم صندوق.
  • رسوم CLMM هي لكل طبقة spacing علامة، مستحقة لكل موضع (وليس لكل بركة)، ويتم المطالبة بها عبر DecreaseLiquidity أو CollectFees.

إلى أين بعد ذلك

المصادر: