From e5293b4b3d94be5aa2b7a1089acd81d0bac67393 Mon Sep 17 00:00:00 2001 From: thomaspanf Date: Sun, 15 Feb 2026 18:12:21 -0800 Subject: [PATCH 1/3] Skip megapools with no active validators when calculating ETH Rewards --- shared/services/rewards/generator-impl-v11.go | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/shared/services/rewards/generator-impl-v11.go b/shared/services/rewards/generator-impl-v11.go index a8928fbb2..67cd51a86 100644 --- a/shared/services/rewards/generator-impl-v11.go +++ b/shared/services/rewards/generator-impl-v11.go @@ -580,8 +580,12 @@ func (r *treeGeneratorImpl_v11) calculateEthRewards(checkBeaconPerformance bool) // Repeat, for megapools if nodeInfo.Megapool != nil { megapool := nodeInfo.Megapool + details := r.networkState.MegapoolDetails[megapool.Address] + // Skip megapools with no active validators (all exited/dissolved) + if details.ActiveValidatorCount == 0 { + continue + } for _, validator := range megapool.Validators { - details := r.networkState.MegapoolDetails[megapool.Address] bond := details.GetMegapoolBondNormalized() nodeFee := r.networkState.NetworkDetails.MegapoolRevenueSplitTimeWeightedAverages.NodeShare voterFee := r.networkState.NetworkDetails.MegapoolRevenueSplitTimeWeightedAverages.VoterShare From d57ba32bbcb42b60f13bf9a2f1d8759d2745b8db Mon Sep 17 00:00:00 2001 From: thomaspanf Date: Sun, 15 Feb 2026 18:13:10 -0800 Subject: [PATCH 2/3] Guard against zero division when getting the megapool bond --- bindings/utils/state/megapool.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/bindings/utils/state/megapool.go b/bindings/utils/state/megapool.go index 8787570d7..3154aeb5b 100644 --- a/bindings/utils/state/megapool.go +++ b/bindings/utils/state/megapool.go @@ -44,6 +44,9 @@ type NativeMegapoolDetails struct { // Get the normalized bond per 32 eth validator // This is used in treegen to calculate attestation scores func (m *NativeMegapoolDetails) GetMegapoolBondNormalized() *big.Int { + if m.ActiveValidatorCount == 0 { + return big.NewInt(0) + } return big.NewInt(0).Div(m.NodeBond, big.NewInt(int64(m.ActiveValidatorCount))) } From 561f07fa27c9332dc227065ccb342e37b8e9f5ab Mon Sep 17 00:00:00 2001 From: thomaspanf Date: Sun, 15 Feb 2026 18:19:52 -0800 Subject: [PATCH 3/3] Scope network values and megapool bond per megapool instead of per validator --- shared/services/rewards/generator-impl-v11.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/shared/services/rewards/generator-impl-v11.go b/shared/services/rewards/generator-impl-v11.go index 67cd51a86..79ef8468b 100644 --- a/shared/services/rewards/generator-impl-v11.go +++ b/shared/services/rewards/generator-impl-v11.go @@ -585,11 +585,11 @@ func (r *treeGeneratorImpl_v11) calculateEthRewards(checkBeaconPerformance bool) if details.ActiveValidatorCount == 0 { continue } + nodeFee := r.networkState.NetworkDetails.MegapoolRevenueSplitTimeWeightedAverages.NodeShare + voterFee := r.networkState.NetworkDetails.MegapoolRevenueSplitTimeWeightedAverages.VoterShare + pdaoFee := r.networkState.NetworkDetails.MegapoolRevenueSplitTimeWeightedAverages.PdaoShare + bond := details.GetMegapoolBondNormalized() for _, validator := range megapool.Validators { - bond := details.GetMegapoolBondNormalized() - nodeFee := r.networkState.NetworkDetails.MegapoolRevenueSplitTimeWeightedAverages.NodeShare - voterFee := r.networkState.NetworkDetails.MegapoolRevenueSplitTimeWeightedAverages.VoterShare - pdaoFee := r.networkState.NetworkDetails.MegapoolRevenueSplitTimeWeightedAverages.PdaoShare // The megapool score is given by: // (bond + effectiveNodeFee*(32-bond)) / 32