Skip to content
Open
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
121 changes: 121 additions & 0 deletions bindings/utils/state/megapool.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,127 @@ func unpackValidatorInfoFromGlobalIndex(contract *rocketpool.Contract, data []by
return validator, nil
}

// Get all validators for a single megapool, via its own local index -- unlike
// GetAllMegapoolValidators, which walks the network-wide global index on RocketMegapoolManager.
func GetNodeMegapoolValidators(rp *rocketpool.RocketPool, contracts *NetworkContracts, megapoolAddress common.Address) ([]megapool.ValidatorInfoFromGlobalIndex, error) {
opts := &bind.CallOpts{
BlockNumber: contracts.ElBlockNumber,
}

if contracts.Multicaller == nil {
return nil, fmt.Errorf("multicaller is nil")
}

mp, err := megapool.NewMegaPoolV1(rp, megapoolAddress, opts)
if err != nil {
return nil, fmt.Errorf("error creating megapool contract for %s: %w", megapoolAddress.Hex(), err)
}

validatorCount, err := mp.GetValidatorCount(opts)
if err != nil {
return nil, fmt.Errorf("error getting validator count for megapool %s: %w", megapoolAddress.Hex(), err)
}

count := int(validatorCount)
validators := make([]megapool.ValidatorInfoFromGlobalIndex, count)
if count == 0 {
return validators, nil
}

// Capture values before launching goroutines
multicallerAddress := contracts.Multicaller.ContractAddress
megapoolContract := mp.GetContract()

var wg errgroup.Group
wg.SetLimit(threadLimit)
for i := 0; i < count; i += megapoolValidatorsBatchSize {
i := i
m := min(i+megapoolValidatorsBatchSize, count)

wg.Go(func() error {
mc, err := multicall.NewMultiCaller(rp.Client, multicallerAddress)
if err != nil {
return err
}
var dummy *big.Int
for j := i; j < m; j++ {
err = mc.AddCall(megapoolContract, &dummy, "getValidatorInfoAndPubkey", uint32(j))
if err != nil {
return fmt.Errorf("error adding validator info call for local index %d: %w", j, err)
}
}
responses, err := mc.Execute(true, opts)
if err != nil {
return fmt.Errorf("error executing megapool validator multicall for %s: %w", megapoolAddress.Hex(), err)
}
for idx, response := range responses {
if !response.Status {
return fmt.Errorf("megapool validator call failed for local index %d", i+idx)
}
validator, err := unpackValidatorInfoAndPubkey(megapoolContract, response.ReturnDataRaw)
if err != nil {
return fmt.Errorf("error unpacking validator info for local index %d: %w", i+idx, err)
}
validator.MegapoolAddress = megapoolAddress
validator.ValidatorId = uint32(i + idx)
validators[i+idx] = validator
}
return nil
})
}
if err := wg.Wait(); err != nil {
return nil, fmt.Errorf("error getting megapool validators for %s: %w", megapoolAddress.Hex(), err)
}

return validators, nil
}

// Manually unpack a getValidatorInfoAndPubkey response (nested structs don't work with UnpackIntoInterface)
func unpackValidatorInfoAndPubkey(contract *rocketpool.Contract, data []byte) (megapool.ValidatorInfoFromGlobalIndex, error) {
iface, err := contract.ABI.Unpack("getValidatorInfoAndPubkey", data)
if err != nil {
return megapool.ValidatorInfoFromGlobalIndex{}, err
}

src := iface[0].(struct {
LastAssignmentTime uint32 `json:"lastAssignmentTime"`
LastRequestedValue uint32 `json:"lastRequestedValue"`
LastRequestedBond uint32 `json:"lastRequestedBond"`
DepositValue uint32 `json:"depositValue"`

Staked bool `json:"staked"`
Exited bool `json:"exited"`
InQueue bool `json:"inQueue"`
InPrestake bool `json:"inPrestake"`
ExpressUsed bool `json:"expressUsed"`
Dissolved bool `json:"dissolved"`
Exiting bool `json:"exiting"`
Locked bool `json:"locked"`

ExitBalance uint64 `json:"exitBalance"`
LockedTime uint64 `json:"lockedTime"`
})

var validator megapool.ValidatorInfoFromGlobalIndex
validator.Pubkey = iface[1].([]byte)
validator.ValidatorInfo.LastAssignmentTime = src.LastAssignmentTime
validator.ValidatorInfo.LastRequestedValue = src.LastRequestedValue
validator.ValidatorInfo.LastRequestedBond = src.LastRequestedBond
validator.ValidatorInfo.DepositValue = src.DepositValue
validator.ValidatorInfo.Staked = src.Staked
validator.ValidatorInfo.Exited = src.Exited
validator.ValidatorInfo.InQueue = src.InQueue
validator.ValidatorInfo.InPrestake = src.InPrestake
validator.ValidatorInfo.ExpressUsed = src.ExpressUsed
validator.ValidatorInfo.Dissolved = src.Dissolved
validator.ValidatorInfo.Exiting = src.Exiting
validator.ValidatorInfo.Locked = src.Locked
validator.ValidatorInfo.ExitBalance = src.ExitBalance
validator.ValidatorInfo.LockedTime = src.LockedTime

return validator, nil
}

// Get multiple megapool details at once using batched multicalls
func GetBulkMegapoolDetails(rp *rocketpool.RocketPool, contracts *NetworkContracts, megapoolAddresses []common.Address) (map[common.Address]NativeMegapoolDetails, error) {
opts := &bind.CallOpts{
Expand Down
13 changes: 0 additions & 13 deletions rocketpool-cli/node/rewards.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,11 @@ package node

import (
"fmt"
"math/big"
"time"

cliutils "github.com/rocket-pool/smartnode/rocketpool-cli/cli"
"github.com/rocket-pool/smartnode/rocketpool-cli/cli/color"
"github.com/rocket-pool/smartnode/rocketpool-cli/cli/prompt"
"github.com/rocket-pool/smartnode/shared/math"
rprewards "github.com/rocket-pool/smartnode/shared/services/rewards"
"github.com/rocket-pool/smartnode/shared/services/rocketpool"
)
Expand Down Expand Up @@ -87,17 +85,6 @@ func getRewards(yes bool) error {
return err
}

beaconBalances, err := rp.GetValidatorMapAndBalances()
if err != nil {
return err
}
// Add the megapool unskimmed beacon rewards, if available.
// NodeBond and NodeShareOfCLBalance are nil for nodes without a megapool (legacy minipools only).
if beaconBalances.NodeBond != nil && beaconBalances.NodeShareOfCLBalance != nil {
megapoolUnskimmedRewards := new(big.Int).Sub(beaconBalances.NodeBond, beaconBalances.NodeShareOfCLBalance)
rewards.BeaconRewards = rewards.BeaconRewards + math.WeiToEth(megapoolUnskimmedRewards)
}

fmt.Println("=== ETH ===")
fmt.Printf("Your share of unskimmed Beacon Chain (CL) rewards is currently %.6f ETH.\n", rewards.BeaconRewards)
fmt.Printf("You have claimed %.6f ETH from the Smoothing Pool.\n", rewards.CumulativeEthRewards)
Expand Down
2 changes: 1 addition & 1 deletion rocketpool/api/megapool/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ func getValidatorMapAndBalances(c *cli.Command) (*api.MegapoolValidatorMapAndRew

status, err := getStatus(c, false)
if err != nil {
return nil, fmt.Errorf("Error getting the megapool status")
return nil, fmt.Errorf("Error getting the megapool status: %w", err)
}

// Response
Expand Down
Loading
Loading