FlareWatch는 각 P-Chain 검증자에게 9개 차원에 걸쳐 0–100의 복합 점수를 할당합니다. 계산은 결정론적이고, 입력값은 공개 체인 데이터 [Flare Explorer] [FSE] [Flaremetrics]이며, 동일한 알고리즘이 FlareWatch의 자체 검증자 노드를 포함한 네트워크의 모든 검증자에게 적용됩니다(특별한 처우 없이 정확히 이 함수로 평가됨). 이 페이지는 모든 차원과 임계값을 문서화하여 운영자와 스테이킹 참여자가 점수 계산 방식과 각 값이 선택된 이유를 정확히 알 수 있도록 합니다. 여기의 모든 주장은 기본 온체인 또는 상위 소스로 다시 연결됩니다. 하단의 출처 및 참고자료를 참조하세요.
스테이킹 모드에서 표시되는 항목입니다(VRM + MIRROR 보상을 위해 FLR을 P-Chain 검증자에게 위임). 위임 모드에서 표시되는 FTSO 제공자 점수(WFLR을 FTSO 데이터 제공자에게 위임)는 데이터 제공자 성능(정확도, V2 프로토콜 참여 등)에 중점을 두는 별도의 13차원 알고리즘을 사용합니다. 이들은 서로 다른 온체인 역할이며 별도로 평가됩니다. 위임 측에 대해서는 FTSO 제공자 점수 방법론을 참조하세요.스테이킹 테이블의 APY는 위임자가 받는 all-in rate입니다 — 하나의 수치로, 복잡한 계산이 필요 없습니다. 이는 Flare의 보상 스크립트에서 측정되며(공식이 아닌 실제 지급액), 검증자 수수료를 차감한 금액이고, 각 에포크마다 실제 보상과 함께 변동합니다. FlareWatch 전체에서 APY는 수수료 이후를 의미하며 APY는 수수료 이전을 의미합니다.
Flare Systems Explorer와 비교하십니까? FSE 및 기타 탐색기는 위임 비율만 표시합니다 — MIRROR를 추가하지 않으므로 MIRROR 활성 검증자의 총 APY가 더 높게 표시됩니다(차이는 위의 MIRROR 라인과 정확히 일치합니다). 두 수치 모두 동일한 보상 스크립트 데이터의 약 8에포크 후행 평균이므로, 검증자의 중간 창 수수료 변경은 창을 통해 노화될 때까지 두 사이트의 현재 수수료 스냅샷에 지연됩니다.
APY 툴팁에 나타나는 두 개의 다른 수치는 위임자의 비율이 아닙니다: 이론적 기준선(네트워크 총 APY × (1 − 수수료), 스테이킹만 해당 — 충분한 측정 이력이 존재하기 전의 폴백으로 사용) 및 운영자의 자체 본드 수익률(검증자의 자신의 스테이크 반환, 수수료 포착으로 증대됨 — 운영자 메트릭이며 당신이 얻는 것이 아닙니다).
점수 지정의 경우: 순 수익률 차원은 VRM 위임 비율만 점수를 지정하고 MIRROR는 자신의 차원에서 점수를 지정합니다 — MIRROR가 표시된 총 APY에 포함되어 있더라도 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-inactive로 표시됩니다.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의 크론은 모든 활성 검증자의 점수를 매 5분마다 다시 계산합니다. 입력값(P-Chain RPC 읽기, Flaremetrics, FSE, 보상 스크립트)은 매 실행마다 새로 가져옵니다.Flare는 검증자 스테이크를 삭감하지 않습니다. 검증자 부정행위에 대한 전체 페널티 메커니즘은 보상 몰수와 FIP-10 패스 시스템입니다. 더블 서명 삭감, 동의어 삭감, 추적해야 할 스테이크 소실 이벤트가 없습니다. FIP-10 최소 조건을 충족하지 못한 검증자는 해당 에포크의 보상을 잃습니다(패스가 0이면 전부 몰수, 아니면 실패한 프로토콜당 패스 1개 손실). 스테이크된 원금은 변하지 않습니다.
즉, 점수에는 '삭감 이력' 차원이 없습니다. 추적할 그러한 이력이 없기 때문입니다. 우리가 추적하는 것은 모든 최소 실패의 결과입니다. 즉, 검증자가 그 에포크에서 0을 벌었으며, 이는 epochsIncluded / epochsObserved에 기록됩니다. 2026-05-14의 v4.2 업데이트는 점수의 신뢰성 배수를 전체 FIP-10 최소 집합(가동시간, FSP 서명, FTSO 제출 비율, FDC 참여)에 걸친 비율을 사용하도록 확대했으므로 어느 축이 실패했든 상관없이 최소값을 실패한 검증자는 가동시간 차원에서 비례적으로 페널티를 받습니다.
FIP-10 최소 임계값(출처: dev.flare.network/network/fsp/rewarding): 스테이킹은 80% 가동시간 + 100만 FLR 활성 자체 본딩 필요. FTSO 앵커 피드는 추정값이 80%의 라운드에서 합의 중앙값의 0.5% 이내여야 함. FTSO 블록 지연 피드는 예상 업데이트의 80% 제출 필요. FDC는 투표 라운드의 60% 참여 필요. 80% 가동시간 + 100만 자체 본딩 기준을 충족하지만 300만 / 1,500만 수익 임계값 미만인 검증자는 여전히 보상을 받지만 패스를 축적할 수 없습니다. 회색 영역은 이 카드의 passEligibility: "at-risk" 분류를 통해 표시됩니다.