FlareWatch memberikan setiap validator P-Chain skor komposit 0–100 di seluruh 9 dimensi. Matematinya deterministik, inputnya adalah data chain publik [Flare Explorer] [FSE] [Flaremetrics], dan algoritma yang sama berlaku untuk setiap validator di jaringan — termasuk node validator FlareWatch sendiri, yang diskor dengan fungsi yang tepat tanpa perlakuan khusus. Halaman ini mendokumentasikan setiap dimensi dan ambang batas sehingga operator dan staker dapat melihat dengan tepat bagaimana skor dihitung dan mengapa setiap nilai dipilih. Setiap klaim di sini tertaut kembali ke sumber on-chain atau upstream primernya — lihat Sumber & referensi di bagian bawah.
staking mode di halaman validator (mendelegasikan FLR ke validator P-Chain untuk reward VRM + MIRROR). Skor penyedia FTSO yang ditampilkan dalam delegation mode (mendelegasikan WFLR ke penyedia data FTSO) menggunakan algoritma terpisah 13-dimensi yang berfokus pada kinerja penyedia data — akurasi, partisipasi protokol V2, dll. Ini adalah peran on-chain yang berbeda dengan reward yang berbeda, diskor secara terpisah. Lihat Metodologi Skor Penyedia FTSO untuk sisi delegasi.APY di tabel staking adalah all-in rate yang diterima delegator — satu angka, tidak ada mental math. Ini diukur dari reward-scripts Flare (actual payouts, bukan formula), setelah dikurangi biaya validator, dan bergerak setiap epoch dengan reward nyata. Di mana pun di FlareWatch, APY berarti setelah biaya dan APY berarti sebelumnya.
Membandingkan dengan Flare Systems Explorer? FSE dan explorer lain menampilkan delegation rate only — mereka tidak menambahkan MIRROR — jadi Total APY kami membaca lebih tinggi di validator MIRROR-active mana pun (gapnya exactly MIRROR line di atas). Kedua figure adalah ~8-epoch trailing averages dari data reward-scripts yang sama, jadi perubahan fee mid-window validator lags current-fee snapshot di situs mana pun hingga usianya melalui window.
Dua figure lain muncul di APY tooltip dan bukan rate delegator: theoretical baseline (network gross APY × (1 − fee), staking only — digunakan sebagai fallback sebelum measured history cukup ada), dan self-bond yield operator (own stake return validator, diamplifikasi oleh fee capture — operator metric, bukan apa yang Anda hasilkan).
Untuk scoring: dimensi Net Yield scores VRM delegation rate only, dan MIRROR scores di dimensi tersendiri — jadi MIRROR tidak pernah double-counted, meskipun termasuk dalam displayed Total APY.
| 90+ | Top tier — top ~10–20% operator. Profil tipikal: validator full-stack + FTSO + FDC, biaya low-end, MIRROR-active, keandalan FIP-10 konsisten, basis delegator sehat, self-bond bermakna. Tidak ada dimensi tunggal yang diperlukan — operator mencapai Top tier dengan menumpuk kekuatan di sebagian besar kategori. |
| 80–89 | Strong — memenuhi sebagian besar benchmark kunci; satu atau dua dimensi kurang dari top tier. |
| 70–79 | Good — memenuhi semua kriteria baseline; tidak ada celah besar. |
| 60–69 | Acceptable — dapat digunakan tetapi tidak terdiferensiasi. |
| <60 | Below median — celah signifikan dalam satu atau lebih dimensi. Fakta matematis, bukan penilaian kualitas. |
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, dan FTSO score Anda (jika Anda juga data provider).generated-files/reward-epoch-N/nodes-data.json. Hitung berapa banyak epoch nodeID Anda memiliki uptimeEligible: true. Rasio itu drive Uptime dimension multiplier Anda.RewardClaimed events dengan claimType=3 referencing nodeID Anda. Jika tidak ada recent, Anda akan show sebagai MIRROR-inactive.GET /api/validators/{nodeID}/score-breakdown untuk retrieve persisted breakdown — setiap dimension's value, algorithm version yang produce, dan recent score history — sebagai JSON. Panel score-breakdown di UI reads dari source yang sama.// 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 dalam basis kode FlareWatch. Operator atau peneliti yang ingin memeriksa implementasi secara langsung (bukan membaca prosa + formula di atas) — atau yang ingin memforking untuk penggunaan mereka sendiri — dapat mengirim email ke [email protected] untuk meminta akses. Kami akan menerbitkan file sebagai paket open-source standalone jika ada permintaan nyata./api/cron/refresh-validators menghitung ulang skor setiap validator aktif setiap 5 menit. Input (pembacaan P-Chain RPC, Flaremetrics, FSE, reward-scripts) diambil segar di setiap penjalankan.Flare tidak melakukan slash pada stake validator. Seluruh mekanisme penalti untuk perilaku validator yang salah adalah forfeiture reward ditambah sistem passes FIP-10. Tidak ada double-signing slash, tidak ada equivocation slash, tidak ada event perusakan stake yang perlu kami lacak. Validator yang gagal kondisi minimum FIP-10 kehilangan reward epoch itu (forfeit penuh jika di nol passes, jika tidak kehilangan satu pass per protokol yang mereka gagalkan); principal stake mereka tetap utuh.
Itu berarti skor tidak memiliki dimensi "slashing history" — tidak ada riwayat seperti itu yang perlu dilacak. Yang KAMI lacak adalah konsekuensi dari setiap kegagalan minimum: validator menghasilkan nol di epoch itu, yang ditangkap dalam epochsIncluded / epochsObserved. Update v4.2 pada 2026-05-14 memperluas multiplier keandalan skor untuk menggunakan rasio itu di seluruh set minimum FIP-10 (uptime, FSP signing, tingkat submisi FTSO, partisipasi FDC) sehingga validator yang gagal minimum apa pun secara proporsional dihukum di dimensi Uptime terlepas dari sumbu mana yang gagal.
Ambang batas minimum FIP-10, bersumber dari dev.flare.network/network/fsp/rewarding: staking memerlukan uptime 80% + self-bond aktif 1M FLR; feed anchor FTSO memerlukan estimasi dalam 0,5% dari median konsensus di 80% putaran; feed block-latency FTSO memerlukan pengiriman 80% pembaruan yang diharapkan; FDC memerlukan partisipasi dalam 60% putaran voting. Validator yang memenuhi lantai uptime 80% + self-bond 1M tetapi di bawah ambang batas earning 3M / 15M masih menerima reward tetapi tidak dapat mengakumulasi passes — zona abu-abu yang ditampilkan melalui kartu passEligibility: "at-risk" ini.