Repository: rotki/rotki

Issue:
api/test_compound.py::test_query_compound_history is failing
## Problem Definition

rotkehlchen/tests/api/test_compound.py::test_query_compound_history is failing. Both in the CI and locally on develop.

```

2020-11-25T12:28:54.8552235Z =================================== FAILURES ===================================
2020-11-25T12:28:54.8592469Z _ test_query_compound_history[default_mock_price_value0-mocked_current_prices0-mocked_price_queries0-True-ethereum_modules0-ethereum_accounts0] _
2020-11-25T12:28:54.8594289Z 
2020-11-25T12:28:54.8595885Z rotkehlchen_api_server = <rotkehlchen.api.server.APIServer object at 0x7fec70e6f550>
2020-11-25T12:28:54.8600064Z ethereum_accounts = ['0x2B888954421b424C5D3D9Ce9bB67c9bD47537d12', '0xC440f3C87DC4B6843CABc413916220D4f4FeD117', '0xF59D4937BF1305856C3a267bB07791507a3377Ee', '0x65304d6aff5096472519ca86a6a1fea31cb47Ced']
2020-11-25T12:28:54.8601669Z 
2020-11-25T12:28:54.8602494Z     @pytest.mark.parametrize('ethereum_accounts', [TEST_ACCOUNTS])
2020-11-25T12:28:54.8603588Z     @pytest.mark.parametrize('ethereum_modules', [['compound']])
2020-11-25T12:28:54.8604653Z     @pytest.mark.parametrize('start_with_valid_premium', [True])
2020-11-25T12:28:54.8605809Z     @pytest.mark.parametrize('mocked_price_queries', [mocked_historical_prices])
2020-11-25T12:28:54.8607008Z     @pytest.mark.parametrize('mocked_current_prices', [mocked_current_prices])
2020-11-25T12:28:54.8608142Z     @pytest.mark.parametrize('default_mock_price_value', [FVal(1)])
2020-11-25T12:28:54.8609727Z     def test_query_compound_history(rotkehlchen_api_server, ethereum_accounts):  # pylint: disable=unused-argument  # noqa: E501
2020-11-25T12:28:54.8610778Z         """Check querying the compound history endpoint works. Uses real data"""
2020-11-25T12:28:54.8611595Z         rotki = rotkehlchen_api_server.rest_api.rotkehlchen
2020-11-25T12:28:54.8612380Z         setup = setup_balances(
2020-11-25T12:28:54.8612809Z             rotki,
2020-11-25T12:28:54.8613325Z             ethereum_accounts=ethereum_accounts,
2020-11-25T12:28:54.8614116Z             eth_balances=['1000000', '2000000', '33000030003', '42323213'],
2020-11-25T12:28:54.8614606Z             token_balances={},
2020-11-25T12:28:54.8615064Z             btc_accounts=None,
2020-11-25T12:28:54.8615805Z             original_queries=['zerion', 'logs', 'blocknobytime'],
2020-11-25T12:28:54.8616328Z         )
2020-11-25T12:28:54.8617088Z         # Since this test can be a bit slow we don't run both async and sync in the same test run
2020-11-25T12:28:54.8617909Z         # Instead we randomly choose one. Eventually both cases will be covered.
2020-11-25T12:28:54.8618650Z         async_query = random.choice([True, False])
2020-11-25T12:28:54.8619129Z     
2020-11-25T12:28:54.8619523Z         with ExitStack() as stack:
2020-11-25T12:28:54.8620155Z             # patch ethereum/etherscan to not autodetect tokens
2020-11-25T12:28:54.8620843Z             setup.enter_ethereum_patches(stack)
2020-11-25T12:28:54.8621478Z             response = requests.get(api_url_for(
2020-11-25T12:28:54.8622052Z                 rotkehlchen_api_server,
2020-11-25T12:28:54.8622670Z                 "compoundhistoryresource",
2020-11-25T12:28:54.8623453Z             ), json={'async_query': async_query})
2020-11-25T12:28:54.8623932Z             if async_query:
2020-11-25T12:28:54.8624464Z                 task_id = assert_ok_async_response(response)
2020-11-25T12:28:54.8625111Z                 # Timeout of 120 since this test can take a long time
2020-11-25T12:28:54.8625845Z                 outcome = wait_for_async_task(rotkehlchen_api_server, task_id, timeout=120)
2020-11-25T12:28:54.8626681Z                 assert outcome['message'] == ''
2020-11-25T12:28:54.8627350Z                 result = outcome['result']
2020-11-25T12:28:54.8627779Z             else:
2020-11-25T12:28:54.8628351Z                 result = assert_proper_response_with_result(response)
2020-11-25T12:28:54.8628885Z     
2020-11-25T12:28:54.8629259Z         assert len(result) == 5
2020-11-25T12:28:54.8629878Z         expected_events = process_result_list(EXPECTED_EVENTS)
2020-11-25T12:28:54.8630656Z         # Check only 22 first events, since this is how many there were in the time of
2020-11-25T12:28:54.8631628Z         # the writing of the test. Also don't check events for one of the addresses
2020-11-25T12:28:54.8632647Z         # as it's added later, has many events and it's only to see we handle repay correctly
2020-11-25T12:28:54.8633281Z         to_check_events = [
2020-11-25T12:28:54.8634237Z             x for x in result['events'] if x['address'] != '0x65304d6aff5096472519ca86a6a1fea31cb47Ced'
2020-11-25T12:28:54.8634917Z         ]
2020-11-25T12:28:54.8635396Z         assert to_check_events[:22] == expected_events
2020-11-25T12:28:54.8635953Z         # Check one repay event
2020-11-25T12:28:54.8636406Z         other_events = [
2020-11-25T12:28:54.8637442Z             x for x in result['events'] if x['address'] == '0x65304d6aff5096472519ca86a6a1fea31cb47Ced'
2020-11-25T12:28:54.8638125Z         ]
2020-11-25T12:28:54.8638759Z         assert other_events[12]['event_type'] == 'repay'
2020-11-25T12:28:54.8640120Z         expected_hash = '0x48a3e2ef8a746383deac34d74f2f0ea0451b2047701fbed4b9d769a782888eea'
2020-11-25T12:28:54.8641463Z         assert other_events[12]['tx_hash'] == expected_hash
2020-11-25T12:28:54.8642239Z         assert other_events[12]['value']['amount'] == '0.55064402'
2020-11-25T12:28:54.8642692Z     
2020-11-25T12:28:54.8643135Z         # Check interest profit mappings
2020-11-25T12:28:54.8644112Z         profit_0 = result['interest_profit']['0x2B888954421b424C5D3D9Ce9bB67c9bD47537d12']
2020-11-25T12:28:54.8645069Z         assert FVal(profit_0['DAI']['amount']) > FVal(9)
2020-11-25T12:28:54.8646143Z         profit_1 = result['interest_profit']['0xC440f3C87DC4B6843CABc413916220D4f4FeD117']
2020-11-25T12:28:54.8647205Z         assert FVal(profit_1['USDC']['amount']) > FVal(2)
2020-11-25T12:28:54.8648210Z         profit_2 = result['interest_profit']['0xF59D4937BF1305856C3a267bB07791507a3377Ee']
2020-11-25T12:28:54.8649153Z         assert FVal(profit_2['DAI']['amount']) > FVal('0.3')
2020-11-25T12:28:54.8649807Z     
2020-11-25T12:28:54.8650218Z         # Check debt loss mappings
2020-11-25T12:28:54.8771055Z         debt_0 = result['debt_loss']['0xC440f3C87DC4B6843CABc413916220D4f4FeD117']
2020-11-25T12:28:54.8772338Z         assert FVal(debt_0['cUSDC']['amount']) > FVal('84')
2020-11-25T12:28:54.8773104Z         assert FVal(debt_0['ETH']['amount']) > FVal('0.000012422')
2020-11-25T12:28:54.8773546Z     
2020-11-25T12:28:54.8774019Z         # Check liquidation profit mappings
2020-11-25T12:28:54.8775109Z         lprofit_0 = result['liquidation_profit']['0xC440f3C87DC4B6843CABc413916220D4f4FeD117']
2020-11-25T12:28:54.8776146Z         assert FVal(lprofit_0['ETH']['amount']) > FVal('0.000012')
2020-11-25T12:28:54.8776609Z     
2020-11-25T12:28:54.8777044Z         # Check rewards mappings
2020-11-25T12:28:54.8777998Z >       rewards_0 = result['rewards']['0xC440f3C87DC4B6843CABc413916220D4f4FeD117']
2020-11-25T12:28:54.8779157Z E       KeyError: '0xC440f3C87DC4B6843CABc413916220D4f4FeD117'
2020-11-25T12:28:54.8779691Z 
2020-11-25T12:28:54.8780208Z rotkehlchen/tests/api/test_compound.py:574: KeyError
```

