Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions bindings/utils/state/network.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ type NetworkDetails struct {
// Saturn
MegapoolRevenueSplitSettings MegapoolRevenueSplitSettings
MegapoolRevenueSplitTimeWeightedAverages MegapoolRevenueSplitTimeWeightedAverages
SmoothingPoolPendingVoterShare *big.Int `json:"smoothing_pool_earmarked_voter_share_eth"`
PendingVoterShareEth *big.Int `json:"pending_voter_share_eth"`
}

// Create a snapshot of all of the network's details
Expand Down Expand Up @@ -170,7 +170,7 @@ func NewNetworkDetails(rp *rocketpool.RocketPool, contracts *NetworkContracts, i
contracts.Multicaller.AddCall(contracts.RocketNetworkRevenues, &details.MegapoolRevenueSplitTimeWeightedAverages.NodeShare, "getCurrentNodeShare")
contracts.Multicaller.AddCall(contracts.RocketNetworkRevenues, &details.MegapoolRevenueSplitTimeWeightedAverages.VoterShare, "getCurrentVoterShare")
contracts.Multicaller.AddCall(contracts.RocketNetworkRevenues, &details.MegapoolRevenueSplitTimeWeightedAverages.PdaoShare, "getCurrentProtocolDAOShare")
contracts.Multicaller.AddCall(contracts.RocketRewardsPool, &details.SmoothingPoolPendingVoterShare, "getPendingVoterShare")
contracts.Multicaller.AddCall(contracts.RocketRewardsPool, &details.PendingVoterShareEth, "getPendingVoterShare")
}
_, err := contracts.Multicaller.FlexibleCall(true, opts)
if err != nil {
Expand Down
38 changes: 19 additions & 19 deletions shared/services/rewards/generator-impl-v11.go
Original file line number Diff line number Diff line change
Expand Up @@ -491,7 +491,7 @@ func (r *treeGeneratorImpl_v11) calculateEthRewards(checkBeaconPerformance bool)
// Get the Smoothing Pool contract's balance
r.smoothingPoolBalance = r.networkState.NetworkDetails.SmoothingPoolBalance
r.log.Printlnf("%s Smoothing Pool Balance:\t%s\t(%.3f)", r.logPrefix, r.smoothingPoolBalance.String(), eth.WeiToEth(r.smoothingPoolBalance))
r.log.Printlnf("%s Earmarked Voter Share:\t%s\t(%.3f)", r.logPrefix, r.networkState.NetworkDetails.SmoothingPoolPendingVoterShare.String(), eth.WeiToEth(r.networkState.NetworkDetails.SmoothingPoolPendingVoterShare))
r.log.Printlnf("%s Voter Share from Megapools not in the smoothing pool:\t%s\t(%.3f)", r.logPrefix, r.networkState.NetworkDetails.PendingVoterShareEth.String(), eth.WeiToEth(r.networkState.NetworkDetails.PendingVoterShareEth))

if r.rewardsFile.Index == 0 {
// This is the first interval, Smoothing Pool rewards are ignored on the first interval since it doesn't have a discrete start time
Expand Down Expand Up @@ -850,7 +850,8 @@ func (r *treeGeneratorImpl_v11) calculateNodeRewards() (*nodeRewards, error) {
var err error
bonusScalar := big.NewInt(0).Set(oneEth)

voterEth := big.NewInt(0)
voterEthFromSmoothingPool := big.NewInt(0)
totalVoterEth := big.NewInt(0)
pdaoEth := big.NewInt(0)

// If pdao score is greater than 0, calculate the pdao share
Expand All @@ -862,15 +863,15 @@ func (r *treeGeneratorImpl_v11) calculateNodeRewards() (*nodeRewards, error) {

// If voter score is greater than 0, calculate the voter share
if r.totalVoterScore.Cmp(common.Big0) > 0 {
voterEth.Mul(r.smoothingPoolBalance, r.totalVoterScore)
voterEth.Div(voterEth, big.NewInt(int64(r.successfulAttestations)))
voterEth.Div(voterEth, oneEth)
voterEthFromSmoothingPool.Mul(r.smoothingPoolBalance, r.totalVoterScore)
voterEthFromSmoothingPool.Div(voterEthFromSmoothingPool, big.NewInt(int64(r.successfulAttestations)))
voterEthFromSmoothingPool.Div(voterEthFromSmoothingPool, oneEth)

// Set the voter share eth in the rewards file
r.rewardsFile.TotalRewards.SmoothingPoolVoterShareEth.Set(voterEth)
r.rewardsFile.TotalRewards.SmoothingPoolVoterShareEth.Set(voterEthFromSmoothingPool)

// Add in the earmarked voter share
voterEth.Add(voterEth, r.networkState.NetworkDetails.SmoothingPoolPendingVoterShare)
// Add in the pending voter share (ETH distributed from Megapools)
totalVoterEth.Add(voterEthFromSmoothingPool, r.networkState.NetworkDetails.PendingVoterShareEth)
}

totalMegapoolVoteEligibleRpl := big.NewInt(0)
Expand All @@ -891,18 +892,18 @@ func (r *treeGeneratorImpl_v11) calculateNodeRewards() (*nodeRewards, error) {
continue
}

// The node's voter share is nodeRpl*voterEth/totalMegapoolVoteEligibleRpl
// The node's voter share is nodeRpl*totalVoterEth/totalMegapoolVoteEligibleRpl
nodeInfo.VoterShareEth.Set(nodeInfo.MegapoolVoteEligibleRpl)
nodeInfo.VoterShareEth.Mul(nodeInfo.VoterShareEth, voterEth)
nodeInfo.VoterShareEth.Mul(nodeInfo.VoterShareEth, totalVoterEth)
nodeInfo.VoterShareEth.Div(nodeInfo.VoterShareEth, totalMegapoolVoteEligibleRpl)
trueVoterEth.Add(trueVoterEth, nodeInfo.VoterShareEth)
}

// If there weren't any successful attestations, everything goes to the pool stakers
// If there weren't any successful attestations, everything goes to the pool stakers (rETH holders)
if r.totalAttestationScore.Cmp(common.Big0) == 0 || r.successfulAttestations == 0 {
r.log.Printlnf("WARNING: Total attestation score = %s, successful attestations = %d... sending the whole smoothing pool balance to the pool stakers.", r.totalAttestationScore.String(), r.successfulAttestations)
poolStakerEth := big.NewInt(0).Set(r.smoothingPoolBalance)
poolStakerEth.Sub(poolStakerEth, trueVoterEth)
poolStakerEth.Sub(poolStakerEth, voterEthFromSmoothingPool)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This uses a different calculation to the poolStakerETH calculation further down. Here it doesn't add pending voter share and then remove trueVoterETH. I don't think this is correct in the case where there is 0 megapoolVoteEligibleRpl.

Further down it would mean that voter share goes to rETH if there is no eligible RPL but here the voter share would not get distributed, I think.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a commit after Patches comment that changed trueVoterEth to voterEthFromSmoothingPool.

poolStakerEth.Sub(poolStakerEth, pdaoEth)
return &nodeRewards{
poolStakerEth: poolStakerEth,
Expand Down Expand Up @@ -965,15 +966,13 @@ func (r *treeGeneratorImpl_v11) calculateNodeRewards() (*nodeRewards, error) {
}

if r.rewardsFile.RulesetVersion >= 10 {
remainingBalance := big.NewInt(0).Sub(r.smoothingPoolBalance, totalEthForMinipools)
// We're distributing the smoothing pool balance plus the pending voter share
remainingBalance := big.NewInt(0).Add(r.smoothingPoolBalance, r.networkState.NetworkDetails.PendingVoterShareEth)
remainingBalance.Sub(remainingBalance, totalEthForMinipools)
remainingBalance.Sub(remainingBalance, totalEthForMegapools)
remainingBalance.Sub(remainingBalance, pdaoEth)
if trueVoterEth.Sign() > 0 {
remainingBalance.Sub(remainingBalance, trueVoterEth)
} else {
// Nobody earned voter share.
// Subtract voter share- it shouldn't be used to pay bonuses, or we could have a deficit later.
remainingBalance.Sub(remainingBalance, r.networkState.NetworkDetails.SmoothingPoolPendingVoterShare)
}
// Only process bonuses if totalConsensusBonus is greater than zero
if totalConsensusBonus != nil && totalConsensusBonus.Sign() > 0 {
Expand Down Expand Up @@ -1024,8 +1023,9 @@ func (r *treeGeneratorImpl_v11) calculateNodeRewards() (*nodeRewards, error) {

trueNodeOperatorAmount.Add(trueNodeOperatorAmount, totalEthForBonuses)

// This is how much actually goes to the pool stakers - it should ideally be equal to poolStakerShare but this accounts for any cumulative floating point errors
truePoolStakerAmount := big.NewInt(0).Sub(r.smoothingPoolBalance, trueNodeOperatorAmount)
// This is how much actually goes to the pool stakers (rETH holders) - it should ideally be equal to poolStakerShare but this accounts for any cumulative floating point errors
truePoolStakerAmount := big.NewInt(0).Add(r.smoothingPoolBalance, r.networkState.NetworkDetails.PendingVoterShareEth)
truePoolStakerAmount.Sub(truePoolStakerAmount, trueNodeOperatorAmount)
truePoolStakerAmount.Sub(truePoolStakerAmount, pdaoEth)
truePoolStakerAmount.Sub(truePoolStakerAmount, trueVoterEth)

Expand Down
18 changes: 9 additions & 9 deletions shared/services/rewards/mock_v11_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -850,7 +850,7 @@ func TestInsufficientEthForBonusesesV11(tt *testing.T) {
// Ovewrite the SP balance to a value under the bonus commission
history.NetworkDetails.SmoothingPoolBalance = big.NewInt(1100)
// Set the SP voter share to 0
history.NetworkDetails.SmoothingPoolPendingVoterShare = big.NewInt(100)
history.NetworkDetails.PendingVoterShareEth = big.NewInt(100)
// Set the pdao share to 0
state := history.GetEndNetworkState()
state.IsSaturnDeployed = true
Expand Down Expand Up @@ -909,12 +909,12 @@ func TestInsufficientEthForBonusesesV11(tt *testing.T) {
// Check the rewards file
rewardsFile := v11Artifacts.RewardsFile
ethOne := rewardsFile.GetNodeSmoothingPoolEth(nodeOne.Address)
if ethOne.Uint64() != 579 {
t.Fatalf("Node one ETH amount does not match expected value: %s != %d", ethOne.String(), 169+416)
if ethOne.Uint64() != 707 {
t.Fatalf("Node one ETH amount does not match expected value: %s != %d", ethOne.String(), 707)
}
ethTwo := rewardsFile.GetNodeSmoothingPoolEth(nodeTwo.Address)
if ethTwo.Uint64() != 420 {
t.Fatalf("Node two ETH amount does not match expected value: %s != %d", ethTwo.String(), 177+237)
if ethTwo.Uint64() != 492 {
t.Fatalf("Node two ETH amount does not match expected value: %s != %d", ethTwo.String(), 492)
}

// Check the minipool performance file
Expand All @@ -923,15 +923,15 @@ func TestInsufficientEthForBonusesesV11(tt *testing.T) {
if !ok {
t.Fatalf("Node one minipool performance not found")
}
if perfOne.GetBonusEthEarned().Uint64() != 393 {
t.Fatalf("Node one bonus does not match expected value: %s != %d", perfOne.GetBonusEthEarned().String(), 416)
if perfOne.GetBonusEthEarned().Uint64() != 521 {
t.Fatalf("Node one bonus does not match expected value: %s != %d", perfOne.GetBonusEthEarned().String(), 521)
}
perfTwo, ok := minipoolPerformanceFile.GetMinipoolPerformance(nodeTwo.Minipools[0].Address)
if !ok {
t.Fatalf("Node two minipool performance not found")
}
if perfTwo.GetBonusEthEarned().Uint64() != 225 {
t.Fatalf("Node two bonus does not match expected value: %s != %d", perfTwo.GetBonusEthEarned().String(), 237)
if perfTwo.GetBonusEthEarned().Uint64() != 297 {
t.Fatalf("Node two bonus does not match expected value: %s != %d", perfTwo.GetBonusEthEarned().String(), 297)
}
}

Expand Down
2 changes: 1 addition & 1 deletion shared/services/rewards/test/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -646,7 +646,7 @@ func NewDefaultMockHistoryNoNodes() *MockHistory {
VoterShare: big.NewInt(6e16),
PdaoShare: big.NewInt(5e16),
},
SmoothingPoolPendingVoterShare: big.NewInt(0).Mul(big.NewInt(10), oneEth),
PendingVoterShareEth: big.NewInt(0).Mul(big.NewInt(10), oneEth),

// The rest of the fields seem unimportant and are left empty
},
Expand Down
2 changes: 1 addition & 1 deletion shared/types/eth2/fork/electra/state_electra.go
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,7 @@ func (state *BeaconState) GetSlot() uint64 {
return state.Slot
}

// Added for compatibility
// Added for compatibility
func (state *BeaconState) BlockHeaderProof() ([][]byte, error) {
return nil, nil
}
2 changes: 1 addition & 1 deletion shared/types/eth2/fork/fulu/state_fulu.go
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ func (state *BeaconState) BlockRootProof(slot uint64) ([][]byte, error) {
if err != nil {
return nil, fmt.Errorf("could not get proof for block root: %w", err)
}

return proof.Hashes, nil
}

Expand Down
Loading