FlareWatch asigna a cada validador de la P-Chain una puntuación compuesta de 0–100 en 9 dimensiones. Las matemáticas son deterministas, los datos de entrada son públicos en la cadena [Flare Explorer] [FSE] [Flaremetrics], y el mismo algoritmo se aplica a cada validador en la red — incluyendo el nodo validador de FlareWatch, que se califica mediante esta función exacta sin trato especial. Esta página documenta cada dimensión y umbral para que operadores y delegadores puedan ver exactamente cómo se calcula la puntuación y por qué se eligió cada valor. Cada afirmación aquí se vincula a su fuente principal en cadena o upstream — ver Fuentes y referencias al pie.
modo de staking en la página de validadores (delegando FLR a un validador de P-Chain para recompensas de VRM + MIRROR). La puntuación del proveedor FTSO que se muestra en modo de delegación (delegando WFLR a proveedores de datos FTSO) utiliza un algoritmo separado de 13 dimensiones enfocado en el desempeño del proveedor de datos — precisión, participación en el protocolo V2, etc. Son roles distintos en cadena con recompensas distintas, puntuados por separado. Ver Metodología de puntuación del proveedor FTSO para el lado de delegación.El APY en la tabla de staking es la tasa todo incluido que recibe un delegador — un número, sin cálculos mentales. Se mide desde los scripts de recompensas de Flare (pagos reales, no una fórmula), neto de la comisión del validador, y se mueve cada época con recompensas reales. En todo FlareWatch, APY significa después de la comisión y APY significa antes.
¿Comparando con Flare Systems Explorer? FSE y otros exploradores muestran solo la tasa de delegación — no suman MIRROR — así que nuestro APY Total se lee más alto en cualquier validador activo en MIRROR (la diferencia es exactamente la línea MIRROR arriba). Ambas cifras son promedios móviles de ~8 épocas de los mismos datos de scripts de recompensas, así que un cambio de comisión a mitad de ventana del validador se atrasa en una snapshot de comisión actual en cualquier sitio hasta que envejezca a través de la ventana.
Otras dos cifras aparecen en el tooltip de APY y no son la tasa del delegador: la línea de base teórica (APY bruto de red × (1 − comisión), solo staking — usada como fallback antes de que exista suficiente historial medido), y el rendimiento de auto-stake del operador (la rentabilidad del propio stake del validador, amplificada por captura de comisión — una métrica del operador, no lo que ganas).
Para scoring: la dimensión Net Yield puntúa solo la tasa de delegación VRM, y MIRROR se puntúa en su propia dimensión — así que MIRROR nunca se cuenta doble, aunque esté incluido en el APY Total mostrado.
| 90+ | Nivel superior — aproximadamente el 10–20% superior de operadores. Perfil típico: validador de stack completo + FTSO + FDC, comisión baja, activo en MIRROR, fiabilidad FIP-10 consistente, base de delegadores saludable, self-bond significativo. No se requiere una sola dimensión — los operadores alcanzan nivel superior apilando fortaleza en la mayoría de categorías. |
| 80–89 | Fuerte — cumple con la mayoría de puntos de referencia clave; una o dos dimensiones por debajo del nivel superior. |
| 70–79 | Bueno — cumple con todos los criterios de línea base; sin brechas importantes. |
| 60–69 | Aceptable — usable pero no diferenciado. |
| <60 | Por debajo de la mediana — brechas significativas en una o más dimensiones. Hecho matemático, no un juicio de calidad. |
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, y puntuación FTSO (si también eres proveedor de datos).generated-files/reward-epoch-N/nodes-data.json. Cuenta cuántas épocas tu nodeID tuvo uptimeEligible: true. Ese ratio impulsa tu multiplicador de dimensión Uptime.RewardClaimed con claimType=3 referenciando tu nodeID. Si no hay recientes, aparecerás como MIRROR-inactivo.GET /api/validators/{nodeID}/score-breakdown para recuperar el desglose persistido — valor de cada dimensión, la versión del algoritmo que lo produjo, e historial de puntuación reciente — como JSON. El panel de desglose de puntuación en la UI lee de la misma fuente.// 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 en la base de código de FlareWatch. Los operadores o investigadores que deseen inspeccionar la implementación directamente (en lugar de leer la prosa + fórmulas anteriores) — o que deseen bifurcarlo para su propio uso — pueden enviar un correo a [email protected] para solicitar acceso. Publicaremos el archivo como un paquete independiente de código abierto si hay demanda real./api/cron/refresh-validators recomputa la puntuación de cada validador activo cada 5 minutos. Las entradas (lecturas P-Chain RPC, Flaremetrics, FSE, scripts de recompensas) se obtienen nuevas en cada ejecución.Flare no reduce el stake del validador. El mecanismo de penalización completo para el mal comportamiento del validador es pérdida de recompensa más el sistema de pases FIP-10. No hay slash de doble firma, no hay slash de equívoco, no hay evento de destrucción de stake que necesitemos rastrear. Los validadores que fallan las condiciones mínimas de FIP-10 pierden las recompensas de esa época (pérdida total si tienen cero pases, de lo contrario pierden un pase por protocolo que fallaron); su principal apostado permanece intacto.
Esto significa que la puntuación no tiene dimensión de "historial de slashing" — no hay tal historial que rastrear. Lo que SÍ rastreamos es la consecuencia de cada fallo mínimo: el validador ganó cero en esa época, que se captura en epochsIncluded / epochsObserved. La actualización v4.2 del 2026-05-14 amplió el multiplicador de confiabilidad de la puntuación para usar esa proporción en todo el conjunto de mínimos FIP-10 (tiempo de actividad, firma FSP, tasa de envío FTSO, participación FDC), de modo que un validador que falla cualquier mínimo se penaliza proporcionalmente en la dimensión de Tiempo de Actividad independientemente de qué eje falló.
Umbrales mínimos de FIP-10, obtenidos de dev.flare.network/network/fsp/rewarding: staking requiere 80% de tiempo de actividad + 1M FLR de auto-bond activo; los feeds de anclaje FTSO requieren estimaciones dentro del 0.5% de la mediana de consenso en el 80% de las rondas; los feeds de latencia de bloques FTSO requieren enviar el 80% de las actualizaciones esperadas; FDC requiere participar en el 60% de las rondas de votación. Los validadores que cumplen el piso de 80% de tiempo de actividad + 1M auto-bond pero están por debajo de los umbrales de ganancia de 3M / 15M aún reciben recompensas pero no pueden acumular pases — la zona gris expuesta a través de la clasificación passEligibility: "at-risk" de esta tarjeta.