Repository: rotki/rotki

Issue:
ETH that is in flight in the deposit queue is not detected properly
## Problem Definition

When a user sends ETH to the deposit contract rotki seems to no longer properly detect it until the deposit is confirmed.

This seems to be due to the https://beaconcha.in/api/v1/validator/eth1/0xDEPOSITINGETH1ADDRESS call now returning a 0 validator index for each validator from the depositing address that is waiting in the deposit queue.

## Task

Figure out a way to fix this. Probably needs to be fixed by beacon chain but we also would need to make adjustments.



Discussion:

Resolving patch:
diff --git a/rotkehlchen/chain/ethereum/eth2.py b/rotkehlchen/chain/ethereum/eth2.py
--- a/rotkehlchen/chain/ethereum/eth2.py
+++ b/rotkehlchen/chain/ethereum/eth2.py
@@ -192,8 +192,15 @@ def get_eth2_balances(
 
         address_to_validators[address] = validators
         for validator in validators:
-            validator_indices.append(validator.validator_index)
-            index_to_address[validator.validator_index] = address
+            if validator.validator_index is not None:
+                validator_indices.append(validator.validator_index)
+                index_to_address[validator.validator_index] = address
+            else:
+                # Validator is early in depositing, and no index is known yet.
+                # Simply count 32 ETH balance for them
+                balance_mapping[address] += Balance(
+                    amount=FVal('32'), usd_value=FVal('32') * usd_price,
+                )
 
     # Get current balance of all validator indices
     performance = beaconchain.get_performance(validator_indices)
@@ -202,6 +209,7 @@ def get_eth2_balances(
         balance_mapping[index_to_address[validator_index]] += Balance(amount, amount * usd_price)
 
     # The performance call does not return validators that are not active and are still depositing
+    # So for them let's just count 32 ETH
     depositing_indices = set(index_to_address.keys()) - set(performance.keys())
     for index in depositing_indices:
         balance_mapping[index_to_address[index]] += Balance(
@@ -222,17 +230,29 @@ def get_eth2_details(
     indices = []
     index_to_address = {}
     index_to_pubkey = {}
+    result = []
     assert beaconchain.db is not None, 'Beaconchain db should be populated'
-    # and for each address get the validator info (to get the index) -- this could be avoided
+
     for address in addresses:
         validators = beaconchain.get_eth1_address_validators(address)
         for validator in validators:
+            if validator.validator_index is None:
+                # for validators that are so early in the depositing queue that no
+                # validator index is confirmed yet let's return only the most basic info
+                result.append(ValidatorDetails(
+                    validator_index=None,
+                    public_key=validator.public_key,
+                    eth1_depositor=address,
+                    performance=DEPOSITING_VALIDATOR_PERFORMANCE,
+                    daily_stats=[],
+                ))
+                continue
+
             index_to_address[validator.validator_index] = address
             index_to_pubkey[validator.validator_index] = validator.public_key
             indices.append(validator.validator_index)
 
     # Get current balance of all validator indices
-    result = []
     performance_result = beaconchain.get_performance(list(indices))
     for validator_index, entry in performance_result.items():
         stats = get_validator_daily_stats(
diff --git a/rotkehlchen/chain/ethereum/typing.py b/rotkehlchen/chain/ethereum/typing.py
--- a/rotkehlchen/chain/ethereum/typing.py
+++ b/rotkehlchen/chain/ethereum/typing.py
@@ -84,7 +84,7 @@ def endpoint(self, own_rpc_endpoint: str) -> str:
 # Ethereum 2 stuff. Perhaps on its own file at some point?
 class ValidatorID(NamedTuple):
     # not using index due to : https://github.com/python/mypy/issues/9043
-    validator_index: int
+    validator_index: Optional[int]  # may be null if the index is not yet determined
     public_key: str
 
 
@@ -267,7 +267,7 @@ def serialize(self, eth_usd_price: FVal) -> Dict[str, Dict[str, str]]:
 
 
 class ValidatorDetails(NamedTuple):
-    validator_index: int
+    validator_index: Optional[int]
     public_key: str
     eth1_depositor: ChecksumEthAddress
     performance: ValidatorPerformance
diff --git a/rotkehlchen/chain/manager.py b/rotkehlchen/chain/manager.py
--- a/rotkehlchen/chain/manager.py
+++ b/rotkehlchen/chain/manager.py
@@ -1267,6 +1267,9 @@ def get_eth2_history_events(
             addresses=self.accounts.eth,
         )
         for entry in eth2_details:
+            if entry.validator_index is None:
+                continue  # don't query stats for validators without an index yet
+
             stats = get_validator_daily_stats(
                 db=self.database,
                 validator_index=entry.validator_index,


Test patch: