FlareWatchは各FTSOデータプロバイダーに対して12の評価対象ディメンションの0~100の合成スコアを割り当てます。数学は決定論的で、入力はFlareエコシステムのオンチェーンおよび公開データです。[Flaremetrics] [FSE] [Flare Explorer]、同じアルゴリズムはすべてのプロバイダー(FlareWatch 独自の FTSO プロバイダーを含む)に適用され、特別な扱いはありません。このページはすべての次元と閾値をドキュメント化し、委任者と運用者はスコアの計算方法と各値の選択理由を正確に確認できます。ここのすべてのクレームは、その主要なアップストリームソースにリンク返します。ソースと参照 下部にあります。
委任モードで表示されるスコア(WFLRをFTSOデータプロバイダーに委任してFTSOインフレーション共有を受け取る場合)です。ステーキングモードで表示されるバリデータスコア(FLRをP-Chainバリデータに委任してVRM + MIRRORリワードを受け取る場合)は、バリデータ運用に焦点を当てた別の9次元アルゴリズムを使用します。稼働率、手数料、信頼性など異なるオンチェーン役割で、異なるリワード構造を持ち、個別にスコアリングされます。ステーキング側についてはバリデータスコアメソドロジーを参照してください。| 90+ | トップティア — FTSOプロバイダーのトップ約10~20%。典型的プロファイル:平均以上のリワードレート、高い精度、V2プロトコル完全対応(FTSO Scaling + Fast Updates + FDC)、手数料ゼロ/低い、大規模デリゲータベース、MIRRORペイヤーバリデータノード、認知ブランド。単一の次元は必須ではありません。プロバイダーはほとんどのカテゴリにおいて強みを積み重ねることでトップティアに到達します。 |
| 80~89 | 強力 — ほとんどの主要ベンチマークを満たします。1~2次元でトップティアに届きません。 |
| 70~79 | 良好 — すべてのベースライン基準を満たします。大きなギャップはありません。 |
| 60~69 | 許容範囲 — 利用可能ですが、差別化されていません。 |
| <60 | 中央値未満 — 1つ以上の次元で大きなギャップがあります。数学的事実であり、品質判定ではありません。 |
if (rate <= 0 || medianRate <= 0): score = 0 else: ratio = rate / medianRate score = min(25, round(ratio * 12.5 * 10) / 10) // 1 decimal place // Anomaly detection: providers > 3× the median are capped at // median × 3 for scoring purposes (prevents data outliers from // distorting the linear curve).
if (fseAccuracySecondary > 0): pct = fseAccuracySecondary / 100 if (pct >= 97) score = 25 elif (pct >= 95) score = 18 + (pct - 95) * 3.5 // 95 → 18, 97 → 25 elif (pct >= 93) score = 16 + (pct - 93) * 1 // 93 → 16, 95 → 18 elif (pct >= 90) score = 13 + (pct - 90) * 1 // 90 → 13, 93 → 16 elif (pct >= 85) score = 10 + (pct - 85) * 0.6 // 85 → 10, 90 → 13 elif (pct >= 80) score = 6 + (pct - 80) * 0.8 // 80 → 6, 85 → 10 else score = max(0, 2 + (pct - 70) * 0.4) elif (fseAccuracyPrimary > 0): // Primary fallback: similar piecewise linear curve. else: score = WEIGHT_ACCURACY / 2 // Neutral — no FSE data
earned = last 12 epochs where rewardRate > 0, keyed by epochId pairs = [earned[i-1], earned[i]] where epochId[i] - epochId[i-1] == 1 if (pairs.length < 3) return 10 // Neutral — too few consecutive pairs // DOWNSIDE volatility only: rises never hurt, so a stable or RISING // rate scores near full and a recovery lifts the score. Only drops // between CONSECUTIVE epochs count, in proportion to depth (RMS), // weighted toward recent pairs so an active recovery pulls the score up. drops[i] = max(0, (prev - cur) / prev) // rise -> 0 w[i] = 0.8 ^ (age of pair) // newest pair = highest cv = sqrt( sum(w[i] * drops[i]^2) / sum(w[i]) ) score = max(0, round((1 - min(1, cv * 6)) * 20 * 10) / 10)
if (!isActive) score = 0 // see "Active" below
else:
score = 3 // active baseline
if (hasSubmitAddress AND hasSigningPolicyAddress AND voterRegistered):
score += 4 // V1 registered
if (fseFtsoScaling) score += 8/3 // ~2.67 each
if (fseFastUpdates) score += 8/3
if (fseFdc) score += 8/3
score = min(15, round(score * 10) / 10)anchor = max(lowest active fee observed, protocol fee floor) // FIP-16 sets a 20% minimum entity fee. All 98 providers charge // exactly 20%, so the anchor is 20% and nobody is docked for // charging the only fee the protocol permits. Same curve and // same anchor the validator page's Fee dimension uses. if (!isActive) score = 0 d = fee - anchor // distance ABOVE the best real offer if (d <= 0) score = 15 // at or below the anchor → full marks elif (d <= 5) score = 15 - d * 0.43 elif (d <= 10) score = 12.9 - (d - 5) * 0.64 elif (d <= 15) score = 9.6 - (d - 10) * 0.86 elif (d <= 20) score = 5.4 - (d - 15) * 1.07 else: score = 0 // extractive
if (no fseNodeIDs) score = 0 if (mirrorStatsMap empty) score = 12 / 2 = 6 // Neutral seed before data lands activeCount = nodes_with_status_active fraction = activeCount / fseNodeIDs.length base = 12 * fraction // Overperformance bonus per node, applied only when ALL gates pass: // - >= 30 days observed since first reading (firstObservedAtMs) // - >= 3 paid stake observations // - finite medianOverpaymentRatio // Bayesian shrinkage with prior k=5 toward 1.0 (neutral): // shrunken = (observedRatio * N + 1.0 * 5) / (N + 5) // Bucketed bonus from shrunken: // < 1.05 → 0 < 1.15 → 1 < 1.30 → 2 >= 1.30 → 3 avgBonus = sum_per_node(bonus) / fseNodeIDs.length score = round((base + avgBonus) * 10) / 10
if (count <= 5) score = 0 elif (count >= 500) score = 12 else: ratio = log(count / 5) / log(100) // maps [5, 500] → [0, 1] score = round(min(12, max(0, ratio * 12)) * 10) / 10
if (fseActive) score = 10 elif (rewardRate > 0) score = 7 else score = 0
change = abs(votePowerDailyChangePct * 100) if (change < 1) score = 10 elif (change < 3) score = 10 - (change - 1) * 1.5 // 1 → 10, 3 → 7 elif (change < 5) score = 7 - (change - 3) * 1.5 // 3 → 7, 5 → 4 elif (change < 10) score = 4 - (change - 5) * 0.4 // 5 → 4, 10 → 2 else score = max(0, 2 - (change - 10) * 0.1)
if (no fspData OR totalEpochs <= 0) score = 5 // active window = epochs from the provider's first paid epoch to now missed = (active-window epochs) - (epochs the provider was paid) score = max(0, 10 - missed * 3)
if (no name) score = 0 elif (name starts with 0x or matches hex regex) score = 0 elif (name.length < 4) score = 4 else score = 8
ownBond = operator's own P-Chain node bond (FLR) total = ownBond + delegated WFLR vote power alignment = piecewise-linear ratio curve (0% → 0 … ≥10% → 7) absolute = min(7, ownBond / 5,000,000 * 7) // saturates at 5M FLR score = max(alignment, absolute)
fspRewardRate、delegationFeePercentage、wNatWeight、votePowerDailyChangePctをメモします。providersuccessrate.secondaryをチェック、V2ステータスに関してはentityminimalconditionslatest.ftso_scaling / ftso_fast_updates / fdcフラグをチェックします。claimType=3でRewardClaimedイベントを見つけ、nodeIDを参照します。最近いずれかのノード向けのなくない場合は、スコアでMIRROR非アクティブとして表示されます。// Step 1 — Raw composite (sum of 12 dimensions, max 172)
raw = rewardRate + accuracy + consistency + v2 + fee + mirror
+ delegators + participation + stability + compliance
+ identity + selfBond
// An UNMEASURED reward rate is not a FAILED one. When a provider is
// demonstrably distributing but we hold no rate figure for it, the
// Reward Rate weight leaves the DENOMINATOR rather than scoring 0
// against it — we score what we measured, over what we could measure.
maxRaw = (rewardRate figure missing AND isActive) ? 172 - 25 : 172
normalized = round((raw / maxRaw) * 100)
// (The separate vote-power dilution penalty was REMOVED in v4.9. It
// double-counted: an over-cap provider already earns a below-median
// realized reward rate, so the median-anchored Reward Rate dimension
// docks it for dilution once. Cap proximity is now a neutral DISPLAY
// signal on every provider, not a second deduction in the score.)
// Step 2 — Dynamic weight redistribution
// Across the active provider set, dimensions where everyone clusters
// (stddev < 1.0) become non-discriminating. Their weight gets
// redistributed evenly across dimensions where the spread is wider
// (stddev >= 1.0). The redistribution recomputes the score:
//
// for each dim d:
// multiplier[d] = 1.0 if stddev[d] < 1.0
// = (weight[d] + bonus) / weight[d] otherwise
// bonus = sum(weights of low-stddev dims) / count(high-stddev dims)
//
// adjusted_raw = sum(breakdown[d] * multiplier[d])
// adjusted_max = sum(weight[d] * multiplier[d])
// final = round((adjusted_raw / adjusted_max) * 100)
// Step 3 — Final score (capped at 100)
score = min(100, final)services/ftso/scoring.ts に実装されています。実装を直接検査したい(上記の説明と公式だけを読む代わりに)か、独自の用途にフォークしたい場合は、[email protected] にメールを送信してアクセスをリクエストしてください。本当の需要があれば、ファイルをスタンドアロンのオープンソースパッケージとして公開します。/api/cron/refresh-validators の cron 内のパスとして実行され、アクティブなすべてのプロバイダーのスコアを 5 分ごと に再計算します(P-Chain バリデーターの再スコア付けと同じ実行)。入力(Flaremetrics、FSE、FSP 報酬、V2 RewardManager イベント)は毎回の実行時に新しく取得されます。