## Task

Figure out why and fix it


Discussion:

Resolving patch:
diff --git a/rotkehlchen/chain/ethereum/aave/__init__.py b/rotkehlchen/chain/ethereum/aave/__init__.py
--- a/rotkehlchen/chain/ethereum/aave/__init__.py
+++ b/rotkehlchen/chain/ethereum/aave/__init__.py
@@ -110,6 +110,8 @@ def _get_balances(
             lending_map = {}
             borrowing_map = {}
             for balance_entry in balance_entries:
+                # Aave also has "Aave • Staking" and "Aave • Uniswap Market" but
+                # here we are only querying the balances in the lending protocol
                 if balance_entry.protocol.name != 'Aave':
                     continue
 
diff --git a/rotkehlchen/chain/ethereum/compound.py b/rotkehlchen/chain/ethereum/compound.py
--- a/rotkehlchen/chain/ethereum/compound.py
+++ b/rotkehlchen/chain/ethereum/compound.py
@@ -176,7 +176,7 @@ def get_balances(
             borrowing_map = {}
             rewards_map = {}
             for balance_entry in balance_entries:
-                if balance_entry.protocol.name != 'Compound':
+                if balance_entry.protocol.name not in ('Compound Governance', 'Compound'):
                     continue
 
                 entry = balance_entry.base_balance
@@ -188,7 +188,11 @@ def get_balances(
                     )
                     continue
 
-                if entry.token_address == A_COMP.ethereum_address:
+                unclaimed_comp_rewards = (
+                    entry.token_address == A_COMP.ethereum_address and
+                    balance_entry.protocol.name == 'Compound Governance'
+                )
+                if unclaimed_comp_rewards:
                     rewards_map[A_COMP] = CompoundBalance(
                         balance_type=BalanceType.ASSET,
                         balance=entry.balance,
diff --git a/rotkehlchen/chain/manager.py b/rotkehlchen/chain/manager.py
--- a/rotkehlchen/chain/manager.py
+++ b/rotkehlchen/chain/manager.py
@@ -75,13 +75,13 @@
 # Mapping to token symbols to ignore. True means all
 DEFI_PROTOCOLS_TO_SKIP_ASSETS = {
     # aTokens are already detected at token balance queries
-    'Aave': True,  # None means all
+    'Aave': True,  # True means all
     # cTokens are already detected at token balance queries
-    'Compound': True,  # None means all
+    'Compound': True,  # True means all
     # Chitoken is in our all_assets.json
-    'Chi Gastoken by 1inch': True,  # None means all
+    'Chi Gastoken by 1inch': True,  # True means all
     # yearn vault balances are detected by the yTokens
-    'yearn.finance • Vaults': True,
+    'yearn.finance • Vaults': True,  # True means all
     # Synthetix SNX token is in all_assets.json
     'Synthetix': ['SNX'],
 }


Test patch:
diff --git a/rotkehlchen/tests/unit/test_zerion.py b/rotkehlchen/tests/unit/test_zerion.py
--- a/rotkehlchen/tests/unit/test_zerion.py
+++ b/rotkehlchen/tests/unit/test_zerion.py
@@ -36,3 +36,96 @@ def test_query_all_protocol_balances_for_account(
     assert len(errors) == 0
     warnings = function_scope_messages_aggregator.consume_warnings()
     assert len(warnings) == 0
+
+
+KNOWN_ZERION_PROTOCOL_NAMES = (
+    'Curve • Vesting',
+    'Curve • Liquidity Gauges',
+    'ygov.finance (v1)',
+    'ygov.finance (v2)',
+    'mStable • Staking',
+    'Swerve • Liquidity Gauges',
+    'Pickle Finance • Farms',
+    'Pickle Finance • Staking',
+    'Aave • Staking',
+    'C.R.E.A.M. • Staking',
+    'Compound Governance',
+    'zlot.finance',
+    'FinNexus',
+    'Pickle Finance',
+    'DODO',
+    'Berezka',
+    'bZx',
+    'C.R.E.A.M.',
+    'Swerve',
+    'SashimiSwap',
+    'Harvest',
+    'KIMCHI',
+    'SushiSwap',
+    'Nexus Mutual',
+    'Mooniswap',
+    'Matic',
+    'Aragon',
+    'Melon',
+    'yearn.finance • Vaults',
+    'KeeperDAO',
+    'mStable',
+    'KyberDAO',
+    'DDEX • Spot',
+    'DDEX • Margin',
+    'DDEX • Lending',
+    'Ampleforth',
+    'Maker Governance',
+    'Gnosis Protocol',
+    'Chi Gastoken by 1inch',
+    'Idle • Risk-Adjusted',
+    'Aave • Uniswap Market',
+    'Uniswap V2',
+    'PieDAO',
+    'Multi-Collateral Dai',
+    'Bancor',
+    'DeFi Money Market',
+    'TokenSets',
+    '0x Staking',
+    'Uniswap V1',
+    'Synthetix',
+    'PoolTogether',
+    'Dai Savings Rate',
+    'Chai',
+    'iearn.finance (v3)',
+    'iearn.finance (v2)',
+    'Idle',
+    'dYdX',
+    'Curve',
+    'Compound',
+    'Balancer',
+    'Aave',
+)
+
+
+def test_protocol_names_are_known(
+        ethereum_manager,
+        function_scope_messages_aggregator,
+        inquirer,  # pylint: disable=unused-argument
+):
+    zerion = Zerion(ethereum_manager, function_scope_messages_aggregator)
+    protocol_names = zerion.contract.call(
+        ethereum=zerion.ethereum,
+        method_name='getProtocolNames',
+        arguments=[],
+    )
+
+    # Make sure that none of the already known names has changed. If it has changed.
+    # If it has that may cause trouble as we saw in: https://github.com/rotki/rotki/issues/1803
+    for expected_name in KNOWN_ZERION_PROTOCOL_NAMES:
+        msg = f'Could not find "{expected_name}" in the zerion protocol names'
+        assert expected_name in protocol_names, msg
+
+    # informative pass with some warnings if a protocol is added by zerion we don't know about
+    # We should check those warnings from time to time and add them to the known
+    # protocols and add an icon for them among other things
+    for name in protocol_names:
+        if name not in KNOWN_ZERION_PROTOCOL_NAMES:
+            test_warnings.warn(
+                UserWarning(f'Unknown protocol "{name}" seen in Zerion protocol names'),
+            )