From c7d9a8e6850fb26ecc8f4b2c2b2c978bb9a9f9f4 Mon Sep 17 00:00:00 2001
From: Justin Brower <jbrower95@gmail.com>
Date: Tue, 20 Aug 2024 12:44:27 -0400
Subject: [PATCH 1/7] update healthcheck logic

---
 cli/commands/checkpoint.go  |   3 +-
 cli/commands/credentials.go |   5 +-
 cli/commands/status.go      |   8 +--
 cli/commands/utils.go       |  21 --------
 cli/core/findStalePods.go   | 105 ++++++++++++++++++++++--------------
 cli/utils/utils.go          |  43 +++++++++++++--
 6 files changed, 113 insertions(+), 72 deletions(-)

diff --git a/cli/commands/checkpoint.go b/cli/commands/checkpoint.go
index 8beb62c9..c0b27eaf 100644
--- a/cli/commands/checkpoint.go
+++ b/cli/commands/checkpoint.go
@@ -5,6 +5,7 @@ import (
 
 	"github.com/Layr-Labs/eigenpod-proofs-generation/cli/core"
 	"github.com/Layr-Labs/eigenpod-proofs-generation/cli/core/onchain"
+	"github.com/Layr-Labs/eigenpod-proofs-generation/cli/utils"
 	"github.com/ethereum/go-ethereum/accounts/abi/bind"
 	"github.com/ethereum/go-ethereum/common"
 	"github.com/ethereum/go-ethereum/core/types"
@@ -94,7 +95,7 @@ func CheckpointCommand(args TCheckpointCommandArgs) error {
 
 	txns, err := core.SubmitCheckpointProof(ctx, args.Sender, args.EigenpodAddress, chainId, proof, eth, args.BatchSize, args.NoPrompt, args.SimulateTransaction)
 	if args.SimulateTransaction {
-		printableTxns := aMap(txns, func(txn *types.Transaction) Transaction {
+		printableTxns := utils.Map(txns, func(txn *types.Transaction, _ uint64) Transaction {
 			return Transaction{
 				To:       txn.To().Hex(),
 				CallData: common.Bytes2Hex(txn.Data()),
diff --git a/cli/commands/credentials.go b/cli/commands/credentials.go
index c445cec0..cc230af8 100644
--- a/cli/commands/credentials.go
+++ b/cli/commands/credentials.go
@@ -7,6 +7,7 @@ import (
 	"math/big"
 
 	"github.com/Layr-Labs/eigenpod-proofs-generation/cli/core"
+	"github.com/Layr-Labs/eigenpod-proofs-generation/cli/utils"
 	"github.com/ethereum/go-ethereum/common"
 	"github.com/ethereum/go-ethereum/core/types"
 	"github.com/fatih/color"
@@ -65,7 +66,7 @@ func CredentialsCommand(args TCredentialCommandArgs) error {
 		}()), err)
 
 		if args.SimulateTransaction {
-			out := aMap(txns, func(txn *types.Transaction) CredentialProofTransaction {
+			out := utils.Map(txns, func(txn *types.Transaction, _ uint64) CredentialProofTransaction {
 				gas := txn.Gas()
 				return CredentialProofTransaction{
 					Transaction: Transaction{
@@ -79,7 +80,7 @@ func CredentialsCommand(args TCredentialCommandArgs) error {
 							return nil
 						}(),
 					},
-					ValidatorIndices: aMap(aFlatten(indices), func(index *big.Int) uint64 {
+					ValidatorIndices: utils.Map(utils.Flatten(indices), func(index *big.Int, _ uint64) uint64 {
 						return index.Uint64()
 					}),
 				}
diff --git a/cli/commands/status.go b/cli/commands/status.go
index 701ba539..bb9b90a2 100644
--- a/cli/commands/status.go
+++ b/cli/commands/status.go
@@ -74,7 +74,7 @@ func StatusCommand(args TStatusArgs) error {
 			for _, validator := range awaitingActivationQueueValidators {
 				publicKey := validator.PublicKey
 				if !isVerbose {
-					publicKey = shortenHex(publicKey)
+					publicKey = utils.ShortenHex(publicKey)
 				}
 
 				targetColor = color.New(color.FgHiRed)
@@ -97,7 +97,7 @@ func StatusCommand(args TStatusArgs) error {
 			for _, validator := range inactiveValidators {
 				publicKey := validator.PublicKey
 				if !isVerbose {
-					publicKey = shortenHex(publicKey)
+					publicKey = utils.ShortenHex(publicKey)
 				}
 
 				if validator.Slashed {
@@ -120,7 +120,7 @@ func StatusCommand(args TStatusArgs) error {
 			for _, validator := range activeValidators {
 				publicKey := validator.PublicKey
 				if !isVerbose {
-					publicKey = shortenHex(publicKey)
+					publicKey = utils.ShortenHex(publicKey)
 				}
 
 				if validator.Slashed {
@@ -143,7 +143,7 @@ func StatusCommand(args TStatusArgs) error {
 			for _, validator := range withdrawnValidators {
 				publicKey := validator.PublicKey
 				if !isVerbose {
-					publicKey = shortenHex(publicKey)
+					publicKey = utils.ShortenHex(publicKey)
 				}
 
 				if validator.Slashed {
diff --git a/cli/commands/utils.go b/cli/commands/utils.go
index f0f8fbbb..49059b16 100644
--- a/cli/commands/utils.go
+++ b/cli/commands/utils.go
@@ -25,24 +25,3 @@ func printProofs(txns any) {
 	core.PanicOnError("failed to serialize proofs", err)
 	fmt.Println(string(out))
 }
-
-// imagine if golang had a standard library
-func aMap[A any, B any](coll []A, mapper func(i A) B) []B {
-	out := make([]B, len(coll))
-	for i, item := range coll {
-		out[i] = mapper(item)
-	}
-	return out
-}
-
-func aFlatten[A any](coll [][]A) []A {
-	out := []A{}
-	for _, arr := range coll {
-		out = append(out, arr...)
-	}
-	return out
-}
-
-func shortenHex(publicKey string) string {
-	return publicKey[0:6] + ".." + publicKey[len(publicKey)-4:]
-}
diff --git a/cli/core/findStalePods.go b/cli/core/findStalePods.go
index 52f7f662..638620dc 100644
--- a/cli/core/findStalePods.go
+++ b/cli/core/findStalePods.go
@@ -5,8 +5,10 @@ import (
 	"fmt"
 	"log"
 	"math/big"
+	"strings"
 
 	"github.com/Layr-Labs/eigenpod-proofs-generation/cli/core/onchain"
+	"github.com/Layr-Labs/eigenpod-proofs-generation/cli/utils"
 	"github.com/attestantio/go-eth2-client/spec/phase0"
 	"github.com/ethereum/go-ethereum/accounts/abi/bind"
 	"github.com/ethereum/go-ethereum/common"
@@ -25,8 +27,20 @@ type Cache struct {
 	PodOwnerShares map[string]PodOwnerShare
 }
 
+func keys[A comparable, B any](coll map[A]B) []A {
+	if len(coll) == 0 {
+		return []A{}
+	}
+	out := make([]A, len(coll))
+	for key, _ := range coll {
+		out[len(out)] = key
+	}
+	return out
+}
+
 type PodOwnerShare struct {
 	Shares     uint64
+	NativeETH  phase0.Gwei
 	IsEigenpod bool
 }
 
@@ -46,6 +60,7 @@ func isEigenpod(eth *ethclient.Client, chainId uint64, eigenpodAddress string) (
 	// default to false
 	cache.PodOwnerShares[eigenpodAddress] = PodOwnerShare{
 		Shares:     0,
+		NativeETH:  phase0.Gwei(0),
 		IsEigenpod: false,
 	}
 
@@ -85,10 +100,16 @@ func isEigenpod(eth *ethclient.Client, chainId uint64, eigenpodAddress string) (
 		return false, fmt.Errorf("PodOwnerShares() failed: %s", err.Error())
 	}
 
+	balance, err := eth.BalanceAt(context.Background(), common.HexToAddress(eigenpodAddress), nil)
+	if err != nil {
+		return false, fmt.Errorf("balance check failed: %s", err.Error())
+	}
+
 	// Simulate fetching from contracts
 	// Implement contract fetching logic here
 	cache.PodOwnerShares[eigenpodAddress] = PodOwnerShare{
 		Shares:     podOwnerShares.Uint64(),
+		NativeETH:  phase0.Gwei(balance.Uint64()),
 		IsEigenpod: true,
 	}
 
@@ -103,24 +124,6 @@ func executionWithdrawalAddress(withdrawalCredentials []byte) *string {
 	return &addr
 }
 
-func aFilter[T any](coll []T, criteria func(T) bool) []T {
-	var result []T
-	for _, item := range coll {
-		if criteria(item) {
-			result = append(result, item)
-		}
-	}
-	return result
-}
-
-func aMap[T any, A any](coll []T, mapper func(T, uint64) A) []A {
-	var result []A
-	for idx, item := range coll {
-		result = append(result, mapper(item, uint64(idx)))
-	}
-	return result
-}
-
 func FindStaleEigenpods(ctx context.Context, eth *ethclient.Client, nodeUrl string, beacon BeaconClient, chainId *big.Int, verbose bool) (map[string][]ValidatorWithIndex, error) {
 	beaconState, err := beacon.GetBeaconState(ctx, "head")
 	if err != nil {
@@ -133,7 +136,7 @@ func FindStaleEigenpods(ctx context.Context, eth *ethclient.Client, nodeUrl stri
 		return nil, err
 	}
 
-	allValidatorsWithIndices := aMap(_allValidators, func(validator *phase0.Validator, index uint64) ValidatorWithIndex {
+	allValidatorsWithIndices := utils.Map(_allValidators, func(validator *phase0.Validator, index uint64) ValidatorWithIndex {
 		return ValidatorWithIndex{
 			Validator: validator,
 			Index:     index,
@@ -141,7 +144,7 @@ func FindStaleEigenpods(ctx context.Context, eth *ethclient.Client, nodeUrl stri
 	})
 
 	// TODO(pectra): this logic changes after the pectra upgrade.
-	allSlashedValidators := aFilter(allValidatorsWithIndices, func(v ValidatorWithIndex) bool {
+	allSlashedValidators := utils.Filter(allValidatorsWithIndices, func(v ValidatorWithIndex) bool {
 		if !v.Validator.Slashed {
 			return false // we only care about slashed validators.
 		}
@@ -163,7 +166,7 @@ func FindStaleEigenpods(ctx context.Context, eth *ethclient.Client, nodeUrl stri
 
 	validatorToPod := map[uint64]string{}
 
-	allSlashedValidatorsBelongingToEigenpods := aFilter(allSlashedValidators, func(validator ValidatorWithIndex) bool {
+	allSlashedValidatorsBelongingToEigenpods := utils.Filter(allSlashedValidators, func(validator ValidatorWithIndex) bool {
 		isPod, err := isEigenpod(eth, chainId.Uint64(), *executionWithdrawalAddress(validator.Validator.WithdrawalCredentials))
 		if err != nil {
 			return false
@@ -172,11 +175,13 @@ func FindStaleEigenpods(ctx context.Context, eth *ethclient.Client, nodeUrl stri
 	})
 
 	allValidatorInfo := make(map[uint64]onchain.IEigenPodValidatorInfo)
-
 	for _, validator := range allSlashedValidatorsBelongingToEigenpods {
 		eigenpodAddress := *executionWithdrawalAddress(validator.Validator.WithdrawalCredentials)
 		pod, err := onchain.NewEigenPod(common.HexToAddress(eigenpodAddress), eth)
-		PanicOnError("failed to dial eigenpod", err)
+		if err != nil {
+			// failed to load validator info.
+			return map[string][]ValidatorWithIndex{}, fmt.Errorf("failed to dial eigenpod: %s", err.Error())
+		}
 
 		info, err := pod.ValidatorPubkeyToInfo(nil, validator.Validator.PublicKey[:])
 		if err != nil {
@@ -186,9 +191,9 @@ func FindStaleEigenpods(ctx context.Context, eth *ethclient.Client, nodeUrl stri
 		allValidatorInfo[validator.Index] = info
 	}
 
-	allActiveSlashedValidatorsBelongingToEigenpods := aFilter(allSlashedValidatorsBelongingToEigenpods, func(validator ValidatorWithIndex) bool {
+	allActiveSlashedValidatorsBelongingToEigenpods := utils.Filter(allSlashedValidatorsBelongingToEigenpods, func(validator ValidatorWithIndex) bool {
 		validatorInfo := allValidatorInfo[validator.Index]
-		return validatorInfo.Status == 1
+		return validatorInfo.Status == 1 // "ACTIVE"
 	})
 
 	if verbose {
@@ -204,30 +209,50 @@ func FindStaleEigenpods(ctx context.Context, eth *ethclient.Client, nodeUrl stri
 		}
 	}
 
-	if verbose {
-		log.Printf("%d EigenPods were slashed\n", len(slashedEigenpods))
-	}
-
 	allValidatorBalances, err := beaconState.ValidatorBalances()
 	if err != nil {
 		return nil, err
 	}
 
-	var unhealthyEigenpods map[string]bool = make(map[string]bool)
-	for _, validator := range allActiveSlashedValidatorsBelongingToEigenpods {
-		balance := allValidatorBalances[validator.Index]
-		pod := validatorToPod[validator.Index]
-		executionBalance := cache.PodOwnerShares[pod].Shares
-		if executionBalance == 0 {
-			continue
+	totalAssetsGweiByEigenpod := utils.Reduce(keys(slashedEigenpods), func(allBalances map[string]phase0.Gwei, eigenpod string) map[string]phase0.Gwei {
+		// total assets of an eigenpod are determined as;
+		//	SUM(
+		//		- native ETH in the pod
+		//		- any active validators and their associated balances
+		// 	)
+		allEigenpodsForValidator := utils.Filter(allValidatorsWithIndices, func(v ValidatorWithIndex) bool {
+			withdrawal := executionWithdrawalAddress(v.Validator.WithdrawalCredentials)
+			return withdrawal != nil && strings.EqualFold(*withdrawal, eigenpod)
+		})
+
+		allValidatorBalancesSummed := utils.Reduce(allEigenpodsForValidator, func(accum phase0.Gwei, validator ValidatorWithIndex) phase0.Gwei {
+			return accum + allValidatorBalances[validator.Index]
+		}, phase0.Gwei(0))
+
+		balance := phase0.Gwei(cache.PodOwnerShares[eigenpod].NativeETH) + allValidatorBalancesSummed
+		allBalances[eigenpod] = phase0.Gwei(balance)
+		return allBalances
+	}, map[string]phase0.Gwei{})
+
+	if verbose {
+		log.Printf("%d EigenPods were slashed\n", len(slashedEigenpods))
+	}
+
+	unhealthyEigenpods := utils.Filter(keys(slashedEigenpods), func(eigenpod string) bool {
+		balance, ok := totalAssetsGweiByEigenpod[eigenpod]
+		if !ok {
+			return false
 		}
+		executionBalance := cache.PodOwnerShares[eigenpod].Shares
 		if balance <= phase0.Gwei(float64(executionBalance)*ACCEPTABLE_BALANCE_DEVIATION) {
-			unhealthyEigenpods[pod] = true
 			if verbose {
-				log.Printf("[%s] %.2f%% deviation (beacon: %d -> execution: %d)\n", pod, 100*(float64(executionBalance)-float64(balance))/float64(executionBalance), balance, executionBalance)
+				log.Printf("[%s] %.2f%% deviation (beacon: %d -> execution: %d)\n", eigenpod, 100*(float64(executionBalance)-float64(balance))/float64(executionBalance), balance, executionBalance)
 			}
+			return true
 		}
-	}
+
+		return false
+	})
 
 	if len(unhealthyEigenpods) == 0 {
 		if verbose {
@@ -241,7 +266,7 @@ func FindStaleEigenpods(ctx context.Context, eth *ethclient.Client, nodeUrl stri
 	}
 
 	var entries map[string][]ValidatorWithIndex = make(map[string][]ValidatorWithIndex)
-	for val := range unhealthyEigenpods {
+	for _, val := range unhealthyEigenpods {
 		entries[val] = slashedEigenpods[val]
 	}
 
diff --git a/cli/utils/utils.go b/cli/utils/utils.go
index 341d348f..c84626ed 100644
--- a/cli/utils/utils.go
+++ b/cli/utils/utils.go
@@ -1,9 +1,44 @@
 package utils
 
-func ShortenHex(publicKey string) string {
-	return publicKey[0:6] + ".." + publicKey[len(publicKey)-4:]
-}
-
 // maximum number of proofs per txn for each of the following proof types:
 const DEFAULT_BATCH_CREDENTIALS = 60
 const DEFAULT_BATCH_CHECKPOINT = 80
+
+// imagine if golang had a standard library
+func Map[A any, B any](coll []A, mapper func(i A, index uint64) B) []B {
+	out := make([]B, len(coll))
+	for i, item := range coll {
+		out[i] = mapper(item, uint64(i))
+	}
+	return out
+}
+
+func Filter[A any](coll []A, criteria func(i A) bool) []A {
+	out := []A{}
+	for _, item := range coll {
+		if criteria(item) {
+			out = append(out, item)
+		}
+	}
+	return out
+}
+
+func Reduce[A any, B any](coll []A, processor func(accum B, next A) B, initialState B) B {
+	val := initialState
+	for _, item := range coll {
+		val = processor(val, item)
+	}
+	return val
+}
+
+func Flatten[A any](coll [][]A) []A {
+	out := []A{}
+	for _, arr := range coll {
+		out = append(out, arr...)
+	}
+	return out
+}
+
+func ShortenHex(publicKey string) string {
+	return publicKey[0:6] + ".." + publicKey[len(publicKey)-4:]
+}

From 263c5c183c4c13bc02a1f32b8c3ea7488d94e0ea Mon Sep 17 00:00:00 2001
From: Justin Brower <jbrower95@gmail.com>
Date: Tue, 20 Aug 2024 13:09:47 -0400
Subject: [PATCH 2/7] use reduce instead

---
 cli/core/findStalePods.go | 11 +++++++----
 1 file changed, 7 insertions(+), 4 deletions(-)

diff --git a/cli/core/findStalePods.go b/cli/core/findStalePods.go
index 638620dc..fe10489f 100644
--- a/cli/core/findStalePods.go
+++ b/cli/core/findStalePods.go
@@ -200,14 +200,17 @@ func FindStaleEigenpods(ctx context.Context, eth *ethclient.Client, nodeUrl stri
 		log.Printf("%d EigenValidators were slashed\n", len(allActiveSlashedValidatorsBelongingToEigenpods))
 	}
 
-	slashedEigenpods := make(map[string][]ValidatorWithIndex)
-	for _, validator := range allActiveSlashedValidatorsBelongingToEigenpods {
+	slashedEigenpods := utils.Reduce(allActiveSlashedValidatorsBelongingToEigenpods, func(pods map[string][]ValidatorWithIndex, validator ValidatorWithIndex) map[string][]ValidatorWithIndex {
 		podAddress := executionWithdrawalAddress(validator.Validator.WithdrawalCredentials)
 		if podAddress != nil {
-			slashedEigenpods[*podAddress] = append(slashedEigenpods[*podAddress], validator)
+			if pods[*podAddress] == nil {
+				pods[*podAddress] = []ValidatorWithIndex{}
+			}
+			pods[*podAddress] = append(pods[*podAddress], validator)
 			validatorToPod[validator.Index] = *podAddress
 		}
-	}
+		return pods
+	}, map[string][]ValidatorWithIndex{})
 
 	allValidatorBalances, err := beaconState.ValidatorBalances()
 	if err != nil {

From bffd07e13e206d9637849791a008132d36b2c457 Mon Sep 17 00:00:00 2001
From: Justin Brower <jbrower95@gmail.com>
Date: Tue, 20 Aug 2024 14:11:40 -0400
Subject: [PATCH 3/7] wei to gwei

---
 cli/core/findStalePods.go | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/cli/core/findStalePods.go b/cli/core/findStalePods.go
index fe10489f..69d34e2d 100644
--- a/cli/core/findStalePods.go
+++ b/cli/core/findStalePods.go
@@ -13,6 +13,7 @@ import (
 	"github.com/ethereum/go-ethereum/accounts/abi/bind"
 	"github.com/ethereum/go-ethereum/common"
 	"github.com/ethereum/go-ethereum/ethclient"
+	"github.com/ethereum/go-ethereum/params"
 	"github.com/pkg/errors"
 )
 
@@ -23,6 +24,10 @@ func PodManagerContracts() map[uint64]string {
 	}
 }
 
+func weiToGwei(val uint64) phase0.Gwei {
+	return phase0.Gwei(new(big.Int).Div(new(big.Int).SetUint64(val), big.NewInt(params.GWei)).Uint64())
+}
+
 type Cache struct {
 	PodOwnerShares map[string]PodOwnerShare
 }
@@ -109,7 +114,7 @@ func isEigenpod(eth *ethclient.Client, chainId uint64, eigenpodAddress string) (
 	// Implement contract fetching logic here
 	cache.PodOwnerShares[eigenpodAddress] = PodOwnerShare{
 		Shares:     podOwnerShares.Uint64(),
-		NativeETH:  phase0.Gwei(balance.Uint64()),
+		NativeETH:  weiToGwei(balance.Uint64()),
 		IsEigenpod: true,
 	}
 

From 7abc9d8104734353e641a375e16c1d106cef60eb Mon Sep 17 00:00:00 2001
From: Justin Brower <jbrower95@gmail.com>
Date: Tue, 20 Aug 2024 14:32:37 -0400
Subject: [PATCH 4/7] more nits

---
 cli/core/findStalePods.go | 29 +++++++++++++----------------
 1 file changed, 13 insertions(+), 16 deletions(-)

diff --git a/cli/core/findStalePods.go b/cli/core/findStalePods.go
index 69d34e2d..ec098565 100644
--- a/cli/core/findStalePods.go
+++ b/cli/core/findStalePods.go
@@ -44,14 +44,14 @@ func keys[A comparable, B any](coll map[A]B) []A {
 }
 
 type PodOwnerShare struct {
-	Shares     uint64
-	NativeETH  phase0.Gwei
-	IsEigenpod bool
+	Shares                uint64
+	ExecutionLayerBalance phase0.Gwei
+	IsEigenpod            bool
 }
 
 const ACCEPTABLE_BALANCE_DEVIATION = float64(0.95)
 
-var cache Cache
+var cache Cache // valid for the duration of a command.
 
 func isEigenpod(eth *ethclient.Client, chainId uint64, eigenpodAddress string) (bool, error) {
 	if cache.PodOwnerShares == nil {
@@ -64,9 +64,9 @@ func isEigenpod(eth *ethclient.Client, chainId uint64, eigenpodAddress string) (
 
 	// default to false
 	cache.PodOwnerShares[eigenpodAddress] = PodOwnerShare{
-		Shares:     0,
-		NativeETH:  phase0.Gwei(0),
-		IsEigenpod: false,
+		Shares:                0,
+		ExecutionLayerBalance: phase0.Gwei(0),
+		IsEigenpod:            false,
 	}
 
 	podManAddress, ok := PodManagerContracts()[chainId]
@@ -113,9 +113,9 @@ func isEigenpod(eth *ethclient.Client, chainId uint64, eigenpodAddress string) (
 	// Simulate fetching from contracts
 	// Implement contract fetching logic here
 	cache.PodOwnerShares[eigenpodAddress] = PodOwnerShare{
-		Shares:     podOwnerShares.Uint64(),
-		NativeETH:  weiToGwei(balance.Uint64()),
-		IsEigenpod: true,
+		Shares:                podOwnerShares.Uint64(),
+		ExecutionLayerBalance: weiToGwei(balance.Uint64()),
+		IsEigenpod:            true,
 	}
 
 	return true, nil
@@ -169,8 +169,6 @@ func FindStaleEigenpods(ctx context.Context, eth *ethclient.Client, nodeUrl stri
 		return map[string][]ValidatorWithIndex{}, nil
 	}
 
-	validatorToPod := map[uint64]string{}
-
 	allSlashedValidatorsBelongingToEigenpods := utils.Filter(allSlashedValidators, func(validator ValidatorWithIndex) bool {
 		isPod, err := isEigenpod(eth, chainId.Uint64(), *executionWithdrawalAddress(validator.Validator.WithdrawalCredentials))
 		if err != nil {
@@ -212,7 +210,6 @@ func FindStaleEigenpods(ctx context.Context, eth *ethclient.Client, nodeUrl stri
 				pods[*podAddress] = []ValidatorWithIndex{}
 			}
 			pods[*podAddress] = append(pods[*podAddress], validator)
-			validatorToPod[validator.Index] = *podAddress
 		}
 		return pods
 	}, map[string][]ValidatorWithIndex{})
@@ -228,16 +225,16 @@ func FindStaleEigenpods(ctx context.Context, eth *ethclient.Client, nodeUrl stri
 		//		- native ETH in the pod
 		//		- any active validators and their associated balances
 		// 	)
-		allEigenpodsForValidator := utils.Filter(allValidatorsWithIndices, func(v ValidatorWithIndex) bool {
+		allValidatorsForEigenpod := utils.Filter(allValidatorsWithIndices, func(v ValidatorWithIndex) bool {
 			withdrawal := executionWithdrawalAddress(v.Validator.WithdrawalCredentials)
 			return withdrawal != nil && strings.EqualFold(*withdrawal, eigenpod)
 		})
 
-		allValidatorBalancesSummed := utils.Reduce(allEigenpodsForValidator, func(accum phase0.Gwei, validator ValidatorWithIndex) phase0.Gwei {
+		allValidatorBalancesSummed := utils.Reduce(allValidatorsForEigenpod, func(accum phase0.Gwei, validator ValidatorWithIndex) phase0.Gwei {
 			return accum + allValidatorBalances[validator.Index]
 		}, phase0.Gwei(0))
 
-		balance := phase0.Gwei(cache.PodOwnerShares[eigenpod].NativeETH) + allValidatorBalancesSummed
+		balance := phase0.Gwei(cache.PodOwnerShares[eigenpod].ExecutionLayerBalance) + allValidatorBalancesSummed
 		allBalances[eigenpod] = phase0.Gwei(balance)
 		return allBalances
 	}, map[string]phase0.Gwei{})

From e2ccdafab3b8a3a230aea39cc671f8d090f461e2 Mon Sep 17 00:00:00 2001
From: Justin Brower <jbrower95@gmail.com>
Date: Tue, 20 Aug 2024 14:33:45 -0400
Subject: [PATCH 5/7] one line

---
 cli/core/findStalePods.go | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/cli/core/findStalePods.go b/cli/core/findStalePods.go
index ec098565..e90f376c 100644
--- a/cli/core/findStalePods.go
+++ b/cli/core/findStalePods.go
@@ -234,8 +234,7 @@ func FindStaleEigenpods(ctx context.Context, eth *ethclient.Client, nodeUrl stri
 			return accum + allValidatorBalances[validator.Index]
 		}, phase0.Gwei(0))
 
-		balance := phase0.Gwei(cache.PodOwnerShares[eigenpod].ExecutionLayerBalance) + allValidatorBalancesSummed
-		allBalances[eigenpod] = phase0.Gwei(balance)
+		allBalances[eigenpod] = phase0.Gwei(cache.PodOwnerShares[eigenpod].ExecutionLayerBalance) + allValidatorBalancesSummed
 		return allBalances
 	}, map[string]phase0.Gwei{})
 

From 6d5873f5c9fa0db819e56cf5938cb68ed1d89373 Mon Sep 17 00:00:00 2001
From: Justin Brower <jbrower95@gmail.com>
Date: Tue, 20 Aug 2024 17:44:51 -0400
Subject: [PATCH 6/7] update logic to be in wei

---
 cli/core/findStalePods.go | 34 +++++++++++++++++-----------------
 1 file changed, 17 insertions(+), 17 deletions(-)

diff --git a/cli/core/findStalePods.go b/cli/core/findStalePods.go
index e90f376c..3a92d4c3 100644
--- a/cli/core/findStalePods.go
+++ b/cli/core/findStalePods.go
@@ -44,9 +44,9 @@ func keys[A comparable, B any](coll map[A]B) []A {
 }
 
 type PodOwnerShare struct {
-	Shares                uint64
-	ExecutionLayerBalance phase0.Gwei
-	IsEigenpod            bool
+	SharesWei                uint64
+	ExecutionLayerBalanceWei uint64
+	IsEigenpod               bool
 }
 
 const ACCEPTABLE_BALANCE_DEVIATION = float64(0.95)
@@ -64,9 +64,9 @@ func isEigenpod(eth *ethclient.Client, chainId uint64, eigenpodAddress string) (
 
 	// default to false
 	cache.PodOwnerShares[eigenpodAddress] = PodOwnerShare{
-		Shares:                0,
-		ExecutionLayerBalance: phase0.Gwei(0),
-		IsEigenpod:            false,
+		SharesWei:                0,
+		ExecutionLayerBalanceWei: 0,
+		IsEigenpod:               false,
 	}
 
 	podManAddress, ok := PodManagerContracts()[chainId]
@@ -113,9 +113,9 @@ func isEigenpod(eth *ethclient.Client, chainId uint64, eigenpodAddress string) (
 	// Simulate fetching from contracts
 	// Implement contract fetching logic here
 	cache.PodOwnerShares[eigenpodAddress] = PodOwnerShare{
-		Shares:                podOwnerShares.Uint64(),
-		ExecutionLayerBalance: weiToGwei(balance.Uint64()),
-		IsEigenpod:            true,
+		SharesWei:                podOwnerShares.Uint64(),
+		ExecutionLayerBalanceWei: balance.Uint64(),
+		IsEigenpod:               true,
 	}
 
 	return true, nil
@@ -219,7 +219,7 @@ func FindStaleEigenpods(ctx context.Context, eth *ethclient.Client, nodeUrl stri
 		return nil, err
 	}
 
-	totalAssetsGweiByEigenpod := utils.Reduce(keys(slashedEigenpods), func(allBalances map[string]phase0.Gwei, eigenpod string) map[string]phase0.Gwei {
+	totalAssetsWeiByEigenpod := utils.Reduce(keys(slashedEigenpods), func(allBalances map[string]uint64, eigenpod string) map[string]uint64 {
 		// total assets of an eigenpod are determined as;
 		//	SUM(
 		//		- native ETH in the pod
@@ -230,25 +230,25 @@ func FindStaleEigenpods(ctx context.Context, eth *ethclient.Client, nodeUrl stri
 			return withdrawal != nil && strings.EqualFold(*withdrawal, eigenpod)
 		})
 
-		allValidatorBalancesSummed := utils.Reduce(allValidatorsForEigenpod, func(accum phase0.Gwei, validator ValidatorWithIndex) phase0.Gwei {
+		allValidatorBalancesSummedGwei := utils.Reduce(allValidatorsForEigenpod, func(accum phase0.Gwei, validator ValidatorWithIndex) phase0.Gwei {
 			return accum + allValidatorBalances[validator.Index]
 		}, phase0.Gwei(0))
-
-		allBalances[eigenpod] = phase0.Gwei(cache.PodOwnerShares[eigenpod].ExecutionLayerBalance) + allValidatorBalancesSummed
+		//																				   converting gwei to wei
+		allBalances[eigenpod] = cache.PodOwnerShares[eigenpod].ExecutionLayerBalanceWei + (uint64(allValidatorBalancesSummedGwei) * params.GWei)
 		return allBalances
-	}, map[string]phase0.Gwei{})
+	}, map[string]uint64{})
 
 	if verbose {
 		log.Printf("%d EigenPods were slashed\n", len(slashedEigenpods))
 	}
 
 	unhealthyEigenpods := utils.Filter(keys(slashedEigenpods), func(eigenpod string) bool {
-		balance, ok := totalAssetsGweiByEigenpod[eigenpod]
+		balance, ok := totalAssetsWeiByEigenpod[eigenpod]
 		if !ok {
 			return false
 		}
-		executionBalance := cache.PodOwnerShares[eigenpod].Shares
-		if balance <= phase0.Gwei(float64(executionBalance)*ACCEPTABLE_BALANCE_DEVIATION) {
+		executionBalance := cache.PodOwnerShares[eigenpod].SharesWei
+		if balance <= uint64(float64(executionBalance)*ACCEPTABLE_BALANCE_DEVIATION) {
 			if verbose {
 				log.Printf("[%s] %.2f%% deviation (beacon: %d -> execution: %d)\n", eigenpod, 100*(float64(executionBalance)-float64(balance))/float64(executionBalance), balance, executionBalance)
 			}

From a5391282cdb19075ed77f2361842dab9dd6715b1 Mon Sep 17 00:00:00 2001
From: Justin Brower <jbrower95@gmail.com>
Date: Tue, 20 Aug 2024 17:47:33 -0400
Subject: [PATCH 7/7] fix lint

---
 cli/commands/staleBalance.go | 6 +++---
 cli/main.go                  | 2 +-
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/cli/commands/staleBalance.go b/cli/commands/staleBalance.go
index d7382132..1e55dfaf 100644
--- a/cli/commands/staleBalance.go
+++ b/cli/commands/staleBalance.go
@@ -18,7 +18,7 @@ type TFixStaleBalanceArgs struct {
 	BeaconNode            string
 	Sender                string
 	EigenpodAddress       string
-	SlashedValidatorIndex int64
+	SlashedValidatorIndex uint64
 	Verbose               bool
 	CheckpointBatchSize   uint64
 	NoPrompt              bool
@@ -39,7 +39,7 @@ func FixStaleBalance(args TFixStaleBalanceArgs) error {
 	eth, beacon, chainId, err := core.GetClients(ctx, args.EthNode, args.BeaconNode, args.Verbose)
 	core.PanicOnError("failed to get clients", err)
 
-	validator, err := beacon.GetValidator(ctx, uint64(args.SlashedValidatorIndex))
+	validator, err := beacon.GetValidator(ctx, args.SlashedValidatorIndex)
 	core.PanicOnError("failed to fetch validator state", err)
 
 	if !validator.Validator.Slashed {
@@ -75,7 +75,7 @@ func FixStaleBalance(args TFixStaleBalanceArgs) error {
 		}
 	}
 
-	proof, oracleBeaconTimesetamp, err := core.GenerateValidatorProof(ctx, args.EigenpodAddress, eth, chainId, beacon, new(big.Int).SetUint64(uint64(args.SlashedValidatorIndex)), args.Verbose)
+	proof, oracleBeaconTimesetamp, err := core.GenerateValidatorProof(ctx, args.EigenpodAddress, eth, chainId, beacon, new(big.Int).SetUint64(args.SlashedValidatorIndex), args.Verbose)
 	core.PanicOnError("failed to generate credential proof for slashed validator", err)
 
 	if !args.NoPrompt {
diff --git a/cli/main.go b/cli/main.go
index 33bc0bdd..82ef84d4 100644
--- a/cli/main.go
+++ b/cli/main.go
@@ -71,7 +71,7 @@ func main() {
 						BeaconNode:            beacon,
 						Sender:                sender,
 						EigenpodAddress:       eigenpodAddress,
-						SlashedValidatorIndex: int64(slashedValidatorIndex),
+						SlashedValidatorIndex: slashedValidatorIndex,
 						Verbose:               verbose,
 						CheckpointBatchSize:   batchSize,
 						NoPrompt:              noPrompt,