يعين FlareWatch لكل مدقق P-Chain درجة مركبة من 0–100 عبر 9 أبعاد. الرياضيات حتمية، والمدخلات هي بيانات السلسلة العامة [Flare Explorer] [FSE] [Flaremetrics]، والخوارزمية نفسها تنطبق على كل مدقق في الشبكة — بما في ذلك عقدة المدقق الخاصة بـ FlareWatch، التي تُسجل بهذه الدالة بالضبط بدون معاملة خاصة. توثق هذه الصفحة كل بُعد وحد أدنى حتى يتمكن المشغلون والمراهنون من رؤية كيفية حساب الدرجة بالضبط ولماذا تم اختيار كل قيمة. كل مطالبة هنا ترتبط بمصدرها الأساسي في السلسلة أو المصدر الأعلى — انظر المصادر والمراجع في الأسفل.
وضع الرهن على صفحة المدققين (تفويض FLR إلى مدقق P-Chain للحصول على مكافآت VRM + MIRROR). تستخدم درجة موفر FTSO الموضحة في وضع التفويض (تفويض WFLR إلى موفري بيانات FTSO) خوارزمية منفصلة بـ 13 بُعد تركز على أداء موفر البيانات — الدقة، مشاركة بروتوكول V2، إلخ. إنها أدوار مختلفة في السلسلة بمكافآت مختلفة، يتم تسجيلها بشكل منفصل. انظر منهجية درجة موفر FTSO لجانب التفويض.العائد السنوي على جدول الرهن هو معدل الجملة الذي يحصل عليه المفوّض — رقم واحد بدون حساب عقلي. يتم قياسه من سكريبتات مكافآت Flare (المدفوعات الفعلية وليس الصيغة)، بخصم من رسم المدقق، وينتقل كل حقبة مع المكافآت الحقيقية. في كل مكان على FlareWatch، العائد السنوي يعني بعد الرسم والعائد السنوي يعني قبله.
مقارنة مع Flare Systems Explorer؟ يعرض FSE ومستكشفات أخرى معدل التفويض فقط — لا يضيفون MIRROR — لذا يقرأ إجمالي العائد السنوي لدينا أعلى على أي مدقق نشط MIRROR (الفجوة بالضبط هي سطر MIRROR أعلاه). كلا الرقمين ~متوسطات زائدة من 8 حقب من نفس بيانات سكريبتات المكافآت، لذا يتأخر تغيير رسم المدقق في منتصف النافذة عن لقطة الرسم الحالي على أي موقع حتى يتقادم من خلال النافذة.
يظهر رقمان آخران في تلميح العائد السنوي وليس معدل المفوّض: الحد الأدنى النظري (إجمالي العائد السنوي للشبكة × (1 − الرسم)، الرهن فقط — يُستخدم كمحاولة أخيرة قبل وجود سجل مقاس كافي)، وعائد السند الذاتي للمشغل (عائد الرهن الخاص للمدقق، مضخم برسم الالتقاط — مقياس مشغل وليس ما تكسبه).
للنقاط: بعد Net Yield ينقط معدل تفويض VRM فقط، ويتم نقط MIRROR في بعده الخاص — لذا لا يتم عد MIRROR مرتين أبدًا، حتى لو تم تضمينه في إجمالي العائد السنوي المعروض.
| 90+ | الفئة الأولى — أفضل ~10–20% من المشغلين. الملف الشخصي النموذجي: مدقق مكدس كامل + FTSO + FDC، رسم منخفض، نشط MIRROR، موثوقية FIP-10 متسقة، قاعدة مفوضين صحية، رابط ذاتي ذو مغزى. لا يلزم بُعد واحد — يصل المشغلون إلى الفئة الأولى بتجميع القوة عبر معظم الفئات. |
| 80–89 | قوي — يلبي معظم المعايير الرئيسية؛ بُعد أو اثنين أقصر من الفئة الأولى. |
| 70–79 | جيد — يلبي جميع معايير الأساس؛ بدون فجوات كبيرة. |
| 60–69 | مقبول — قابل للاستخدام لكن غير متمايز. |
| <60 | دون الوسيط — فجوات كبيرة في بُعد أو أكثر. حقيقة رياضية، وليس حكماً على الجودة. |
if (uptime >= 99.5) raw = 17 + (uptime - 99.5) * 6
else if (uptime >= 99) raw = 13 + (uptime - 99) * 8
else if (uptime >= 95) raw = 4 + (uptime - 95) * 2.25 // v3.9: was (u - 95) * 3.25 starting at 0
else raw = max(0, uptime - 90) * 0.8 // 90 → 0, 95 → 4 (continuity)
raw = clamp(raw, 0, 20)
reliability = epochsIncluded / epochsObserved // last ~8 epochs · v4.2: the
// FULL FIP-10 minimums set
// (uptime + FSP + FTSO + FDC),
// not RPC-uptime alone
score = raw * clamp(reliability, 0, 1) // dimension max 20scoreAPR = delegationAPY > 0 ? delegationAPY : baseAPR // VRM, net of fee medianAPR = median(scoreAPR across all validators) cappedAPR = min(scoreAPR, 25) // APY_DISPLAY_CAP if (medianAPR > 0): ratio = cappedAPR / medianAPR score = clamp(((ratio - 0.6) / 0.6) * 18, 0, 18) else: score = min(18, (cappedAPR / 8) * 18) // fallback: BASE_APY = 8
// anchor = max(observed minimum active fee, 20% protocol floor) d = fee - anchor // distance above market best if (d <= 0) score = 7 // at/below best available else if (d <= 5) score = 7 - d * 0.2 // 0 → 5 over: 7 → 6 else if (d <= 10) score = 6 - (d - 5) * 0.3 // 5 → 10 over: 6 → 4.5 else if (d <= 15) score = 4.5 - (d - 10) * 0.4 // 10 → 15 over: 4.5 → 2.5 else if (d <= 20) score = 2.5 - (d - 15) * 0.5 // 15 → 20 over: 2.5 → 0 else score = 0 // fees > anchor+20 saturate at 0/7 — the v4.5 extreme-fee // penalty below takes over from there
// Verification baseline (v3.10 hybrid) isCurated = (in KNOWN_VALIDATORS) OR ( daysObserved >= 90 AND operatorDelegatorCount >= 25 AND retention30d >= -15% AND selfBondFLR >= 1_000_000 ) if (isCurated) verification = 7 else if (name auto-discovered) verification = 3 else verification = 0 // FTSO-derived (only when ftsoOperatorScore is a number) clamped = clamp(ftsoOperatorScore, 50, 100) ftsoDerived = 4 + (clamped - 50) * (8/50) // FTSO 50 → 4, FTSO 100 → 12 // Final score score = max(verification, ftsoDerived)
passthrough = max(0, 1 - fee / 100) if (mirrorStatus == "active") base = 10 * passthrough else if (mirrorStatus == "paused") base = 5 * passthrough else if (mirrorStatus == "inactive") base = 0 else base = 5 * passthrough // no data yet // v4.6 — capped, median-anchored bonus for delivered MIRROR yield. // Only mirror-active validators paying ABOVE 1.2x the network median // delivered rate (mirrorAPY, net of fee) earn it; size-neutral. ratio = mirrorAPY / networkMedianMirrorAPY bonus = clamp((ratio - 1.2) * 5, 0, 2) // active only, else 0 score = base + bonus // dimension max 12
utilization = clamp(1 - freeSpaceFLR / maxDelegationFLR, 0, 1) if (utilization <= 0.70): score = 1.75 + (utilization / 0.70) * 5.25 // 1.75 → 7 ramp else: score = 7 - ((utilization - 0.70) / 0.30) * 1.75 // 7 → 5.25 ramp
// Count signal (max 6)
if (delegatorCount <= 5) countScore = 0
else if (delegatorCount >= 500) countScore = 6
else countScore = clamp(log(delegatorCount / 5) / log(100) * 6, 0, 6)
// Concentration adjustment (-1 to +1) — skip if <3 delegators
avgFLR = delegatedFLR / delegatorCount
if (avgFLR < 500_000) concentrationAdj = +1
else if (avgFLR < 5_000_000) concentrationAdj = +0.5
else if (avgFLR > 50_000_000) concentrationAdj = -1
else if (avgFLR > 20_000_000) concentrationAdj = -0.5
else concentrationAdj = 0
// Longevity bonus (0 to +1)
daysObserved = (now - firstObservedAtMs) / 86400000
if (daysObserved >= 90) longevityBonus = +1
else if (daysObserved >= 30) longevityBonus = +0.5
else longevityBonus = 0
// Self-bond alignment (-1 to +2, two-axis since v4.7)
if (selfBondFLR < 1_000_000) selfBondAdj = -1 // hollow-operator floor
else:
ratio = selfBondFLR / totalStake // totalStake = selfBond + delegated
proportional = ratio >= 0.10 ? +2 : ratio >= 0.05 ? +1 : 0
absolute = min(1, selfBondFLR / 20_000_000) * 2 // saturates at top-decile bond
selfBondAdj = max(proportional, absolute) // the better of the two axes
// Retention (-0.5 to +0.5, v3.7) — skip if no 30-day baseline yet
delta = (delegatedFLR - delegatedFLR30dAgo) / delegatedFLR30dAgo
if (delta >= +0.10) retentionAdj = +0.5
else if (delta <= -0.15) retentionAdj = -0.5
else retentionAdj = 0
// Self-bond trajectory (-0.5 to +0.5, v3.7) — skip if no baseline
sbDelta = (selfBondFLR - selfBondFLR30dAgo) / selfBondFLR30dAgo
if (sbDelta >= +0.20) selfBondTrajectoryAdj = +0.5
else if (sbDelta <= -0.10) selfBondTrajectoryAdj = -0.5
else selfBondTrajectoryAdj = 0
score = clamp(countScore + concentrationAdj + longevityBonus + selfBondAdj
+ retentionAdj + selfBondTrajectoryAdj, 0, 11)// Time-weighted rate is computed upstream from per-epoch // reward-scripts data with decay = 0.85 per epoch back. r = deliveryRatio // capped at 1.0 if (r >= 1.00) base = 10 else if (r >= 0.97) base = 9 + (r - 0.97) * (1 / 0.03) // 0.97 → 9, 1.00 → 10 else if (r >= 0.95) base = 8 + (r - 0.95) * (1 / 0.02) // 0.95 → 8, 0.97 → 9 else if (r >= 0.90) base = 6 + (r - 0.90) * (2 / 0.05) // 0.90 → 6, 0.95 → 8 else if (r >= 0.85) base = 4 + (r - 0.85) * (2 / 0.05) // 0.85 → 4, 0.90 → 6 else if (r >= 0.80) base = 2 + (r - 0.80) * (2 / 0.05) // 0.80 → 2, 0.85 → 4 else base = max(0, r * 2.5) // 0 → 0, 0.80 → 2 // Variance penalty (CoV = std-dev / mean across per-epoch rates) variancePenalty = min(0.30, coefficientOfVariation * 0.5) score = base * (1 - variancePenalty) // Sample-size confidence dampener for < 3 epochs if (totalStakesCompleted < 3): confidence = totalStakesCompleted / 3 score = 5 + (score - 5) * confidence
daysLeft = (endTimeMs - now) / 86_400_000 if (daysLeft < 14) score = 0 else if (daysLeft < 30) score = 0 + (daysLeft - 14) * (2 / 16) // 14 → 0, 30 → 2 else if (daysLeft < 60) score = 2 + (daysLeft - 30) * (1 / 30) // 30 → 2, 60 → 3 else if (daysLeft < 120) score = 3 + (daysLeft - 60) * (2 / 60) // 60 → 3, 120 → 5 else score = 5
consecutiveMisses = 0 for entry in participation.recent (newest-first): if entry.eligible: break consecutiveMisses++ if consecutiveMisses < 2: penalty = 0 elif consecutiveMisses == 2: penalty = 3 elif consecutiveMisses == 3: penalty = 6 else: penalty = 10 // 4+ score = max(0, positiveDimensionsSum - penalty)
// v4.5 — fees beyond the Fee dimension's range (anchor+20)
if fee <= 50: penalty = 0
else: fraction = min(1, (fee - 50) / 50) * 0.75
penalty = positiveDimensionsSum * fraction
// fee 50% → no change · 75% → −37.5% of score · 100% → −75%
score = max(0, positiveDimensionsSum - outagePenalty - penalty)delegationFee، selfBond، delegatedStake، ودرجة FTSO (إذا كنت أيضًا موفر بيانات).generated-files/reward-epoch-N/nodes-data.json. احسب كم عدد الحقب التي كان nodeID الخاص بك فيها uptimeEligible: true. تلك النسبة تحرك مضاعف بعد Uptime الخاص بك.RewardClaimed مع claimType=3 التي تشير إلى nodeID الخاص بك. إذا لم تكن هناك مؤخرًا، ستظهر كـ MIRROR-غير نشط.GET /api/validators/{nodeID}/score-breakdown لاسترجاع التفصيل المستمر — قيمة كل بعد، نسخة الخوارزمية التي أنتجتها، وسجل الدرجات الأخير — كـ JSON. لوحة تفصيل الدرجات في الواجهة تقرأ من نفس المصدر.// Step 1 — Raw composite (sum of dimensions, minus the two penalties)
positive = uptime + netYield + fee + operatorQuality
+ mirror + capacity + trust + delivery + timeRemaining
// Penalties (see the two penalty cards above):
// v4.3 active-outage streak — 0-1 missed epochs → 0, 2 → 3, 3 → 6, 4+ → 10
// v4.5 extreme fee (>50%) — positive × min(1, (fee - 50) / 50) × 0.75
raw = clamp(positive - streakPenalty - extremeFeePenalty, 0, 100)
// Step 2 — Smooth across recent cron snapshots (v3.5)
// Weights: current 0.5, prev1 0.3, prev2 0.15, prev3 0.05
smoothed = 0.5*raw + 0.3*prev1 + 0.15*prev2 + 0.05*prev3
// Step 3 — Apply sudden-change penalty if flagged this run
// Triggers: fee +50% or +5pt jump, self-bond -20% drop, uptime -5% crash
// Magnitude: -10 pts on detection, decays -7, -4, -1 over 3 runs
suddenPenalty = -10 if any flag triggered else (decaying remainder)
// Step 4 — Final score
score = clamp(smoothed + suddenPenalty, 0, 100)services/validators/scoring.ts في قاعدة كود FlareWatch. يمكن للمشغلين أو الباحثين الذين يريدون فحص التنفيذ مباشرة (بدلاً من قراءة النثر + الصيغ أعلاه) — أو الذين يريدون عمل نسخة منه لاستخدامهم الخاص — إرسال بريد إلى [email protected] لطلب الوصول. سننشر الملف كحزمة مفتوحة المصدر مستقلة إذا كان هناك طلب حقيقي./api/cron/refresh-validators درجة كل مدقق نشط كل 5 دقائق. يتم جلب المدخلات (قراءات P-Chain RPC، Flaremetrics، FSE، reward-scripts) بشكل جديد في كل مرة تشغيل.Flare لا تقطع حصة المدقق. آلية العقوبة بأكملها لسوء السلوك من المدقق هي مصادرة المكافأة بالإضافة إلى نظام تمريرات FIP-10. لا يوجد قطع توقيع مزدوج، لا قطع تعادل، لا حدث تدمير حصة نحتاج إلى تتبعه. المدققون الذين يفشلون في شروط الحد الأدنى لـ FIP-10 يفقدون مكافآت تلك الحقبة (مصادرة كاملة إذا كانت عند صفر تمريرات، وإلا يفقدون تمريرة واحدة لكل بروتوكول فشلوا فيه)؛ رأس مالهم المرهون لم يتغير.
هذا يعني أن الدرجة ليس لديها بُعد "سجل القطع" — لا يوجد مثل هذا السجل لتتبعه. ما نتتبعه بالفعل هو نتيجة كل فشل في الحد الأدنى: كسب المدقق صفر في تلك الحقبة، وهو ما يُلتقط في epochsIncluded / epochsObserved. قام تحديث v4.2 في 2026-05-14 بتوسيع مُضاعِف موثوقية الدرجة لاستخدام تلك النسبة عبر مجموعة الحد الأدنى الكاملة لـ FIP-10 (وقت التشغيل، توقيع FSP، معدل تقديم FTSO، مشاركة FDC) لذا فإن فشل المدقق في أي حد أدنى يعاقبه بشكل متناسب في بُعد وقت التشغيل بغض النظر عن المحور الذي فشل فيه.
حدود الحد الأدنى لـ FIP-10، المستمدة من dev.flare.network/network/fsp/rewarding: يتطلب الرهن 80٪ وقت تشغيل + 1M FLR ربط ذاتي نشط؛ تتطلب بيانات FTSO anchor أن تكون التقديرات ضمن 0.5٪ من متوسط الإجماع في 80٪ من الجولات؛ تتطلب بيانات زمن الانتقال لـ FTSO تقديم 80٪ من التحديثات المتوقعة؛ يتطلب FDC المشاركة في 60٪ من جولات التصويت. المدققون الذين يستوفون الحد الأدنى لوقت التشغيل 80٪ + 1M ربط ذاتي ولكن أقل من عتبات الكسب 3M / 15M لا يزالون يتلقون مكافآت ولكن لا يمكنهم تجميع التمريرات — المنطقة الرمادية التي تظهر عبر تصنيف passEligibility: "at-risk" في هذه البطاقة.