FlareWatchは各P-Chainバリデーターに9つのディメンション全体で0~100の複合スコアを割り当てます。数式は確定的で、入力はパブリックチェーンデータ[Flare Explorer] [FSE] [Flaremetrics]であり、ネットワーク上のすべてのバリデーター(FlareWatch自身のバリデーターノードを含む)に同じアルゴリズムが適用されます。このページは、オペレーターとステーカーがスコアの計算方法と各値が選ばれた理由を正確に確認できるよう、すべてのディメンションとしきい値を文書化しています。ここで行われているすべての主張は、一次的なオンチェーンまたはアップストリームソースにリンク戻されています。下部のソースと参考文献を参照してください。
ステーキングモードに表示される内容(FLRをP-Chainバリデーターにデリゲートしており、VRM + MIRRORリワードを受け取る場合)です。デリゲーションモードに表示されるFTSOプロバイダースコア(WFLRをFTSOデータプロバイダーにデリゲート)は、データプロバイダーのパフォーマンス、V2プロトコル参加などに焦点を当てた独立した13ディメンションアルゴリズムを使用します。これらはディメンション上で区別されるオンチェーンロールであり、個別にスコア化されます。デリゲーション側については、FTSOプロバイダースコア方法論を参照してください。ステーキング・テーブルのAPYは、デリゲーターが受け取るオールイン・レート — 1つの数値、暗算不要。Flare の報酬スクリプトから測定(公式ではなく実際のペイアウト)、バリデーターの手数料控除後で、エポックごとに実際の報酬で変動。FlareWatch 全体で、APY は手数料後、APY は手数料前を意味します。
Flare Systems Explorer と比較? FSE および他のエクスプローラーはデリゲーション・レートのみを表示します — MIRROR は追加されません — したがって Total APY は MIRROR 対応バリデーターで高く読み取られます(差はちょうど上記の MIRROR 行です)。両図は同じ報酬スクリプト・データからの約8エポック遅行平均であるため、バリデーターの中盤の窓での手数料変更はウィンドウを通じてエージングされるまで、どちらのサイトでも現在の手数料スナップショットに遅れます。
APY ツールチップに表示される他の2つの図は、デリゲーターのレートではありません。理論的ベースライン(ネットワーク総APY × (1 − 手数料)、ステーキングのみ — 十分な測定履歴が存在する前の代替として使用)、およびオペレーターのセルフボンド利回り(バリデーターの自身のステーク・リターン、手数料キャプチャで増幅 — オペレーター・メトリック、あなたが得るものではありません)。
スコア作成のため。Net YieldディメンションはVRMデリゲーション・レートのみをスコア、MIRROR は独自ディメンションでスコア — したがって MIRROR は、表示される Total APY に含まれていても、決して二重計算されません。
| 90+ | トップティア - オペレーターの上位約10~20%。典型的なプロフィール: フルスタックバリデーター + FTSO + FDC、低いフィー、MIRROR-アクティブ、一貫したFIP-10信頼性、健全なデリゲーターベース、有意義なセルフボンド。単一のディメンションは必須ではありません。オペレーターはほとんどのカテゴリー全体で強みを積み重ねることでトップティアに到達します。 |
| 80–89 | 強力 - ほとんどの主要なベンチマークを満たします。トップティアまでの1~2ディメンション不足です。 |
| 70–79 | 優良 - すべてのベースライン基準を満たします。大きなギャップなし。 |
| 60–69 | 許容可能 - 使用可能だが、差別化されていない。 |
| <60 | 中央値以下 - 1つ以上のディメンションに大きなギャップ。数学的事実であり、品質判断ではありません。 |
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。最後の8つのエポックのうち、あなたのnodeIDがuptimeEligible: trueだったエポックの数をカウントしてください。その比率があなたのアップタイム次元乗数を駆動します。RewardClaimedイベント(claimType=3付き)であなたのnodeIDを参照するものを探してください。最近のものがない場合、MIRROR非アクティブとして表示されます。GET /api/validators/{nodeID}/score-breakdownにアクセスしてパーシスト分解を取得してください——すべての次元の値、それを生成したアルゴリズムバージョン、最近のスコア履歴——JSON形式で。UIのスコア分解パネルは同じソースから読み込みます。// 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 に実装されています。実装を直接検査したい(上記の説明と数式を読む代わりに)、または独自の用途のためにフォークしたい運用者や研究者は、[email protected] にメールしてアクセスをリクエストしてください。本当に需要があれば、このファイルをスタンドアロンのオープンソースパッケージとして公開します。/api/cron/refresh-validators の cron は 5 分ごとに全アクティブバリデーターのスコアを再計算します。入力(P-Chain RPC リード、Flaremetrics、FSE、報酬スクリプト)はすべて実行のたびに最新で取得されます。Flare はバリデーターステーキングをスラッシュしません。バリデーターの不正行為に対するペナルティメカニズム全体は報酬の没収と FIP-10 パス制です。ダブルサイニングスラッシュ、二重検証スラッシュ、追跡が必要なステーク破壊イベントはありません。FIP-10 最小条件を満たさないバリデーターはそのエポックの報酬を失い(パスがゼロの場合は完全没収、それ以外は失敗したプロトコルごとに 1 パス失う)、ステーク元本は保たれます。
つまり、スコアに「スラッシング履歴」次元はありません。追跡する履歴は存在しません。追跡するのは最小失敗の結果です。バリデーターはそのエポックでゼロを獲得し、これは epochsIncluded / epochsObserved に記録されます。2026-05-14 の v4.2 更新では、スコアの信頼性乗数を FIP-10 最小値セット全体(アップタイム、FSP 署名、FTSO 提出率、FDC 参加)にわたるその比率を使用するよう拡張したため、最小値を失敗するバリデーターはどの軸で失敗したかに関係なくアップタイム次元で比例的にペナルティを受けます。
FIP-10 最小閾値(出典:dev.flare.network/network/fsp/rewarding):ステーキングは 80% のアップタイム + 1M FLR のアクティブセルフボンドが必要。FTSO アンカーフィード(推定値はコンセンサス中央値の 0.5% 以内で 80% のラウンドが必要)。FTSO ブロック遅延フィード(期待される更新の 80% を提出)。FDC(投票ラウンドの 60% に参加)。80% アップタイム + 1M セルフボンドフロアを満たしているが 3M / 15M 獲得閾値以下のバリデーターはまだ報酬を受け取りますがパスを累積できません。このカードの passEligibility: "at-risk" 分類を通じて表示されるグレーゾーン。