Skip to content

Commit

Permalink
Check liquidity for tokens in UniswapV3 oracle
Browse files Browse the repository at this point in the history
- Make sure there are at least 2 unit of each token
  • Loading branch information
Uxio0 committed Oct 10, 2022
1 parent 54610de commit 15d5a0f
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 10 deletions.
29 changes: 20 additions & 9 deletions gnosis/eth/oracles/uniswap_v3.py
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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)
Expand All @@ -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
Expand Down
11 changes: 10 additions & 1 deletion gnosis/eth/tests/oracles/test_uniswap_v3.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down

0 comments on commit 15d5a0f

Please sign in to comment.