Repository: rotki/rotki

Issue:
Borrow and Lend events should have both an amount and usdValue
## Abstract

Currently our detailed defi endpoints
```
/api/1/blockchains/ETH/modules/makerdao/dsrhistory
/api/(version)/blockchains/ETH/modules/makerdao/vaultdetails
```

provide "amount" at the event/transaction level, but not usdValue. We should also include usdValue at the event level. This is for the following reasons:
a) Not every protocol will necessarily have an underlying stablecoin for borrowing/lending, thus the amount and usdvalue might not be pegged at a constant ratio
b) Even in the case of DAI (or dai-equivalents), the ratio is not actually 1:1 and this matters for taxable events purposes
c) Even in the case of a stable-coin peg, the peg might not be to USD (and be to EUR, or RMB, etc.) therefore we still need the transaction value at the time of the movement/event in fiat in order to be able to convert to the user's main currency


Discussion:

Resolving patch:
diff --git a/rotkehlchen/chain/ethereum/makerdao.py b/rotkehlchen/chain/ethereum/makerdao.py
--- a/rotkehlchen/chain/ethereum/makerdao.py
+++ b/rotkehlchen/chain/ethereum/makerdao.py
@@ -12,7 +12,7 @@
 from rotkehlchen.assets.asset import Asset
 from rotkehlchen.chain.ethereum.manager import EthereumManager, address_to_bytes32
 from rotkehlchen.constants import ZERO
-from rotkehlchen.constants.assets import A_USD
+from rotkehlchen.constants.assets import A_DAI, A_USD
 from rotkehlchen.constants.ethereum import (
     MAKERDAO_BAT_JOIN,
     MAKERDAO_CAT,
@@ -38,9 +38,10 @@
 )
 from rotkehlchen.fval import FVal
 from rotkehlchen.history import PriceHistorian
+from rotkehlchen.inquirer import Inquirer
 from rotkehlchen.premium.premium import Premium
 from rotkehlchen.serialization.deserialize import deserialize_blocknumber
-from rotkehlchen.typing import ChecksumEthAddress, Timestamp
+from rotkehlchen.typing import ChecksumEthAddress, Price, Timestamp
 from rotkehlchen.user_messages import MessagesAggregator
 from rotkehlchen.utils.interfaces import EthereumModule
 from rotkehlchen.utils.misc import hex_or_bytes_to_int, ts_now
@@ -107,6 +108,7 @@ def __str__(self) -> str:
 class VaultEvent(NamedTuple):
     event_type: VaultEventType
     amount: FVal
+    amount_usd_value: FVal
     timestamp: Timestamp
     tx_hash: str
 
@@ -120,6 +122,8 @@ class MakerDAOVault(NamedTuple):
     collateral_asset: Asset
     # The amount of collateral tokens locked
     collateral_amount: FVal
+    # The USD value of collateral locked, given the current price according to the price feed
+    collateral_usd_value: FVal
     # amount of DAI drawn
     debt_value: FVal
     # The current collateralization_ratio of the Vault. None if nothing is locked in.
@@ -128,8 +132,6 @@ class MakerDAOVault(NamedTuple):
     liquidation_ratio: FVal
     # The USD price of collateral at which the Vault becomes unsafe. None if nothing is locked in.
     liquidation_price: Optional[FVal]
-    # The USD value of collateral locked, given the current price according to the price feed
-    collateral_usd_value: FVal
     urn: ChecksumEthAddress
     stability_fee: FVal
 
@@ -227,9 +229,12 @@ class DSRMovement:
     address: ChecksumEthAddress
     # normalized balance in DSR DAI (RAD precision 10**45)
     normalized_balance: int
+    # gain so far in DSR DAI (RAD precision 10**45)
     gain_so_far: int = field(init=False)
+    gain_so_far_usd_value: FVal = field(init=False)
     # dai balance in DSR DAI (RAD precision 10**45)
     amount: int
+    amount_usd_value: FVal
     block_number: int
     timestamp: Timestamp
 
@@ -243,17 +248,21 @@ class DSRCurrentBalances(NamedTuple):
 class DSRAccountReport(NamedTuple):
     movements: List[DSRMovement]
     gain_so_far: int
+    gain_so_far_usd_value: FVal
 
     def serialize(self) -> Dict[str, Any]:
         serialized_report = {
             'gain_so_far': str(_dsrdai_to_dai(self.gain_so_far)),
+            'gain_so_far_usd_value': str(self.gain_so_far_usd_value),
             'movements': [],
         }
         for movement in self.movements:
             serialized_movement = {
                 'movement_type': movement.movement_type,
                 'gain_so_far': str(_dsrdai_to_dai(movement.gain_so_far)),
+                'gain_so_far_usd_value': str(movement.gain_so_far_usd_value),
                 'amount': str(_dsrdai_to_dai(movement.amount)),
+                'amount_usd_value': str(movement.amount_usd_value),
                 'block_number': movement.block_number,
                 'timestamp': movement.timestamp,
             }
@@ -266,6 +275,28 @@ def _dsrdai_to_dai(value: Union[int, FVal]) -> FVal:
     return FVal(value / FVal(RAD))
 
 
+def _query_usd_price_or_use_default(
+        asset: Asset,
+        time: Timestamp,
+        default_value: FVal,
+        location: str,
+) -> Price:
+    try:
+        usd_price = PriceHistorian().query_historical_price(
+            from_asset=asset,
+            to_asset=A_USD,
+            timestamp=time,
+        )
+    except RemoteError:
+        log.error(
+            f'Could not query usd price for {asset.identifier} when processing '
+            f'{location}. Assuming price of ${str(default_value)}',
+        )
+        usd_price = Price(default_value)
+
+    return usd_price
+
+
 class MakerDAO(EthereumModule):
     """Class to manage MakerDAO related stuff such as DSR and CDPs/Vaults"""
 
@@ -527,10 +558,18 @@ def _query_vault_details(
                 asset_symbol=asset_symbol,
                 amount=hex_or_bytes_to_int(event['topics'][3]),
             )
+            timestamp = self.ethereum.get_event_timestamp(event)
+            usd_price = _query_usd_price_or_use_default(
+                asset=vault.collateral_asset,
+                time=timestamp,
+                default_value=ZERO,
+                location='vault collateral deposit',
+            )
             vault_events.append(VaultEvent(
                 event_type=VaultEventType.DEPOSIT_COLLATERAL,
                 amount=amount,
-                timestamp=self.ethereum.get_event_timestamp(event),
+                amount_usd_value=amount * usd_price,
+                timestamp=timestamp,
                 tx_hash=tx_hash,
             ))
 
@@ -555,10 +594,18 @@ def _query_vault_details(
                 asset_symbol=asset_symbol,
                 amount=hex_or_bytes_to_int(event['topics'][3]),
             )
+            timestamp = self.ethereum.get_event_timestamp(event)
+            usd_price = _query_usd_price_or_use_default(
+                asset=vault.collateral_asset,
+                time=timestamp,
+                default_value=ZERO,
+                location='vault collateral withdrawal',
+            )
             vault_events.append(VaultEvent(
                 event_type=VaultEventType.WITHDRAW_COLLATERAL,
                 amount=amount,
-                timestamp=self.ethereum.get_event_timestamp(event),
+                amount_usd_value=amount * usd_price,
+                timestamp=timestamp,
                 tx_hash=event['transactionHash'],
             ))
 
@@ -586,10 +633,18 @@ def _query_vault_details(
                 asset_symbol='DAI',
                 amount=given_amount,
             )
+            timestamp = self.ethereum.get_event_timestamp(event)
+            usd_price = _query_usd_price_or_use_default(
+                asset=A_DAI,
+                time=timestamp,
+                default_value=FVal(1),
+                location='vault debt generation',
+            )
             vault_events.append(VaultEvent(
                 event_type=VaultEventType.GENERATE_DEBT,
                 amount=amount,
-                timestamp=self.ethereum.get_event_timestamp(event),
+                amount_usd_value=amount * usd_price,
+                timestamp=timestamp,
                 tx_hash=event['transactionHash'],
             ))
 
