Repository: rotki/rotki

Issue:
PoolTogether data in Defi Overview is not correct
## Problem Definition

PoolTogether (https://app.pooltogether.com/) data is not correctly represented in the Defi overview. This is because the zerion SDK seems to return "PLT" as the token (which rotki recognizes as "Plutus Defi"), so it's returning an incorrect crypto icon and value in the user's profit currency.
![image](https://user-images.githubusercontent.com/27592/92018221-27906900-ed55-11ea-8c1a-948e738d8f03.png)


The real token depends on which pool (DAI or USDC) the user has deposited their funds into thus should be returned as plDAI or plUSDC, which are locked in value 1:1 to DAI and USDC respectively. Therefore the correct valuation here would be 45 plDAI = 45 USD = ~38 EUR.

Even if zerion returned the correct token names, though, the downside is that these tokens are not listed on coingecko or cryptocompare as they're not really "tradeable tokens" -- just proxies for DAI and USDC, so we cannot grab the icons and prices automatically. We will probably need to create aliases plDAI for DAI and plUSDC for USDC and then include the icons manually? 

Another option of course is that we develop our own submodule (e.g. using their subgraph https://thegraph.com/explorer/subgraph/pooltogether/pooltogether or by querying the relevant contracts) and ignore the zerion results for pooltogether.

More resources:
https://defimarketcap.io/protocol/pool-together
https://etherscan.io/accounts/label/pooltogether



Discussion:
@isidorosp This probably should go along with https://github.com/rotki/rotki/issues/1120, and the "more resources" links should also go there.

But let me see if until full pool together support is possible we can do something in between for what we show in the DeFi overview. Let me check zerion's adapter contract. Can you DM me the address you used so that I can test?

Resolving patch:
diff --git a/rotkehlchen/chain/ethereum/zerion.py b/rotkehlchen/chain/ethereum/zerion.py
--- a/rotkehlchen/chain/ethereum/zerion.py
+++ b/rotkehlchen/chain/ethereum/zerion.py
@@ -8,6 +8,7 @@
 from rotkehlchen.assets.asset import Asset
 from rotkehlchen.chain.ethereum.defi import handle_defi_price_query
 from rotkehlchen.chain.ethereum.utils import token_normalized_value
+from rotkehlchen.constants.assets import A_DAI, A_USDC
 from rotkehlchen.constants.ethereum import ZERION_ABI
 from rotkehlchen.constants.misc import ZERO
 from rotkehlchen.errors import UnknownAsset, UnsupportedAsset
@@ -27,8 +28,6 @@ def _is_symbol_non_standard(symbol: str) -> bool:
     """ignore some non standard asset symbols like Curve finance and Pool together"""
     if '+' in symbol:
         return True
-    if symbol == 'PLT':
-        return True
 
     return False
 
@@ -64,6 +63,38 @@ class DefiProtocolBalances(NamedTuple):
     Callable[[], Dict[ChecksumEthAddress, List[DefiProtocolBalances]]],
 ]
 
+
+def _handle_pooltogether(normalized_balance: FVal, token_name: str) -> Optional[DefiBalance]:
+    """Special handling for pooltogether
+
+    https://github.com/rotki/rotki/issues/1429
+    """
+    if 'DAI' in token_name:
+        dai_price = Inquirer.find_usd_price(A_DAI)
+        return DefiBalance(
+            token_address=to_checksum_address('0x49d716DFe60b37379010A75329ae09428f17118d'),
+            token_name='Pool Together DAI token',
+            token_symbol='plDAI',
+            balance=Balance(
+                amount=normalized_balance,
+                usd_value=normalized_balance * dai_price,
+            ),
+        )
+    elif 'USDC' in token_name:
+        usdc_price = Inquirer.find_usd_price(A_USDC)
+        return DefiBalance(
+            token_address=to_checksum_address('0xBD87447F48ad729C5c4b8bcb503e1395F62e8B98'),
+            token_name='Pool Together USDC token',
+            token_symbol='plUSDC',
+            balance=Balance(
+                amount=normalized_balance,
+                usd_value=normalized_balance * usdc_price,
+            ),
+        )
+
+    return None
+
+
 # last known zerion adapter address
 ZERION_ADAPTER_ADDRESS = deserialize_ethereum_address('0x06FE76B2f432fdfEcAEf1a7d4f6C3d41B5861672')
 
@@ -129,9 +160,9 @@ def all_balances_for_account(self, account: ChecksumEthAddress) -> List[DefiProt
                 balance_type = adapter_balance[0][1]  # can be either 'Asset' or 'Debt'
                 for balances in adapter_balance[1]:
                     underlying_balances = []
-                    base_balance = self._get_single_balance(balances[0])
+                    base_balance = self._get_single_balance(protocol.name, balances[0])
                     for balance in balances[1]:
-                        defi_balance = self._get_single_balance(balance)
+                        defi_balance = self._get_single_balance(protocol.name, balance)
                         underlying_balances.append(defi_balance)
 
                     if base_balance.balance.usd_value == ZERO:
@@ -150,7 +181,11 @@ def all_balances_for_account(self, account: ChecksumEthAddress) -> List[DefiProt
 
         return protocol_balances
 
-    def _get_single_balance(self, entry: Tuple[Tuple[str, str, str, int], int]) -> DefiBalance:
+    def _get_single_balance(
+            self,
+            protocol_name: str,
+            entry: Tuple[Tuple[str, str, str, int], int],
+    ) -> DefiBalance:
         metadata = entry[0]
         balance_value = entry[1]
         decimals = metadata[3]
@@ -160,6 +195,7 @@ def _get_single_balance(self, entry: Tuple[Tuple[str, str, str, int], int]) -> D
         token_name = metadata[1]
 
         special_handling = self.handle_protocols(
+            protocol_name=protocol_name,
             token_symbol=token_symbol,
             normalized_balance=normalized_value,
             token_address=token_address,
@@ -189,12 +225,20 @@ def _get_single_balance(self, entry: Tuple[Tuple[str, str, str, int], int]) -> D
 
     def handle_protocols(
             self,
+            protocol_name: str,
             token_symbol: str,
             normalized_balance: FVal,
             token_address: str,
             token_name: str,
     ) -> Optional[DefiBalance]:
-        """Special handling for price for token/protocols which are easier to do onchain"""
+        """Special handling for price for token/protocols which are easier to do onchain
+        or need some kind of special treatment.
+        """
+        if protocol_name == 'PoolTogether':
+            result = _handle_pooltogether(normalized_balance, token_name)
+            if result is not None:
+                return result
+
         underlying_asset_price = get_underlying_asset_price(token_symbol)
         usd_price = handle_defi_price_query(self.ethereum, token_symbol, underlying_asset_price)
         if usd_price is None:


Test patch: