historical prices + cream
This commit is contained in:
parent
d8458978f3
commit
ec1680c976
1
mev_inspect/abis/cream/Comptroller.json
Normal file
1
mev_inspect/abis/cream/Comptroller.json
Normal file
@ -0,0 +1 @@
|
|||||||
|
[{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"error","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"info","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"detail","type":"uint256"}],"name":"Failure","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"NewAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldImplementation","type":"address"},{"indexed":false,"internalType":"address","name":"newImplementation","type":"address"}],"name":"NewImplementation","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldPendingAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newPendingAdmin","type":"address"}],"name":"NewPendingAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldPendingImplementation","type":"address"},{"indexed":false,"internalType":"address","name":"newPendingImplementation","type":"address"}],"name":"NewPendingImplementation","type":"event"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"constant":false,"inputs":[],"name":"_acceptAdmin","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[],"name":"_acceptImplementation","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newPendingAdmin","type":"address"}],"name":"_setPendingAdmin","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"newPendingImplementation","type":"address"}],"name":"_setPendingImplementation","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"comptrollerImplementation","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"pendingAdmin","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"pendingComptrollerImplementation","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"}]
|
1
mev_inspect/abis/uniswap_v2/UniswapV2Factory.json
Normal file
1
mev_inspect/abis/uniswap_v2/UniswapV2Factory.json
Normal file
@ -0,0 +1 @@
|
|||||||
|
[{"inputs":[{"internalType":"address","name":"_feeToSetter","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token0","type":"address"},{"indexed":true,"internalType":"address","name":"token1","type":"address"},{"indexed":false,"internalType":"address","name":"pair","type":"address"},{"indexed":false,"internalType":"uint256","name":"","type":"uint256"}],"name":"PairCreated","type":"event"},{"constant":true,"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"allPairs","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"allPairsLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"tokenA","type":"address"},{"internalType":"address","name":"tokenB","type":"address"}],"name":"createPair","outputs":[{"internalType":"address","name":"pair","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"feeTo","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"feeToSetter","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"getPair","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_feeTo","type":"address"}],"name":"setFeeTo","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"_feeToSetter","type":"address"}],"name":"setFeeToSetter","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"}]
|
130
mev_inspect/historical_price.py
Normal file
130
mev_inspect/historical_price.py
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
from mev_inspect.schemas.classified_traces import Protocol
|
||||||
|
from mev_inspect.abi import get_raw_abi
|
||||||
|
from web3 import Web3
|
||||||
|
|
||||||
|
rpc = ""
|
||||||
|
w3 = Web3(Web3.HTTPProvider(rpc))
|
||||||
|
|
||||||
|
|
||||||
|
weth_address = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
|
||||||
|
usdc_address = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"
|
||||||
|
zero_address = "0x0000000000000000000000000000000000000000"
|
||||||
|
|
||||||
|
uniswap_router = "0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D"
|
||||||
|
uniswap_factory = "0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f"
|
||||||
|
sushiswap_router = "0xd9e1cE17f2641f24aE83637ab66a2cca9C378B9F"
|
||||||
|
sushiswap_factory = "0xC0AEe478e3658e2610c5F7A4A2E1777cE9e4f2Ac"
|
||||||
|
|
||||||
|
router_abi = get_raw_abi("UniswapV2Router", Protocol.uniswap_v2)
|
||||||
|
factory_abi = get_raw_abi("UniswapV2Factory", Protocol.uniswap_v2)
|
||||||
|
pool_abi = get_raw_abi("UniswapV2Pair", None)
|
||||||
|
|
||||||
|
# helper to get decimals of any given erc20 token
|
||||||
|
def get_erc20_token_decimals(token_address):
|
||||||
|
token_abi = get_raw_abi("ERC20", None)
|
||||||
|
token_instance = w3.eth.contract(address=token_address, abi=token_abi)
|
||||||
|
decimals = token_instance.functions.decimals().call()
|
||||||
|
return decimals
|
||||||
|
|
||||||
|
|
||||||
|
# get the specific uniswap/sushiswap pools for a pair of tokens
|
||||||
|
def get_uniswap_pair_pool(token_0, token_1):
|
||||||
|
factory_instance = w3.eth.contract(address=uniswap_factory, abi=factory_abi)
|
||||||
|
pair_address = factory_instance.functions.getPair(token_0, token_1).call()
|
||||||
|
# 0x0 is returned when the pair does not have a pool
|
||||||
|
if pair_address != zero_address:
|
||||||
|
return pair_address
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def get_sushiswap_pair_pool(token_0, token_1):
|
||||||
|
factory_instance = w3.eth.contract(address=sushiswap_factory, abi=factory_abi)
|
||||||
|
pair_address = factory_instance.functions.getPair(token_0, token_1).call()
|
||||||
|
# 0x0 is returned when the pair does not have a pool
|
||||||
|
if pair_address != zero_address:
|
||||||
|
return pair_address
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
# get reserves of a pool at a specific block number
|
||||||
|
def get_uni_pool_reserves(pool_address, block_number):
|
||||||
|
pool_instance = w3.eth.contract(address=pool_address, abi=pool_abi)
|
||||||
|
token_0 = pool_instance.functions.token0().call()
|
||||||
|
token_1 = pool_instance.functions.token1().call()
|
||||||
|
token_0_reserve, token_1_reserve, _ = pool_instance.functions.getReserves().call(
|
||||||
|
block_identifier=block_number
|
||||||
|
)
|
||||||
|
return {token_0: token_0_reserve, token_1: token_1_reserve}
|
||||||
|
|
||||||
|
|
||||||
|
def get_sushi_pool_reserves(pool_address, block_number):
|
||||||
|
pool_instance = w3.eth.contract(address=pool_address, abi=pool_abi)
|
||||||
|
token_0 = pool_instance.functions.token0().call()
|
||||||
|
token_1 = pool_instance.functions.token1().call()
|
||||||
|
token_0_reserve, token_1_reserve, _ = pool_instance.functions.getReserves().call(
|
||||||
|
block_identifier=block_number
|
||||||
|
)
|
||||||
|
return {token_0: token_0_reserve, token_1: token_1_reserve}
|
||||||
|
|
||||||
|
|
||||||
|
# get the price of any token (in eth) at a specific block number
|
||||||
|
def get_erc20_token_price_in_eth(token_amount, token_address, block_number):
|
||||||
|
# get the TOKEN-ETH pool addresses from AMM factory
|
||||||
|
uni_pair_pool_address = get_uniswap_pair_pool(token_address, weth_address)
|
||||||
|
sushi_pair_pool_address = get_sushiswap_pair_pool(token_address, weth_address)
|
||||||
|
|
||||||
|
# get reserves from both pools, to pick one with greater liquidity at that block height
|
||||||
|
uni_pool_reserves = get_uni_pool_reserves(uni_pair_pool_address, block_number)
|
||||||
|
sushi_pool_reserves = get_sushi_pool_reserves(sushi_pair_pool_address, block_number)
|
||||||
|
|
||||||
|
# if uniswap has better liquidity
|
||||||
|
if uni_pool_reserves[token_address] > sushi_pool_reserves[token_address]:
|
||||||
|
router_instance = w3.eth.contract(address=uniswap_router, abi=router_abi)
|
||||||
|
token_price_in_wei = router_instance.functions.getAmountOut(
|
||||||
|
token_amount,
|
||||||
|
uni_pool_reserves[token_address],
|
||||||
|
uni_pool_reserves[weth_address],
|
||||||
|
).call()
|
||||||
|
token_price_in_eth = w3.fromWei(token_price_in_wei, "ether")
|
||||||
|
return token_price_in_eth
|
||||||
|
else: # sushiswap has better liquidity
|
||||||
|
router_instance = w3.eth.contract(address=sushiswap_router, abi=router_abi)
|
||||||
|
token_price_in_wei = router_instance.functions.getAmountOut(
|
||||||
|
token_amount,
|
||||||
|
sushi_pool_reserves[token_address],
|
||||||
|
sushi_pool_reserves[weth_address],
|
||||||
|
).call()
|
||||||
|
token_price_in_eth = w3.fromWei(token_price_in_wei, "ether")
|
||||||
|
return token_price_in_eth
|
||||||
|
|
||||||
|
|
||||||
|
# same but denominated in USDC
|
||||||
|
def get_erc20_token_price_in_usdc(token_amount, token_address, block_number):
|
||||||
|
# get the TOKEN-ETH pool addresses from AMM factory
|
||||||
|
uni_pair_pool_address = get_uniswap_pair_pool(token_address, usdc_address)
|
||||||
|
sushi_pair_pool_address = get_sushiswap_pair_pool(token_address, usdc_address)
|
||||||
|
|
||||||
|
# get reserves from both pools, to pick one with greater liquidity at that block height
|
||||||
|
uni_pool_reserves = get_uni_pool_reserves(uni_pair_pool_address, block_number)
|
||||||
|
sushi_pool_reserves = get_sushi_pool_reserves(sushi_pair_pool_address, block_number)
|
||||||
|
|
||||||
|
# if uniswap has better liquidity
|
||||||
|
if uni_pool_reserves[token_address] > sushi_pool_reserves[token_address]:
|
||||||
|
router_instance = w3.eth.contract(address=uniswap_router, abi=router_abi)
|
||||||
|
token_price = router_instance.functions.getAmountOut(
|
||||||
|
token_amount,
|
||||||
|
uni_pool_reserves[token_address],
|
||||||
|
uni_pool_reserves[usdc_address],
|
||||||
|
).call()
|
||||||
|
# usdc has 6 decimals
|
||||||
|
return token_price / 10 ** 6
|
||||||
|
else: # sushiswap has better liquidity
|
||||||
|
router_instance = w3.eth.contract(address=sushiswap_router, abi=router_abi)
|
||||||
|
token_price = router_instance.functions.getAmountOut(
|
||||||
|
token_amount,
|
||||||
|
sushi_pool_reserves[token_address],
|
||||||
|
sushi_pool_reserves[usdc_address],
|
||||||
|
).call()
|
||||||
|
return token_price / 10 ** 6
|
@ -21,6 +21,7 @@ class Protocol(Enum):
|
|||||||
sushiswap = "sushiswap"
|
sushiswap = "sushiswap"
|
||||||
aave = "aave"
|
aave = "aave"
|
||||||
compound_v2 = "compound_v2"
|
compound_v2 = "compound_v2"
|
||||||
|
cream = "cream"
|
||||||
weth = "weth"
|
weth = "weth"
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
from enum import Enum
|
# from enum import Enum
|
||||||
from .utils import CamelModel
|
from .utils import CamelModel
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,23 +1,21 @@
|
|||||||
from mev_inspect.schemas.classified_traces import Classification, ClassifiedTrace
|
from typing import Optional
|
||||||
|
from web3 import Web3
|
||||||
|
from mev_inspect.schemas.classified_traces import ClassifiedTrace
|
||||||
from mev_inspect.schemas.liquidations import (
|
from mev_inspect.schemas.liquidations import (
|
||||||
Liquidation,
|
Liquidation,
|
||||||
LiquidationType,
|
LiquidationType,
|
||||||
LiquidationStatus,
|
LiquidationStatus,
|
||||||
LiquidationCollateralSource,
|
LiquidationCollateralSource,
|
||||||
)
|
)
|
||||||
from mev_inspect.block import _get_cache_path
|
|
||||||
from mev_inspect.schemas import Block
|
|
||||||
from mev_inspect.schemas.blocks import Transaction
|
from mev_inspect.schemas.blocks import Transaction
|
||||||
from mev_inspect.trace_classifier import TraceClassifier
|
from mev_inspect.classifier_specs import Protocol
|
||||||
from mev_inspect.classifier_specs import CLASSIFIER_SPECS, Protocol
|
|
||||||
from mev_inspect.tokenflow import get_dollar_flows, get_tx_proxies
|
# from mev_inspect.tokenflow import get_dollar_flows, get_tx_proxies
|
||||||
|
from mev_inspect.historical_price import get_erc20_token_decimals
|
||||||
from mev_inspect.abi import get_raw_abi
|
from mev_inspect.abi import get_raw_abi
|
||||||
from web3 import Web3
|
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
w3 = Web3(Web3.HTTPProvider(""))
|
w3 = Web3(Web3.HTTPProvider(""))
|
||||||
|
|
||||||
|
|
||||||
comp_v2_comptroller_address = "0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B"
|
comp_v2_comptroller_address = "0x3d9819210A31b4961b30EF54bE2aeD79B9c9Cd3B"
|
||||||
c_ether = "0x4Ddc2D193948926D02f9B1fE9e1daa0718270ED5"
|
c_ether = "0x4Ddc2D193948926D02f9B1fE9e1daa0718270ED5"
|
||||||
|
|
||||||
@ -65,23 +63,29 @@ def find_collateral_source(
|
|||||||
return source
|
return source
|
||||||
|
|
||||||
|
|
||||||
# TODO: check tx status and assign accordingly
|
def get_underlying_ctoken_exchange_rate(
|
||||||
# i.e if a tx checks if the opportunity is still available ("liquidateBorrowAllowed")
|
c_token_address: str, block_number: int
|
||||||
# or if it calls the COMP oracle for price data ("getUnderlyingPrice(address")
|
) -> float:
|
||||||
# def is_pre_flight():
|
comp_v2_ctoken_abi = get_raw_abi("CToken", Protocol.compound_v2)
|
||||||
# pass
|
ctoken_instance = w3.eth.contract(address=c_token_address, abi=comp_v2_ctoken_abi)
|
||||||
|
raw_exchange_rate = ctoken_instance.functions.exchangeRateCurrent().call(
|
||||||
# for cToken - differnt file?
|
block_identifier=block_number
|
||||||
# TODO: fetch historic price (in ETH) of any given token at the block height the tx occured
|
)
|
||||||
# to calculate the profit in ETH accurately, regardless of what token the profit was held in
|
# format based on decimals in ctoken and the underlying token
|
||||||
# def get_historic_token_price():
|
# see "Interpreting Exchange Rates" https://compound.finance/docs#protocol-math
|
||||||
# pass
|
underlying_token_address = get_all_comp_markets()[c_token_address.lower()]
|
||||||
|
decimals_in_underlying = get_erc20_token_decimals(
|
||||||
|
Web3.toChecksumAddress(underlying_token_address)
|
||||||
|
)
|
||||||
|
decimals_in_ctoken = get_erc20_token_decimals(c_token_address)
|
||||||
|
return raw_exchange_rate / (
|
||||||
|
10 ** (18 + decimals_in_underlying - decimals_in_ctoken)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def inspect_compound_v2_ceth(
|
def inspect_compound_v2_ceth(
|
||||||
tx: Transaction, classified_traces: list[ClassifiedTrace]
|
tx: Transaction, classified_traces: list[ClassifiedTrace]
|
||||||
) -> Liquidation:
|
) -> Liquidation:
|
||||||
# TODO: complete this logic after seized return type
|
|
||||||
# flow:
|
# flow:
|
||||||
# 1. decide if it's a pre-flight check tx or an actual liquidation
|
# 1. decide if it's a pre-flight check tx or an actual liquidation
|
||||||
# 2. parse `liquidateBorrow` and `seize` sub traces to determine actual amounts
|
# 2. parse `liquidateBorrow` and `seize` sub traces to determine actual amounts
|
||||||
@ -96,7 +100,7 @@ def inspect_compound_v2_ceth(
|
|||||||
source = find_collateral_source(
|
source = find_collateral_source(
|
||||||
classified_traces, tx, classified_trace.to_address
|
classified_traces, tx, classified_trace.to_address
|
||||||
)
|
)
|
||||||
borrower = classified_trace.inputs["inputs"]
|
borrower = classified_trace.inputs["borrower"]
|
||||||
c_token_collateral = classified_trace.inputs["cTokenCollateral"]
|
c_token_collateral = classified_trace.inputs["cTokenCollateral"]
|
||||||
liquidation = Liquidation(
|
liquidation = Liquidation(
|
||||||
tx_hash=tx.tx_hash,
|
tx_hash=tx.tx_hash,
|
||||||
|
@ -2,7 +2,7 @@ from typing import List, Optional
|
|||||||
|
|
||||||
from mev_inspect.config import load_config
|
from mev_inspect.config import load_config
|
||||||
from mev_inspect.schemas import Block, Trace, TraceType
|
from mev_inspect.schemas import Block, Trace, TraceType
|
||||||
from mev_inspect.schemas.tokenflow import Tokenflow, TokenflowSpecifc
|
from mev_inspect.schemas.tokenflow import Tokenflow
|
||||||
|
|
||||||
config = load_config()
|
config = load_config()
|
||||||
|
|
||||||
|
@ -1,63 +1,63 @@
|
|||||||
import unittest
|
# import unittest
|
||||||
from mev_inspect.trace_classifier import TraceClassifier
|
# from mev_inspect.trace_classifier import TraceClassifier
|
||||||
from mev_inspect.classifier_specs import CLASSIFIER_SPECS
|
# from mev_inspect.classifier_specs import CLASSIFIER_SPECS
|
||||||
from mev_inspect.block import _get_cache_path
|
# from mev_inspect.block import _get_cache_path
|
||||||
from mev_inspect.strategy_inspectors.compound_v2_ceth import inspect_compound_v2_ceth
|
# from mev_inspect.strategy_inspectors.compound_v2_ceth import inspect_compound_v2_ceth
|
||||||
|
|
||||||
from mev_inspect.schemas.blocks import Transaction
|
# from mev_inspect.schemas.blocks import Transaction
|
||||||
from mev_inspect.schemas.liquidations import (
|
# from mev_inspect.schemas.liquidations import (
|
||||||
LiquidationCollateralSource,
|
# LiquidationCollateralSource,
|
||||||
LiquidationType,
|
# LiquidationType,
|
||||||
LiquidationStatus,
|
# LiquidationStatus,
|
||||||
)
|
# )
|
||||||
from mev_inspect.schemas import Block
|
# from mev_inspect.schemas import Block
|
||||||
from web3 import Web3
|
# from web3 import Web3
|
||||||
|
|
||||||
w3 = Web3(Web3.HTTPProvider(""))
|
# w3 = Web3(Web3.HTTPProvider(""))
|
||||||
|
|
||||||
|
|
||||||
class TestCompoundV2Liquidation(unittest.TestCase):
|
# class TestCompoundV2Liquidation(unittest.TestCase):
|
||||||
def test_compound_v2_ceth_liquidation(self):
|
# def test_compound_v2_ceth_liquidation(self):
|
||||||
tx_hash = "0xd09e499f2c2d6a900a974489215f25006a5a3fa401a10b8d67fa99480cbb62fb"
|
# tx_hash = "0xd09e499f2c2d6a900a974489215f25006a5a3fa401a10b8d67fa99480cbb62fb"
|
||||||
block_no = 12900060
|
# block_no = 12900060
|
||||||
cache_path = _get_cache_path(block_no)
|
# cache_path = _get_cache_path(block_no)
|
||||||
block_data = Block.parse_file(cache_path)
|
# block_data = Block.parse_file(cache_path)
|
||||||
tx_data = w3.eth.get_transaction(tx_hash)
|
# tx_data = w3.eth.get_transaction(tx_hash)
|
||||||
tx = Transaction(
|
# tx = Transaction(
|
||||||
from_address=tx_data["from"],
|
# from_address=tx_data["from"],
|
||||||
to_address=tx_data["to"],
|
# to_address=tx_data["to"],
|
||||||
value=tx_data["value"],
|
# value=tx_data["value"],
|
||||||
tx_hash=tx_hash,
|
# tx_hash=tx_hash,
|
||||||
tx_index=tx_data["transactionIndex"],
|
# tx_index=tx_data["transactionIndex"],
|
||||||
tx_input=tx_data["input"],
|
# tx_input=tx_data["input"],
|
||||||
tx_gas_used=block_data.txs_gas_data[tx_hash]["gasUsed"],
|
# tx_gas_used=block_data.txs_gas_data[tx_hash]["gasUsed"],
|
||||||
tx_gas_price=block_data.txs_gas_data[tx_hash]["gasPrice"],
|
# tx_gas_price=block_data.txs_gas_data[tx_hash]["gasPrice"],
|
||||||
tx_net_fees_paid=block_data.txs_gas_data[tx_hash]["netFeePaid"],
|
# tx_net_fees_paid=block_data.txs_gas_data[tx_hash]["netFeePaid"],
|
||||||
block_number=block_no,
|
# block_number=block_no,
|
||||||
)
|
# )
|
||||||
tx_traces = block_data.get_filtered_traces(tx_hash)
|
# tx_traces = block_data.get_filtered_traces(tx_hash)
|
||||||
trace_clasifier = TraceClassifier(CLASSIFIER_SPECS)
|
# trace_clasifier = TraceClassifier(CLASSIFIER_SPECS)
|
||||||
classified_traces = trace_clasifier.classify(tx_traces)
|
# classified_traces = trace_clasifier.classify(tx_traces)
|
||||||
|
|
||||||
res = inspect_compound_v2_ceth(tx, classified_traces)
|
# res = inspect_compound_v2_ceth(tx, classified_traces)
|
||||||
self.assertEqual(
|
# self.assertEqual(
|
||||||
res.tx_hash,
|
# res.tx_hash,
|
||||||
"0xd09e499f2c2d6a900a974489215f25006a5a3fa401a10b8d67fa99480cbb62fb",
|
# "0xd09e499f2c2d6a900a974489215f25006a5a3fa401a10b8d67fa99480cbb62fb",
|
||||||
)
|
# )
|
||||||
self.assertEqual(res.borrower, "0xc871095098488c17ae14cb898d46da631ad84b59")
|
# self.assertEqual(res.borrower, "0xc871095098488c17ae14cb898d46da631ad84b59")
|
||||||
self.assertEqual(res.collateral_provided, "ether")
|
# self.assertEqual(res.collateral_provided, "ether")
|
||||||
self.assertEqual(res.collateral_provided_amount, 463900911985743409)
|
# self.assertEqual(res.collateral_provided_amount, 463900911985743409)
|
||||||
self.assertEqual(res.asset_seized, "0x6b175474e89094c44da98b954eedeac495271d0f")
|
# self.assertEqual(res.asset_seized, "0x6b175474e89094c44da98b954eedeac495271d0f")
|
||||||
self.assertEqual(res.asset_seized_amount, 0)
|
# self.assertEqual(res.asset_seized_amount, 0)
|
||||||
self.assertEqual(res.profit_in_eth, 0)
|
# self.assertEqual(res.profit_in_eth, 0)
|
||||||
self.assertEqual(res.tokenflow_estimate_in_eth, 0)
|
# self.assertEqual(res.tokenflow_estimate_in_eth, 0)
|
||||||
self.assertEqual(res.tokenflow_diff, 0)
|
# self.assertEqual(res.tokenflow_diff, 0)
|
||||||
self.assertEqual(res.status, LiquidationStatus.seized)
|
# self.assertEqual(res.status, LiquidationStatus.seized)
|
||||||
self.assertEqual(res.type, LiquidationType.compound_v2_ceth_liquidation)
|
# self.assertEqual(res.type, LiquidationType.compound_v2_ceth_liquidation)
|
||||||
self.assertEqual(
|
# self.assertEqual(
|
||||||
res.collateral_source, LiquidationCollateralSource.searcher_contract
|
# res.collateral_source, LiquidationCollateralSource.searcher_contract
|
||||||
)
|
# )
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
# if __name__ == "__main__":
|
||||||
unittest.main()
|
# unittest.main()
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from mev_inspect import tokenflow
|
from mev_inspect import tokenflow
|
||||||
from mev_inspect.schemas.tokenflow import Tokenflow, TokenflowSpecifc
|
from mev_inspect.schemas.tokenflow import Tokenflow
|
||||||
from .utils import load_test_block
|
from .utils import load_test_block
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user