@@ -617,10 +672,20 @@ def _query_vault_details(
                 # it seems there is a zero DAI value transfer from the urn when
                 # withdrawing ETH. So we should ignore these as events
                 continue
+
+            timestamp = self.ethereum.get_event_timestamp(event)
+            usd_price = _query_usd_price_or_use_default(
+                asset=A_DAI,
+                time=timestamp,
+                default_value=FVal(1),
+                location='vault debt payback',
+            )
+
             vault_events.append(VaultEvent(
                 event_type=VaultEventType.PAYBACK_DEBT,
                 amount=amount,
-                timestamp=self.ethereum.get_event_timestamp(event),
+                amount_usd_value=amount * usd_price,
+                timestamp=timestamp,
                 tx_hash=event['transactionHash'],
             ))
 
@@ -646,15 +711,18 @@ def _query_vault_details(
             )
             timestamp = self.ethereum.get_event_timestamp(event)
             sum_liquidation_amount += amount
-            usd_price = PriceHistorian().query_historical_price(
-                from_asset=vault.collateral_asset,
-                to_asset=A_USD,
-                timestamp=timestamp,
+            usd_price = _query_usd_price_or_use_default(
+                asset=vault.collateral_asset,
+                time=timestamp,
+                default_value=ZERO,
+                location='vault collateral liquidation',
             )
-            sum_liquidation_usd += amount * usd_price
+            amount_usd_value = amount * usd_price
+            sum_liquidation_usd += amount_usd_value
             vault_events.append(VaultEvent(
                 event_type=VaultEventType.LIQUIDATION,
                 amount=amount,
+                amount_usd_value=amount_usd_value,
                 timestamp=timestamp,
                 tx_hash=event['transactionHash'],
             ))
@@ -799,6 +867,9 @@ def get_current_dsr(self) -> DSRCurrentBalances:
                     method_name='pie',
                     arguments=[proxy],
                 )
+                if guy_slice == 0:
+                    # no current DSR balance for this proxy
+                    continue
                 chi = self.ethereum.call_contract(
                     contract_address=MAKERDAO_POT.address,
                     abi=MAKERDAO_POT.abi,
@@ -813,7 +884,6 @@ def get_current_dsr(self) -> DSRCurrentBalances:
                 abi=MAKERDAO_POT.abi,
                 method_name='dsr',
             )
-
             # Calculation is from here:
             # https://docs.makerdao.com/smart-contract-modules/rates-module#a-note-on-setting-rates
             current_dsr_percentage = ((FVal(current_dsr / RAY) ** 31622400) % 1) * 100
@@ -924,14 +994,22 @@ def _historical_dsr_for_account(
                 )
                 continue
 
+            timestamp = self.ethereum.get_event_timestamp(join_event)
+            usd_price = _query_usd_price_or_use_default(
+                asset=A_DAI,
+                time=timestamp,
+                default_value=FVal(1),
+                location='DSR deposit',
+            )
             movements.append(
                 DSRMovement(
                     movement_type='deposit',
                     address=account,
                     normalized_balance=wad_val,
                     amount=dai_value,
+                    amount_usd_value=_dsrdai_to_dai(dai_value) * usd_price,
                     block_number=deserialize_blocknumber(join_event['blockNumber']),
-                    timestamp=self.ethereum.get_event_timestamp(join_event),
+                    timestamp=timestamp,
                 ),
             )
 
@@ -975,14 +1053,22 @@ def _historical_dsr_for_account(
                 )
                 continue
 
+            timestamp = self.ethereum.get_event_timestamp(exit_event)
+            usd_price = _query_usd_price_or_use_default(
+                asset=A_DAI,
+                time=timestamp,
+                default_value=FVal(1),
+                location='DSR withdrawal',
+            )
             movements.append(
                 DSRMovement(
                     movement_type='withdrawal',
                     address=account,
                     normalized_balance=wad_val,
                     amount=dai_value,
+                    amount_usd_value=_dsrdai_to_dai(dai_value) * usd_price,
                     block_number=deserialize_blocknumber(exit_event['blockNumber']),
-                    timestamp=self.ethereum.get_event_timestamp(exit_event),
+                    timestamp=timestamp,
                 ),
             )
 
@@ -995,13 +1081,22 @@ def _historical_dsr_for_account(
                 # skip 0 amount/balance movements. Consider last gain as last gain so far.
                 if idx == 0:
                     m.gain_so_far = 0
+                    m.gain_so_far_usd_value = ZERO
                 else:
                     m.gain_so_far = movements[idx - 1].gain_so_far
+                    m.gain_so_far_usd_value = movements[idx - 1].gain_so_far_usd_value
                 continue
 
             current_chi = FVal(m.amount) / FVal(m.normalized_balance)
             gain_so_far = normalized_balance * current_chi - amount_in_dsr
             m.gain_so_far = gain_so_far.to_int(exact=False)
+            usd_price = _query_usd_price_or_use_default(
+                asset=A_DAI,
+                time=m.timestamp,
+                default_value=FVal(1),
+                location='DSR movement',
+            )
+            m.gain_so_far_usd_value = _dsrdai_to_dai(m.gain_so_far) * usd_price
             if m.movement_type == 'deposit':
                 normalized_balance += m.normalized_balance
                 amount_in_dsr += m.amount
@@ -1017,8 +1112,26 @@ def _historical_dsr_for_account(
         normalized_balance = normalized_balance * chi
         amount_in_dsr = amount_in_dsr
         gain = normalized_balance - amount_in_dsr
-
-        return DSRAccountReport(movements=movements, gain_so_far=gain)
+        try:
+            current_dai_price = Inquirer().find_usd_price(A_DAI)
+        except RemoteError:
+            current_dai_price = Price(FVal(1))
+
+        # Calculate the total gain so far in USD
+        unaccounted_gain = _dsrdai_to_dai(gain)
+        last_usd_value = ZERO
+        last_dai_gain = 0
+        if len(movements) != 0:
+            last_usd_value = movements[-1].gain_so_far_usd_value
+            last_dai_gain = movements[-1].gain_so_far
+        unaccounted_gain = _dsrdai_to_dai(gain - last_dai_gain)
+        gain_so_far_usd_value = unaccounted_gain * current_dai_price + last_usd_value
+
+        return DSRAccountReport(
+            movements=movements,
+            gain_so_far=gain,
+            gain_so_far_usd_value=gain_so_far_usd_value,
+        )
 
     def get_historical_dsr(self) -> Dict[ChecksumEthAddress, DSRAccountReport]:
         with self.lock:
@@ -1026,6 +1139,10 @@ def get_historical_dsr(self) -> Dict[ChecksumEthAddress, DSRAccountReport]:
             reports = {}
             for account, proxy in proxy_mappings.items():
                 report = self._historical_dsr_for_account(account, proxy)
+                if len(report.movements) == 0:
+                    # This proxy has never had any DSR events
+                    continue
+
                 reports[account] = report
 
         return reports


Test patch:
diff --git a/rotkehlchen/tests/api/test_makerdao_dsr.py b/rotkehlchen/tests/api/test_makerdao_dsr.py
--- a/rotkehlchen/tests/api/test_makerdao_dsr.py
+++ b/rotkehlchen/tests/api/test_makerdao_dsr.py
@@ -7,6 +7,7 @@
 import requests
 
 from rotkehlchen.chain.ethereum.makerdao import _dsrdai_to_dai
+from rotkehlchen.constants.assets import A_DAI
 from rotkehlchen.constants.ethereum import (
     MAKERDAO_DAI_JOIN,
     MAKERDAO_POT,
@@ -29,6 +30,32 @@
 from rotkehlchen.tests.utils.mock import MockResponse
 from rotkehlchen.typing import ChecksumEthAddress
 
+mocked_prices = {
+    'DAI': {
+        'USD': {
+            1582699808: FVal('1.002'),
+            1584024065: FVal('1.002'),
+            1585286480: FVal('1.023'),
+            1585286769: FVal('1.023'),
+            1585290263: FVal('1.023'),
+            1586785858: FVal('1.024'),
+            1586788927: FVal('1.024'),
+            1586805054: FVal('1.024'),
+            1587539880: FVal('1.016'),
+            1587539889: FVal('1.016'),
+            1587910979: FVal('1.015'),
+            1588174425: FVal('1.014'),
+            1588664698: FVal('1.006'),
+            1588696496: FVal('1.006'),
+            1588964616: FVal('1.006'),
+            1589989097: FVal('1.003'),
+            1590042891: FVal('1.001'),
+            1590044118: FVal('1.001'),
+            1590521879: FVal('1.003'),
+        },
+    },
+}
+
 TEST_LATEST_BLOCKNUMBER = 9540749
 TEST_LATEST_BLOCKNUMBER_HEX = hex(TEST_LATEST_BLOCKNUMBER)
 
@@ -293,10 +320,13 @@ def setup_tests_for_dsr(
     dsr_history_response = {
         account1: {
             'gain_so_far': _dsrdai_to_dai(account1_gain_so_far),
+            'gain_so_far_usd_value': _dsrdai_to_dai(account1_gain_so_far),
             'movements': [{
                 'movement_type': 'deposit',
                 'gain_so_far': '0.0',
+                'gain_so_far_usd_value': '0.0',
                 'amount': _dsrdai_to_dai(account1_deposit1),
+                'amount_usd_value': _dsrdai_to_dai(account1_deposit1),
                 'block_number': params.account1_join1_blocknumber,
                 'timestamp': blocknumber_to_timestamp(params.account1_join1_blocknumber),
             }, {
@@ -305,7 +335,12 @@ def setup_tests_for_dsr(
                     params.account1_join1_normalized_balance * params.account1_join2_chi -
                     account1_deposit1,
                 ),
+                'gain_so_far_usd_value': _dsrdai_to_dai(
+                    params.account1_join1_normalized_balance * params.account1_join2_chi -
+                    account1_deposit1,
+                ),
                 'amount': _dsrdai_to_dai(account1_deposit2),
+                'amount_usd_value': _dsrdai_to_dai(account1_deposit2),
                 'block_number': params.account1_join2_blocknumber,
                 'timestamp': blocknumber_to_timestamp(params.account1_join2_blocknumber),
             }, {
@@ -317,17 +352,28 @@ def setup_tests_for_dsr(
                     ) * params.account1_exit1_chi -
                     (account1_deposit1 + account1_deposit2),
                 ),
+                'gain_so_far_usd_value': _dsrdai_to_dai(
+                    (
+                        params.account1_join1_normalized_balance +
+                        params.account1_join2_normalized_balance
+                    ) * params.account1_exit1_chi -
+                    (account1_deposit1 + account1_deposit2),
+                ),
                 'amount': _dsrdai_to_dai(account1_withdrawal1),
+                'amount_usd_value': _dsrdai_to_dai(account1_withdrawal1),
                 'block_number': params.account1_exit1_blocknumber,
                 'timestamp': blocknumber_to_timestamp(params.account1_exit1_blocknumber),
             }],
         },
         account2: {
             'gain_so_far': _dsrdai_to_dai(account2_gain_so_far),
+            'gain_so_far_usd_value': _dsrdai_to_dai(account2_gain_so_far),
             'movements': [{
                 'movement_type': 'deposit',
                 'gain_so_far': '0.0',
+                'gain_so_far_usd_value': '0.0',
                 'amount': _dsrdai_to_dai(account2_deposit1),
+                'amount_usd_value': _dsrdai_to_dai(account2_deposit1),
                 'block_number': params.account2_join1_blocknumber,
                 'timestamp': blocknumber_to_timestamp(params.account2_join1_blocknumber),
             }],
@@ -456,9 +502,12 @@ def assert_dsr_history_result_is_correct(result: Dict[str, Any], setup: DSRTestS
 @pytest.mark.parametrize('number_of_eth_accounts', [3])
 @pytest.mark.parametrize('ethereum_modules', [['makerdao']])
 @pytest.mark.parametrize('start_with_valid_premium', [True])
+@pytest.mark.parametrize('default_mock_price_value', [FVal(1)])
+@pytest.mark.parametrize('mocked_current_prices', [{A_DAI: FVal(1)}])
 def test_query_historical_dsr(
         rotkehlchen_api_server,
         ethereum_accounts,
+        inquirer,  # pylint: disable=unused-argument
 ):
     """Test DSR history is correctly queried
 
@@ -493,9 +542,12 @@ def test_query_historical_dsr(
 @pytest.mark.parametrize('number_of_eth_accounts', [3])
 @pytest.mark.parametrize('ethereum_modules', [['makerdao']])
 @pytest.mark.parametrize('start_with_valid_premium', [True])
+@pytest.mark.parametrize('default_mock_price_value', [FVal(1)])
+@pytest.mark.parametrize('mocked_current_prices', [{A_DAI: FVal(1)}])
 def test_query_historical_dsr_async(
         rotkehlchen_api_server,
         ethereum_accounts,
+        inquirer,  # pylint: disable=unused-argument
 ):
     rotki = rotkehlchen_api_server.rest_api.rotkehlchen
     account1 = ethereum_accounts[0]
@@ -522,9 +574,12 @@ def test_query_historical_dsr_async(
 @pytest.mark.parametrize('number_of_eth_accounts', [1])
 @pytest.mark.parametrize('ethereum_modules', [['makerdao']])
 @pytest.mark.parametrize('start_with_valid_premium', [True])
+@pytest.mark.parametrize('default_mock_price_value', [FVal(1)])
+@pytest.mark.parametrize('mocked_current_prices', [{A_DAI: FVal(1)}])
 def test_query_historical_dsr_with_a_zero_withdrawal(
         rotkehlchen_api_server,
         ethereum_accounts,
+        inquirer,  # pylint: disable=unused-argument
 ):
     """Test DSR for an account that was opened while DSR is 0 and made a 0 DAI withdrawal
 
@@ -576,26 +631,57 @@ def mock_get_logs(
     assert json_data['message'] == ''
     result = json_data['result'][ethereum_accounts[0]]
     assert FVal(result['gain_so_far']) == ZERO
+    assert FVal(result['gain_so_far_usd_value']) == ZERO
     movements = result['movements']
     expected_movements = [{
         'movement_type': 'deposit',
         'gain_so_far': ZERO,
+        'gain_so_far_usd_value': ZERO,
         'amount': FVal('79'),
+        'amount_usd_value': FVal('79'),
         'block_number': 9953028,
         'timestamp': 1587970286,
     }, {
         'movement_type': 'withdrawal',
         'gain_so_far': ZERO,
+        'gain_so_far_usd_value': ZERO,
         'amount': FVal('79'),
+        'amount_usd_value': FVal('79'),
         'block_number': 9968906,
         'timestamp': 1588182567,
     }, {
         'movement_type': 'withdrawal',
         'gain_so_far': ZERO,
+        'gain_so_far_usd_value': ZERO,
         'amount': ZERO,
+        'amount_usd_value': ZERO,
         'block_number': 9968906,
         'timestamp': 1588182567,
     }]
     assert_serialized_lists_equal(movements, expected_movements)
     errors = rotki.msg_aggregator.consume_errors()
     assert len(errors) == 0
+
+
+@pytest.mark.parametrize('ethereum_accounts', [['0xf753beFE986e8Be8EBE7598C9d2b6297D9DD6662']])
+@pytest.mark.parametrize('ethereum_modules', [['makerdao']])
+@pytest.mark.parametrize('start_with_valid_premium', [True])
+def test_dsr_for_account_with_proxy_but_no_dsr(
+        rotkehlchen_api_server,
+):
+    """Assure that an account with a DSR proxy but no DSR balance isn't returned in the balances"""
+    response = requests.get(api_url_for(
+        rotkehlchen_api_server,
+        "makerdaodsrbalanceresource",
+    ))
+    assert_proper_response(response)
+    json_data = response.json()
+    assert json_data['message'] == ''
+    assert len(json_data['result']['balances']) == 0
+    response = requests.get(api_url_for(
+        rotkehlchen_api_server,
+        "makerdaodsrhistoryresource",
+    ))
+    json_data = response.json()
+    assert json_data['message'] == ''
+    assert len(json_data['result']) == 0
diff --git a/rotkehlchen/tests/api/test_makerdao_vaults.py b/rotkehlchen/tests/api/test_makerdao_vaults.py
--- a/rotkehlchen/tests/api/test_makerdao_vaults.py
+++ b/rotkehlchen/tests/api/test_makerdao_vaults.py
@@ -20,6 +20,60 @@
 from rotkehlchen.tests.utils.constants import A_USDC, A_WBTC
 from rotkehlchen.tests.utils.makerdao import mock_proxies
 
+mocked_prices = {
+    'ETH': {
+        'USD': {
+            1582699808: FVal('223.73'),
+            1583958747: FVal('194.86'),
+            1584061534: FVal('135.44'),
+            1584061897: FVal('135.44'),
+            1584061977: FVal('135.44'),
+            1586785858: FVal('156.82'),
+            1587910979: FVal('197.78'),
+            1588174425: FVal('215.55'),
+            1588964667: FVal('211.54'),
+            1589993538: FVal('209.85'),
+            1590043499: FVal('198.56'),
+            1590043699: FVal('198.56'),
+        },
+    },
+    'DAI': {
+        'USD': {
+            1582699808: FVal('1.002'),
+            1584024065: FVal('1.002'),
+            1585286480: FVal('1.023'),
+            1585286769: FVal('1.023'),
+            1585290263: FVal('1.023'),
+            1586785858: FVal('1.024'),
+            1586788927: FVal('1.024'),
+            1586805054: FVal('1.024'),
+            1587539880: FVal('1.016'),
+            1587539889: FVal('1.016'),
+            1587910979: FVal('1.015'),
+            1588174425: FVal('1.014'),
+            1588664698: FVal('1.006'),
+            1588696496: FVal('1.006'),
+            1588964616: FVal('1.006'),
+            1589989097: FVal('1.003'),
+            1590042891: FVal('1.001'),
+            1590044118: FVal('1.001'),
+            1590521879: FVal('1.003'),
+        },
+    },
+    'WBTC': {
+        'USD': {
+            1588664698: FVal('7915.09'),
+            1588720248: FVal('7915.09'),
+        },
+    },
+    'USDC': {
+        'USD': {
+            1585286480: FVal(1),
+            1585290300: FVal(1),
+        },
+    },
+}
+
 VAULT_8015 = {
     'identifier': 8015,  # owner is missing and is filled in by the test function
     'collateral_type': 'ETH-A',
@@ -42,36 +96,43 @@
     'events': [{
         'event_type': 'deposit',
         'amount': FVal('41.1641807'),
+        'amount_usd_value': FVal('6455.366829'),
         'timestamp': 1586785858,
         'tx_hash': '0xd382ea1efa843c68914b2377057d384aca2a41710b23be89f165bb0a21986512',
     }, {
         'event_type': 'generate',
         'amount': FVal('1800'),
+        'amount_usd_value': FVal('1843.2'),
         'timestamp': 1586785858,
         'tx_hash': '0xd382ea1efa843c68914b2377057d384aca2a41710b23be89f165bb0a21986512',
     }, {
         'event_type': 'payback',
         'amount': FVal('51'),
+        'amount_usd_value': FVal('52.224'),
         'timestamp': 1586788927,
         'tx_hash': '0xc4ddd0e1b0a6cb4e55ac0be34201a5176372734db3bada58a73bccf98e47b3e7',
     }, {
         'event_type': 'generate',
         'amount': FVal('1000'),
+        'amount_usd_value': FVal('1024'),
         'timestamp': 1586805054,
         'tx_hash': '0x135a1ce0059ea8ca161cff4dba0b579538aa4550c96a895f5cebcc0c56e598d8',
     }, {
         'event_type': 'payback',
         'amount': FVal('1076'),
+        'amount_usd_value': FVal('1093.216'),
         'timestamp': 1587539880,
         'tx_hash': '0x3dd24fc5c64f151bc4a8c1d1a0de39ba23aa760ed27a591a462d822eb5c8fb80',
     }, {
         'event_type': 'payback',
         'amount': FVal('1673.2743084'),
+        'amount_usd_value': FVal('1683.31395425'),
         'timestamp': 1588964616,
         'tx_hash': '0x317f829a351ad9a8fb1a1e5f2f1ee786c0081087dc3a9ece8489e4092f258956',
     }, {
         'event_type': 'withdraw',
         'amount': FVal('41.1641807'),
+        'amount_usd_value': FVal('8707.87080185'),
         'timestamp': 1588964667,
         'tx_hash': '0xa67149325d5e2e20fab2befc3553332866c27ed32a4d04a3975e6eb4b130263b',
     }],
@@ -107,6 +168,8 @@ def _check_vault_details_values(details):
 @pytest.mark.parametrize('number_of_eth_accounts', [1])
 @pytest.mark.parametrize('ethereum_modules', [['makerdao']])
 @pytest.mark.parametrize('start_with_valid_premium', [True])
+@pytest.mark.parametrize('mocked_price_queries', [mocked_prices])
+@pytest.mark.parametrize('default_mock_price_value', [FVal(1)])
 def test_query_vaults(rotkehlchen_api_server, ethereum_accounts):
     """Check querying the vaults endpoint works. Uses real vault data"""
     rotki = rotkehlchen_api_server.rest_api.rotkehlchen
@@ -130,6 +193,8 @@ def test_query_vaults(rotkehlchen_api_server, ethereum_accounts):
 @pytest.mark.parametrize('number_of_eth_accounts', [1])
 @pytest.mark.parametrize('ethereum_modules', [['makerdao']])
 @pytest.mark.parametrize('start_with_valid_premium', [True])
+@pytest.mark.parametrize('mocked_price_queries', [mocked_prices])
+@pytest.mark.parametrize('default_mock_price_value', [FVal(1)])
 def test_query_vaults_async(rotkehlchen_api_server, ethereum_accounts):
     """Check querying the vaults endpoint asynchronously works. Uses real vault data"""
     rotki = rotkehlchen_api_server.rest_api.rotkehlchen
@@ -159,6 +224,8 @@ def test_query_vaults_async(rotkehlchen_api_server, ethereum_accounts):
 @pytest.mark.parametrize('number_of_eth_accounts', [1])
 @pytest.mark.parametrize('ethereum_modules', [['makerdao']])
 @pytest.mark.parametrize('start_with_valid_premium', [True])
+@pytest.mark.parametrize('mocked_price_queries', [mocked_prices])
+@pytest.mark.parametrize('default_mock_price_value', [FVal(1)])
 def test_query_only_details_and_not_vaults(rotkehlchen_api_server, ethereum_accounts):
     """Check querying the vaults details endpoint works before even querying vaults"""
     rotki = rotkehlchen_api_server.rest_api.rotkehlchen
@@ -198,15 +265,8 @@ def test_query_vaults_details_non_premium(rotkehlchen_api_server):
 @pytest.mark.parametrize('number_of_eth_accounts', [3])
 @pytest.mark.parametrize('ethereum_modules', [['makerdao']])
 @pytest.mark.parametrize('start_with_valid_premium', [True])
-@pytest.mark.parametrize('mocked_price_queries', [{
-    'ETH': {
-        'USD': {
-            1584061534: FVal(135.44),
-            1584061897: FVal(135.44),
-            1584061977: FVal(135.44),
-        },
-    },
-}])
+@pytest.mark.parametrize('mocked_price_queries', [mocked_prices])
+@pytest.mark.parametrize('default_mock_price_value', [FVal(1)])
 def test_query_vaults_details_liquidation(rotkehlchen_api_server, ethereum_accounts):
     """Check vault details of a vault with liquidations
 
@@ -260,36 +320,43 @@ def test_query_vaults_details_liquidation(rotkehlchen_api_server, ethereum_accou
         'events': [{
             'event_type': 'deposit',
             'amount': FVal('140'),
+            'amount_usd_value': FVal('31322.2'),
             'timestamp': 1582699808,
             'tx_hash': '0x3246ef91fd3d6e1f7c5766de4fa1f0991ba67d92e518447ba8207fe98569c309',
         }, {
             'event_type': 'generate',
             'amount': FVal('14000'),
+            'amount_usd_value': FVal('14028'),
             'timestamp': 1582699808,
             'tx_hash': '0x3246ef91fd3d6e1f7c5766de4fa1f0991ba67d92e518447ba8207fe98569c309',
         }, {
             'event_type': 'deposit',
             'amount': FVal('1.7'),
+            'amount_usd_value': FVal('331.262'),
             'timestamp': 1583958747,
             'tx_hash': '0x65ac798cb9f22068e43fd9ef8303a31e436989062ae87e25650cc44c7788ab62',
         }, {
             'event_type': 'payback',
             'amount': FVal('2921.344902'),
+            'amount_usd_value': FVal('2927.187591'),
             'timestamp': 1584024065,
             'tx_hash': '0x6e44d22d6898ee012369787cd75ea6fb9ace6f995cd157675f370e8ba4a7b9ad',
         }, {
             'event_type': 'liquidation',
             'amount': FVal('50'),
+            'amount_usd_value': FVal('6772'),
             'timestamp': 1584061534,
             'tx_hash': '0xb02050d914ab40f59a9e07eb4f8161ce36eb97cea9c189b027eb1ceeac83a516',
         }, {
             'event_type': 'liquidation',
             'amount': FVal('50'),
+            'amount_usd_value': FVal('6772'),
             'timestamp': 1584061897,
             'tx_hash': '0x678f31d49dd70d76c0ce441343c0060dc600f4c8dbb4cee2b08c6b451b6097cd',
         }, {
             'event_type': 'liquidation',
             'amount': FVal('41.7'),
+            'amount_usd_value': FVal('5647.848'),
             'timestamp': 1584061977,
             'tx_hash': '0xded0f9de641087692555d92a7fa94fa9fa7abf22744b2d16c20a66c5e48a8edf',
         }],
@@ -303,6 +370,8 @@ def test_query_vaults_details_liquidation(rotkehlchen_api_server, ethereum_accou
 @pytest.mark.parametrize('number_of_eth_accounts', [1])
 @pytest.mark.parametrize('ethereum_modules', [['makerdao']])
 @pytest.mark.parametrize('start_with_valid_premium', [True])
+@pytest.mark.parametrize('mocked_price_queries', [mocked_prices])
+@pytest.mark.parametrize('default_mock_price_value', [FVal(1)])
 def test_query_vaults_wbtc(rotkehlchen_api_server, ethereum_accounts):
     """Check vault info and details for a vault with WBTC as collateral"""
     rotki = rotkehlchen_api_server.rest_api.rotkehlchen
@@ -349,21 +418,25 @@ def test_query_vaults_wbtc(rotkehlchen_api_server, ethereum_accounts):
         'events': [{
             'event_type': 'deposit',
             'amount': FVal('0.011'),
+            'amount_usd_value': FVal('87.06599'),
             'timestamp': 1588664698,
             'tx_hash': '0x9ba4a6187fa2c49ba327e7c923846a08a1e972017ec41d3f9f66ef524f7dde59',
         }, {
             'event_type': 'generate',
             'amount': FVal('25'),
+            'amount_usd_value': FVal('25.15'),
             'timestamp': 1588664698,
             'tx_hash': '0x9ba4a6187fa2c49ba327e7c923846a08a1e972017ec41d3f9f66ef524f7dde59',
         }, {
             'event_type': 'payback',
             'amount': FVal('25.000248996'),
+            'amount_usd_value': FVal('25.15025'),
             'timestamp': 1588696496,
             'tx_hash': '0x8bd960e7eb8b9e2b81d2446d1844dd63f94636c7800ea5e3b4d926ea0244c66c',
         }, {
             'event_type': 'deposit',
             'amount': FVal('0.0113'),
+            'amount_usd_value': FVal('89.440517'),
             'timestamp': 1588720248,
             'tx_hash': '0x678c4da562173c102473f1904ff293a767ebac9ec6c7d728ef2fd41acf00a13a',
         }],  # way too many events in the vault, so no need to check them all
@@ -381,6 +454,8 @@ def test_query_vaults_wbtc(rotkehlchen_api_server, ethereum_accounts):
 @pytest.mark.parametrize('number_of_eth_accounts', [1])
 @pytest.mark.parametrize('ethereum_modules', [['makerdao']])
 @pytest.mark.parametrize('start_with_valid_premium', [True])
+@pytest.mark.parametrize('mocked_price_queries', [mocked_prices])
+@pytest.mark.parametrize('default_mock_price_value', [FVal(1)])
 def test_query_vaults_usdc(rotkehlchen_api_server, ethereum_accounts):
     """Check vault info and details for a vault with USDC as collateral"""
     rotki = rotkehlchen_api_server.rest_api.rotkehlchen
@@ -423,26 +498,31 @@ def test_query_vaults_usdc(rotkehlchen_api_server, ethereum_accounts):
         'events': [{
             'event_type': 'deposit',
             'amount': FVal('45'),
+            'amount_usd_value': FVal('45'),
             'timestamp': 1585286480,
             'tx_hash': '0x8b553dd0e8ee5385ec91105bf911143666d9df0ecd84c04f288278f7658aa7d6',
         }, {
             'event_type': 'generate',
             'amount': FVal('20'),
+            'amount_usd_value': FVal('20.46'),
             'timestamp': 1585286480,
             'tx_hash': '0x8b553dd0e8ee5385ec91105bf911143666d9df0ecd84c04f288278f7658aa7d6',
         }, {
             'event_type': 'generate',
             'amount': FVal('15.99'),
+            'amount_usd_value': FVal('16.35777'),
             'timestamp': 1585286769,
             'tx_hash': '0xdb861c893a51e4649ff3740cd3658cd4c9b1d048d3b8b4d117f4319bd60aee01',
         }, {
             'event_type': 'payback',
             'amount': FVal('35.990506367'),
+            'amount_usd_value': FVal('36.818288'),
             'timestamp': 1585290263,
             'tx_hash': '0xdd7825fe4a93c6f1ffa25a91b6da2396c229fe16b17242ad5c0bf7962928b2ec',
         }, {
             'event_type': 'withdraw',
             'amount': FVal('45'),
+            'amount_usd_value': FVal('45'),
             'timestamp': 1585290300,
             'tx_hash': '0x97462ebba7ce2467787bf6de25a25c24e538cf8a647919112c5f048b6a293408',
         }],
@@ -455,6 +535,8 @@ def test_query_vaults_usdc(rotkehlchen_api_server, ethereum_accounts):
 @pytest.mark.parametrize('number_of_eth_accounts', [1])
 @pytest.mark.parametrize('ethereum_modules', [['makerdao']])
 @pytest.mark.parametrize('start_with_valid_premium', [True])
+@pytest.mark.parametrize('mocked_price_queries', [mocked_prices])
+@pytest.mark.parametrize('default_mock_price_value', [FVal(1)])
 def test_two_vaults_same_account_same_collateral(rotkehlchen_api_server, ethereum_accounts):
     """Check that no events are duplicated between vaults for same collateral by same account
 
@@ -514,26 +596,31 @@ def test_two_vaults_same_account_same_collateral(rotkehlchen_api_server, ethereu
         'events': [{
             'event_type': 'deposit',
             'amount': FVal('1'),
+            'amount_usd_value': FVal('197.78'),
             'timestamp': 1587910979,
             'tx_hash': '0xf59858df4e42cdc2aecfebdcf38e1df841866c6a9eb3adb6bde9a844564a3bb6',
         }, {
             'event_type': 'generate',
             'amount': FVal('80'),
+            'amount_usd_value': FVal('81.2'),
             'timestamp': 1587910979,
             'tx_hash': '0xf59858df4e42cdc2aecfebdcf38e1df841866c6a9eb3adb6bde9a844564a3bb6',
         }, {
             'event_type': 'payback',
             'amount': FVal('80'),
+            'amount_usd_value': FVal('80.24'),
             'timestamp': 1589989097,
             'tx_hash': '0x52396f7d20db54e2e9e716698b643a39815ff149a6cccbe9c7597dc9e06bb9d3',
         }, {
             'event_type': 'deposit',
             'amount': FVal('3.5'),
+            'amount_usd_value': FVal('734.475'),
             'timestamp': 1589993538,
             'tx_hash': '0x3c3942dc40fe68303098d91e765ceecaed4664bba0ef8f8e684b6f0e61968c6c',
         }, {
             'event_type': 'withdraw',
             'amount': FVal('4.5'),
+            'amount_usd_value': FVal('893.52'),
             'timestamp': 1590043499,
             'tx_hash': '0xbcd4158f0089404f6ab5378517762cddc13d21c9d2fcf3fd45cf1cf4b656242c',
         }],
@@ -547,26 +634,31 @@ def test_two_vaults_same_account_same_collateral(rotkehlchen_api_server, ethereu
         'events': [{
             'event_type': 'deposit',
             'amount': FVal('2.4'),
+            'amount_usd_value': FVal('517.32'),
             'timestamp': 1588174425,
             'tx_hash': '0xdb677a4257b5bdb305c278102d7b2460408bb7a3981414b994f4dd80a737ac2a',
         }, {
             'event_type': 'generate',
             'amount': FVal('192'),
+            'amount_usd_value': FVal('194.688'),
             'timestamp': 1588174425,
             'tx_hash': '0xdb677a4257b5bdb305c278102d7b2460408bb7a3981414b994f4dd80a737ac2a',
         }, {
             'event_type': 'payback',
             'amount': FVal('192'),
+            'amount_usd_value': FVal('192.192'),
             'timestamp': 1590042891,
             'tx_hash': '0x488a937677030cc810d0062001c08c944ecf6329b24a45ae9480bada8147bf75',
         }, {
             'event_type': 'deposit',
             'amount': FVal('4.4'),
+            'amount_usd_value': FVal('873.664'),
             'timestamp': 1590043699,
             'tx_hash': '0x712ddb654b878bcb30c5344d7c18f7f796fe94abd6e5b8a22b2da0a6c99bb425',
         }, {
             'event_type': 'generate',
             'amount': FVal('429.79'),
+            'amount_usd_value': FVal('430.21979'),
             'timestamp': 1590044118,
             'tx_hash': '0x36bfa27e157c03393a8816f6c1e3e990474f8f7473413810d87e2f4981d58044',
         }],
diff --git a/rotkehlchen/tests/fixtures/accounting.py b/rotkehlchen/tests/fixtures/accounting.py
--- a/rotkehlchen/tests/fixtures/accounting.py
+++ b/rotkehlchen/tests/fixtures/accounting.py
@@ -53,6 +53,18 @@ def should_mock_price_queries():
     return True
 
 
+@pytest.fixture
+def default_mock_price_value() -> Optional[FVal]:
+    """Determines test behavior If a mock price is not found
+
+    If it's None, then test fails with an error. If it is any other
+    value then this is returned by the price mocking function. It's used
+    for tests where other price queries may happen apart from the ones we check
+    but we never check them so we don't care about the price.
+    """
+    return None
+
+
 @pytest.fixture
 def mocked_price_queries():
     return defaultdict(defaultdict)
diff --git a/rotkehlchen/tests/fixtures/rotkehlchen.py b/rotkehlchen/tests/fixtures/rotkehlchen.py
--- a/rotkehlchen/tests/fixtures/rotkehlchen.py
+++ b/rotkehlchen/tests/fixtures/rotkehlchen.py
@@ -80,6 +80,7 @@ def initialize_mock_rotkehlchen_instance(
         ignored_assets,
         tags,
         manually_tracked_balances,
+        default_mock_price_value,
 ):
     if start_with_logged_in_user:
         rotki.unlock_user(
@@ -108,6 +109,7 @@ def initialize_mock_rotkehlchen_instance(
             historian=PriceHistorian(),
             should_mock_price_queries=should_mock_price_queries,
             mocked_price_queries=mocked_price_queries,
+            default_mock_value=default_mock_price_value,
         )
 
 
@@ -144,6 +146,7 @@ def rotkehlchen_api_server(
         ignored_assets,
         tags,
         manually_tracked_balances,
+        default_mock_price_value,
 ):
     """A partially mocked rotkehlchen server instance"""
 
@@ -167,6 +170,7 @@ def rotkehlchen_api_server(
         ignored_assets=ignored_assets,
         tags=tags,
         manually_tracked_balances=manually_tracked_balances,
+        default_mock_price_value=default_mock_price_value,
     )
     return api_server
 
@@ -190,6 +194,7 @@ def rotkehlchen_instance(
         ignored_assets,
         tags,
         manually_tracked_balances,
+        default_mock_price_value,
 ):
     """A partially mocked rotkehlchen instance"""
 
@@ -211,6 +216,7 @@ def rotkehlchen_instance(
         ignored_assets=ignored_assets,
         tags=tags,
         manually_tracked_balances=manually_tracked_balances,
+        default_mock_price_value=default_mock_price_value,
     )
     return uninitialized_rotkehlchen
 
diff --git a/rotkehlchen/tests/utils/history.py b/rotkehlchen/tests/utils/history.py
--- a/rotkehlchen/tests/utils/history.py
+++ b/rotkehlchen/tests/utils/history.py
@@ -921,6 +921,7 @@ def maybe_mock_historical_price_queries(
         historian,
         should_mock_price_queries: bool,
         mocked_price_queries,
+        default_mock_value: Optional[FVal] = None,
 ) -> None:
     """If needed will make sure the historian's price queries are mocked"""
     if not should_mock_price_queries:
@@ -933,10 +934,13 @@ def mock_historical_price_query(from_asset, to_asset, timestamp):
         try:
             price = mocked_price_queries[from_asset.identifier][to_asset.identifier][timestamp]
         except KeyError:
-            raise AssertionError(
-                f'No mocked price found from {from_asset.identifier} to '
-                f'{to_asset.identifier} at {timestamp}',
-            )
+            if default_mock_value is None:
+                raise AssertionError(
+                    f'No mocked price found from {from_asset.identifier} to '
+                    f'{to_asset.identifier} at {timestamp}',
+                )
+            # else just use the default
+            return default_mock_value
 
         return price