Repository: rotki/rotki

Issue:
Flaky test_remove_blockchain_accounts_alethio
## Problem Definition

rotkehlchen/tests/api/test_blockchain.py::test_remove_blockchain_accounts_alethio seems to be flaky in Travis OSX

```
_ test_remove_blockchain_accounts_alethio[True-owned_eth_tokens0-btc_accounts0-4] _
rotkehlchen_api_server = <rotkehlchen.api.server.APIServer object at 0x10a701080>
ethereum_accounts = ['0x90D6874944FeD19B599391c6fA4e04Fb06e2B63b', '0x345f6DEec950C7C465908417D855CA90c2639f06']
btc_accounts = ['1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2', '1CounterpartyXXXXXXXXXXXXXXXUWLpVr']
query_balances_before_first_modification = True
    @pytest.mark.parametrize('number_of_eth_accounts', [4])
    @pytest.mark.parametrize('btc_accounts', [[UNIT_BTC_ADDRESS1, UNIT_BTC_ADDRESS2]])
    @pytest.mark.parametrize('owned_eth_tokens', [[A_RDN]])
    @pytest.mark.parametrize('query_balances_before_first_modification', [True, False])
    def test_remove_blockchain_accounts_alethio(
            rotkehlchen_api_server,
            ethereum_accounts,
            btc_accounts,
            query_balances_before_first_modification,
    ):
        """Test that the endpoint removing blockchain accounts works properly when using alethio"""
        _remove_blockchain_accounts_test_start(
            api_server=rotkehlchen_api_server,
            query_balances_before_first_modification=query_balances_before_first_modification,
            ethereum_accounts=ethereum_accounts,
            btc_accounts=btc_accounts,
            use_alethio=True,
>           async_query=False,
        )
rotkehlchen/tests/api/test_blockchain.py:1575: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
rotkehlchen/tests/api/test_blockchain.py:1373: in _remove_blockchain_accounts_test_start
    also_btc=query_balances_before_first_modification,
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
rotki = <rotkehlchen.rotkehlchen.Rotkehlchen object at 0x10a5e2ac8>
json_data = {'message': '', 'result': {'per_account': {'BTC': {'1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2': {'amount': '0.03000000', 'usd...2000000'}, 'ETH': {'amount': '6E-12', 'usd_value': '9.762E-10'}, 'RDN': {'amount': '0E-11', 'usd_value': '3.15E-14'}}}}
eth_accounts = ['0x90D6874944FeD19B599391c6fA4e04Fb06e2B63b', '0x345f6DEec950C7C465908417D855CA90c2639f06']
eth_balances = ['2000000', '4000000'], token_balances = {'RDN': ['0', '0']}
also_btc = True, totals_only = False
    def assert_eth_balances_result(
            rotki: Rotkehlchen,
            json_data: Dict[str, Any],
            eth_accounts: List[str],
            eth_balances: List[str],
            token_balances: Dict[str, List[str]],
            also_btc: bool,
            totals_only: bool = False,
    ) -> None:
        """Asserts for correct ETH blockchain balances when mocked in tests
    
        If totals_only is given then this is a query for all balances so only the totals are shown
        """
        result = json_data['result']
        if not totals_only:
            per_account = result['per_account']
            if also_btc:
                assert len(per_account) == 2
            else:
                assert len(per_account) == 1
            per_account = per_account['ETH']
            assert len(per_account) == len(eth_accounts)
            for idx, account in enumerate(eth_accounts):
                expected_amount = from_wei(FVal(eth_balances[idx]))
                amount = FVal(per_account[account]['assets']['ETH']['amount'])
                usd_value = FVal(per_account[account]['assets']['ETH']['usd_value'])
                assert amount == expected_amount
                if amount == ZERO:
                    assert usd_value == ZERO
                else:
                    assert usd_value > ZERO
                have_tokens = False
                for symbol, balances in token_balances.items():
                    expected_token_amount = FVal(balances[idx])
                    if expected_token_amount == ZERO:
                        msg = f'{account} should have no entry for {symbol}'
                        assert symbol not in per_account[account], msg
                    else:
                        have_tokens = True
                        token_amount = FVal(per_account[account]['assets'][symbol]['amount'])
                        usd_value = FVal(per_account[account]['assets'][symbol]['usd_value'])
                        assert token_amount == from_wei(expected_token_amount)
                        assert usd_value > ZERO
    
                account_total_usd_value = FVal(per_account[account]['total_usd_value'])
                if amount != ZERO or have_tokens:
                    assert account_total_usd_value > ZERO
                else:
                    assert account_total_usd_value == ZERO
    
        if totals_only:
            totals = result
        else:
            totals = result['totals']
    
        # Check our owned eth tokens here since the test may have changed their number
        expected_totals_num = 1 + len(rotki.chain_manager.owned_eth_tokens)
        if also_btc:
            assert len(totals) == expected_totals_num + 1
        else:
            assert len(totals) == expected_totals_num
    
        expected_total_eth = sum(from_wei(FVal(balance)) for balance in eth_balances)
        assert FVal(totals['ETH']['amount']) == expected_total_eth
        if expected_total_eth == ZERO:
            assert FVal(totals['ETH']['usd_value']) == ZERO
        else:
            assert FVal(totals['ETH']['usd_value']) > ZERO
    
        for symbol, balances in token_balances.items():
            if symbol not in rotki.chain_manager.owned_eth_tokens:
                # If the token got removed from the owned tokens in the test make sure
                # it's not in the totals anymore
                assert symbol not in totals
                continue
    
            expected_total_token = sum(from_wei(FVal(balance)) for balance in balances)
            assert FVal(totals[symbol]['amount']) == expected_total_token
            if expected_total_token == ZERO:
                msg = f"{FVal(totals[symbol]['usd_value'])} is not ZERO"
>               assert FVal(totals[symbol]['usd_value']) == ZERO, msg
E               AssertionError: 3.15E-14 is not ZERO
rotkehlchen/tests/utils/blockchain.py:337: AssertionError
```

