diff --git a/gnosis/eth/oracles/uniswap_v3.py b/gnosis/eth/oracles/uniswap_v3.py index c65c3ba36..a9a9548c9 100644 --- a/gnosis/eth/oracles/uniswap_v3.py +++ b/gnosis/eth/oracles/uniswap_v3.py @@ -11,6 +11,7 @@ from .. import EthereumClient from ..constants import NULL_ADDRESS +from ..contracts import get_erc20_contract from .abis.uniswap_v3 import ( uniswap_v3_factory_abi, uniswap_v3_pool_abi, @@ -138,19 +139,33 @@ def get_price( f"Uniswap V3 pool does not exist for {token_address} and {token_address_2}" ) - pool_contract = self.w3.eth.contract(pool_address, abi=uniswap_v3_pool_abi) + # Decimals needs to be adjusted + token_decimals = get_decimals(token_address, self.ethereum_client) + token_2_decimals = get_decimals(token_address_2, self.ethereum_client) + pool_contract = self.w3.eth.contract(pool_address, abi=uniswap_v3_pool_abi) try: ( - liquidity, + token_balance, + token_2_balance, (sqrt_price_x96, _, _, _, _, _, _), ) = self.ethereum_client.batch_call( - [pool_contract.functions.liquidity(), pool_contract.functions.slot0()] + [ + get_erc20_contract( + self.ethereum_client.w3, token_address + ).functions.balanceOf(pool_address), + get_erc20_contract( + self.ethereum_client.w3, token_address_2 + ).functions.balanceOf(pool_address), + pool_contract.functions.slot0(), + ] ) - if liquidity == 0: + if (token_balance / 10**token_decimals) < 2 or ( + token_2_balance / 10**token_2_decimals + ) < 2: error_message = ( f"Not enough liquidity on uniswap v3 for pair token_1={token_address} " - f"token_2={token_address_2}" + f"token_2={token_address_2}, at least 2 units of each token are required" ) logger.warning(error_message) raise CannotGetPriceFromOracle(error_message) @@ -166,10 +181,6 @@ def get_price( logger.warning(error_message) raise CannotGetPriceFromOracle(error_message) from e - # Decimals needs to be adjusted - token_decimals = get_decimals(token_address, self.ethereum_client) - token_2_decimals = get_decimals(token_address_2, self.ethereum_client) - # https://docs.uniswap.org/sdk/guides/fetching-prices if not reversed: # Multiplying by itself is way faster than exponential diff --git a/gnosis/eth/tests/oracles/test_uniswap_v3.py b/gnosis/eth/tests/oracles/test_uniswap_v3.py index 177b63c20..5fa51b444 100644 --- a/gnosis/eth/tests/oracles/test_uniswap_v3.py +++ b/gnosis/eth/tests/oracles/test_uniswap_v3.py @@ -64,10 +64,19 @@ def test_get_price(self): with self.assertRaisesMessage( CannotGetPriceFromOracle, f"Not enough liquidity on uniswap v3 for pair token_1={s_usd_token_mainnet_address} " - f"token_2=0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", + f"token_2=0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2, at least 2 units of each token are required", ): uniswap_v3_oracle.get_price(s_usd_token_mainnet_address) + # Test token with no liquidity + wrapped_nxm_token_mainnet_address = "0x0d438F3b5175Bebc262bF23753C1E53d03432bDE" + with self.assertRaisesMessage( + CannotGetPriceFromOracle, + f"Not enough liquidity on uniswap v3 for pair token_1={wrapped_nxm_token_mainnet_address} " + f"token_2=0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2, at least 2 units of each token are required", + ): + uniswap_v3_oracle.get_price(wrapped_nxm_token_mainnet_address) + def test_get_price_contract_not_deployed(self): self.assertFalse(UniswapV3Oracle.is_available(self.ethereum_client)) with self.assertRaisesMessage(