@@ -43,6 +43,14 @@ type storageGetter interface {
4343 GetBool (opts * bind.CallOpts , _key [32 ]byte ) (bool , error )
4444}
4545
46+ type rewardSplitCalculator interface {
47+ CalculateRewards (megapoolAddress common.Address , rewards * big.Int , elBlockNumber uint64 ) (megapool.RewardSplit , error )
48+ }
49+
50+ type smoothingPoolShareCalculator interface {
51+ GetSmoothingPoolShare (ns * state.NetworkState , elBlockHeader * types.Header , slotTime time.Time ) (* big.Int , error )
52+ }
53+
4654// Submit network balances task
4755type submitNetworkBalances struct {
4856 c * cli.Command
@@ -58,6 +66,56 @@ type submitNetworkBalances struct {
5866 isRunning bool
5967}
6068
69+ // liveRewardSplitCalculator calls the on-chain megapool contract.
70+ type liveRewardSplitCalculator struct {
71+ rp * rocketpool.RocketPool
72+ }
73+
74+ func (c * liveRewardSplitCalculator ) CalculateRewards (megapoolAddress common.Address , rewards * big.Int , elBlockNumber uint64 ) (megapool.RewardSplit , error ) {
75+ megapoolContract , err := megapool .NewMegaPoolV1 (c .rp , megapoolAddress , nil )
76+ if err != nil {
77+ return megapool.RewardSplit {}, fmt .Errorf ("error loading megapool contract: %w" , err )
78+ }
79+ opts := & bind.CallOpts {
80+ BlockNumber : new (big.Int ).SetUint64 (elBlockNumber ),
81+ }
82+ return megapoolContract .CalculateRewards (rewards , opts )
83+ }
84+
85+ // liveSmoothingPoolCalculator uses the tree generator to approximate the
86+ // rETH share of the smoothing pool.
87+ type liveSmoothingPoolCalculator struct {
88+ log * log.ColorLogger
89+ cfg * config.RocketPoolConfig
90+ bc beacon.Client
91+ client * rocketpool.RocketPool
92+ }
93+
94+ func (c * liveSmoothingPoolCalculator ) GetSmoothingPoolShare (ns * state.NetworkState , elBlockHeader * types.Header , slotTime time.Time ) (* big.Int , error ) {
95+ currentIndex := ns .NetworkDetails .RewardIndex
96+ startTime := ns .NetworkDetails .IntervalStart
97+ intervalTime := ns .NetworkDetails .IntervalDuration
98+
99+ timeSinceStart := slotTime .Sub (startTime )
100+ intervalsPassed := timeSinceStart / intervalTime
101+ endTime := slotTime
102+ snapshotEnd := & rprewards.SnapshotEnd {
103+ Slot : ns .BeaconSlotNumber ,
104+ ConsensusBlock : ns .BeaconSlotNumber ,
105+ ExecutionBlock : ns .ElBlockNumber ,
106+ }
107+
108+ treegen , err := rprewards .NewTreeGenerator (c .log , "[Balances]" , rprewards .NewRewardsExecutionClient (c .client ), c .cfg , c .bc , currentIndex , startTime , endTime , snapshotEnd , elBlockHeader , uint64 (intervalsPassed ), ns )
109+ if err != nil {
110+ return nil , fmt .Errorf ("error creating merkle tree generator to approximate share of smoothing pool: %w" , err )
111+ }
112+ share , err := treegen .ApproximateStakerShareOfSmoothingPool ()
113+ if err != nil {
114+ return nil , fmt .Errorf ("error getting approximate share of smoothing pool: %w" , err )
115+ }
116+ return share , nil
117+ }
118+
61119// Network balance info
62120type networkBalances struct {
63121 Block uint64
@@ -381,11 +439,26 @@ func (t *submitNetworkBalances) getNetworkBalances(elBlockHeader *types.Header,
381439 mgr := state .NewNetworkStateManager (client , t .cfg .Smartnode .GetStateManagerContracts (), t .bc , t .log )
382440
383441 // Create a new state for the target block
384- state , err := mgr .GetStateForSlot (beaconBlock )
442+ ns , err := mgr .GetStateForSlot (beaconBlock )
385443 if err != nil {
386444 return networkBalances {}, fmt .Errorf ("couldn't get network state for EL block %s, Beacon slot %d: %w" , elBlock , beaconBlock , err )
387445 }
388446
447+ rewardCalc := & liveRewardSplitCalculator {rp : client }
448+ spCalc := & liveSmoothingPoolCalculator {log : t .log , cfg : t .cfg , bc : t .bc , client : client }
449+
450+ return t .getNetworkBalancesFromState (ns , elBlockHeader , slotTime , rewardCalc , spCalc )
451+ }
452+
453+ // getNetworkBalancesFromState computes the network balances from an already-loaded NetworkState.
454+ func (t * submitNetworkBalances ) getNetworkBalancesFromState (
455+ state * state.NetworkState ,
456+ elBlockHeader * types.Header ,
457+ slotTime time.Time ,
458+ rewardCalc rewardSplitCalculator ,
459+ spCalc smoothingPoolShareCalculator ,
460+ ) (networkBalances , error ) {
461+
389462 // Data
390463 var wg errgroup.Group
391464 var depositPoolBalance * big.Int
@@ -413,7 +486,8 @@ func (t *submitNetworkBalances) getNetworkBalances(elBlockHeader *types.Header,
413486 megapoolBalanceDetails = make ([]megapoolBalanceDetail , len (state .MegapoolDetails ))
414487 i := 0
415488 for megapoolAddress , megapoolDetails := range state .MegapoolDetails {
416- megapoolBalanceDetails [i ], err = t .getMegapoolBalanceDetails (megapoolAddress , state , megapoolDetails )
489+ var err error
490+ megapoolBalanceDetails [i ], err = t .getMegapoolBalanceDetails (megapoolAddress , state , megapoolDetails , rewardCalc )
417491 if err != nil {
418492 return fmt .Errorf ("error getting megapool balance details: %w" , err )
419493 }
@@ -434,37 +508,9 @@ func (t *submitNetworkBalances) getNetworkBalances(elBlockHeader *types.Header,
434508
435509 // Get the smoothing pool user share
436510 wg .Go (func () error {
437-
438- // Get the current interval
439- currentIndex := state .NetworkDetails .RewardIndex
440-
441- // Get the start time for the current interval, and how long an interval is supposed to take
442- startTime := state .NetworkDetails .IntervalStart
443- intervalTime := state .NetworkDetails .IntervalDuration
444-
445- timeSinceStart := slotTime .Sub (startTime )
446- intervalsPassed := timeSinceStart / intervalTime
447- endTime := slotTime
448- // Since we aren't generating an actual tree, just use beaconBlock as the snapshotEnd
449- snapshotEnd := & rprewards.SnapshotEnd {
450- Slot : beaconBlock ,
451- ConsensusBlock : beaconBlock ,
452- ExecutionBlock : state .ElBlockNumber ,
453- }
454-
455- // Approximate the staker's share of the smoothing pool balance
456- // NOTE: this will use the "vanilla" variant of treegen, without rolling records, to retain parity with other Oracle DAO nodes that aren't using rolling records
457- treegen , err := rprewards .NewTreeGenerator (t .log , "[Balances]" , rprewards .NewRewardsExecutionClient (client ), t .cfg , t .bc , currentIndex , startTime , endTime , snapshotEnd , elBlockHeader , uint64 (intervalsPassed ), state )
458- if err != nil {
459- return fmt .Errorf ("error creating merkle tree generator to approximate share of smoothing pool: %w" , err )
460- }
461- smoothingPoolShare , err = treegen .ApproximateStakerShareOfSmoothingPool ()
462- if err != nil {
463- return fmt .Errorf ("error getting approximate share of smoothing pool: %w" , err )
464- }
465-
466- return nil
467-
511+ var err error
512+ smoothingPoolShare , err = spCalc .GetSmoothingPoolShare (state , elBlockHeader , slotTime )
513+ return err
468514 })
469515
470516 // Wait for data
@@ -517,7 +563,7 @@ func (t *submitNetworkBalances) getNetworkBalances(elBlockHeader *types.Header,
517563
518564}
519565
520- func (t * submitNetworkBalances ) getMegapoolBalanceDetails (megapoolAddress common.Address , state * state.NetworkState , megapoolDetails rpstate.NativeMegapoolDetails ) (megapoolBalanceDetail , error ) {
566+ func (t * submitNetworkBalances ) getMegapoolBalanceDetails (megapoolAddress common.Address , state * state.NetworkState , megapoolDetails rpstate.NativeMegapoolDetails , rewardCalc rewardSplitCalculator ) (megapoolBalanceDetail , error ) {
521567 megapoolBalanceDetails := megapoolBalanceDetail {}
522568 megapoolValidators := state .MegapoolToPubkeysMap [megapoolAddress ]
523569 // iterate the megapoolValidators array
@@ -598,24 +644,9 @@ func (t *submitNetworkBalances) getMegapoolBalanceDetails(megapoolAddress common
598644 beaconBalanceIncrease = beaconBalanceIncrease .Sub (beaconBalanceIncrease , megapoolDetails .NodeBond )
599645 rewards := big .NewInt (0 ).Add (beaconBalanceIncrease , pendingRewards )
600646
601- // Load the megapool
602- megapoolContract , err := megapool .NewMegaPoolV1 (t .rp , megapoolAddress , nil )
603- if err != nil {
604- return megapoolBalanceDetail {}, fmt .Errorf ("error loading megapool contract: %w" , err )
605- }
606- rewardsSplit := megapool.RewardSplit {
607- NodeRewards : big .NewInt (0 ),
608- VoterRewards : big .NewInt (0 ),
609- RethRewards : big .NewInt (0 ),
610- ProtocolDAORewards : big .NewInt (0 ),
611- }
612647 megapoolBalanceDetails .RethRewards = big .NewInt (0 )
613648 if rewards .Cmp (big .NewInt (0 )) > 0 {
614- opts := & bind.CallOpts {
615- BlockNumber : big .NewInt (0 ).SetUint64 (state .ElBlockNumber ),
616- }
617- rewardsSplit , err = megapoolContract .CalculateRewards (rewards , opts )
618-
649+ rewardsSplit , err := rewardCalc .CalculateRewards (megapoolAddress , rewards , state .ElBlockNumber )
619650 if err != nil {
620651 return megapoolBalanceDetail {}, fmt .Errorf ("error calculating rewards split: %w" , err )
621652 }
0 commit comments