I have not managed to reproduce yet locally

## Task

Find out if it's reproducible, why it may happen and fix it


Discussion:

Resolving patch:
diff --git a/rotkehlchen/chain/manager.py b/rotkehlchen/chain/manager.py
--- a/rotkehlchen/chain/manager.py
+++ b/rotkehlchen/chain/manager.py
@@ -685,12 +685,17 @@ def _query_ethereum_tokens_alethio(
                         usd_value=balance * token_usd_price[token],
                     )
                 else:
-                    self.totals[token] = Balance(
-                        amount=add_or_sub(self.totals[token].amount, balance),  # type: ignore
-                        usd_value=add_or_sub(  # type: ignore
+                    new_amount = add_or_sub(self.totals[token].amount, balance)  # type: ignore
+                    if new_amount == ZERO:
+                        new_usd_value = ZERO
+                    else:
+                        new_usd_value = add_or_sub(  # type: ignore
                             self.totals[token].usd_value,
                             balance * token_usd_price[token],
-                        ),
+                        )
+                    self.totals[token] = Balance(
+                        amount=new_amount,
+                        usd_value=new_usd_value,
                     )
 
     def _query_ethereum_tokens_normal(
@@ -781,12 +786,17 @@ def _query_ethereum_tokens_normal(
                     # Removing the only account that holds this token
                     self.totals[token] = Balance(amount=ZERO, usd_value=ZERO)
                 else:
-                    self.totals[token] = Balance(
-                        amount=add_or_sub(self.totals[token].amount, token_total),  # type: ignore
-                        usd_value=add_or_sub(  # type: ignore
+                    new_amount = add_or_sub(self.totals[token].amount, token_total)  # type: ignore
+                    if new_amount == ZERO:
+                        new_usd_value = ZERO
+                    else:
+                        new_usd_value = add_or_sub(  # type: ignore
                             self.totals[token].usd_value,
                             token_total * token_usd_price[token],
-                        ),
+                        )
+                    self.totals[token] = Balance(
+                        amount=new_amount,
+                        usd_value=new_usd_value,
                     )
 
     def query_ethereum_tokens(


Test patch: