Remove ETH / ERC20 transfer distinction

This commit is contained in:
Luke Van Seters 2021-10-11 15:28:08 -07:00
parent f7fbd97a50
commit 378f5b248e
9 changed files with 72 additions and 101 deletions

View File

@ -11,8 +11,8 @@ from mev_inspect.schemas.classified_traces import (
Protocol,
)
from mev_inspect.schemas.transfers import ERC20Transfer
from mev_inspect.schemas.liquidations import Liquidation
from mev_inspect.transfers import get_transfer
AAVE_CONTRACT_ADDRESSES: List[str] = [
# AAVE Proxy
@ -76,10 +76,12 @@ def _get_liquidator_payback(
for child in child_traces:
if child.classification == Classification.transfer:
child_transfer = ERC20Transfer.from_trace(child)
child_transfer = get_transfer(child)
if (child_transfer.to_address == liquidator) and (
child.from_address in AAVE_CONTRACT_ADDRESSES
if (
child_transfer is not None
and child_transfer.to_address == liquidator
and child.from_address in AAVE_CONTRACT_ADDRESSES
):
return child_transfer.amount

View File

@ -3,13 +3,13 @@ from mev_inspect.schemas.classifiers import (
ClassifierSpec,
TransferClassifier,
)
from mev_inspect.schemas.transfers import ERC20Transfer
from mev_inspect.schemas.transfers import Transfer
class ERC20TransferClassifier(TransferClassifier):
@staticmethod
def get_transfer(trace: DecodedCallTrace) -> ERC20Transfer:
return ERC20Transfer(
def get_transfer(trace: DecodedCallTrace) -> Transfer:
return Transfer(
block_number=trace.block_number,
transaction_hash=trace.transaction_hash,
trace_address=trace.trace_address,

View File

@ -6,13 +6,13 @@ from mev_inspect.schemas.classifiers import (
DecodedCallTrace,
TransferClassifier,
)
from mev_inspect.schemas.transfers import ERC20Transfer
from mev_inspect.schemas.transfers import Transfer
class WethTransferClassifier(TransferClassifier):
@staticmethod
def get_transfer(trace: DecodedCallTrace) -> ERC20Transfer:
return ERC20Transfer(
def get_transfer(trace: DecodedCallTrace) -> Transfer:
return Transfer(
block_number=trace.block_number,
transaction_hash=trace.transaction_hash,
trace_address=trace.trace_address,

View File

@ -2,7 +2,7 @@ import json
from typing import List
from mev_inspect.models.transfers import TransferModel
from mev_inspect.schemas.transfers import ERC20Transfer
from mev_inspect.schemas.transfers import Transfer
def delete_transfers_for_block(
@ -20,7 +20,7 @@ def delete_transfers_for_block(
def write_transfers(
db_session,
transfers: List[ERC20Transfer],
transfers: List[Transfer],
) -> None:
models = [TransferModel(**json.loads(transfer.json())) for transfer in transfers]

View File

@ -4,7 +4,7 @@ from typing import Dict, List, Optional, Type
from pydantic import BaseModel
from .classified_traces import Classification, DecodedCallTrace, Protocol
from .transfers import ERC20Transfer
from .transfers import Transfer
class Classifier(ABC):
@ -21,7 +21,7 @@ class TransferClassifier(Classifier):
@staticmethod
@abstractmethod
def get_transfer(trace: DecodedCallTrace) -> ERC20Transfer:
def get_transfer(trace: DecodedCallTrace) -> Transfer:
raise NotImplementedError()

View File

@ -1,8 +1,9 @@
from typing import List, TypeVar
from typing import List
from pydantic import BaseModel
from .classified_traces import Classification, ClassifiedTrace, Protocol
ETH_TOKEN_ADDRESS = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"
class Transfer(BaseModel):
@ -12,50 +13,4 @@ class Transfer(BaseModel):
from_address: str
to_address: str
amount: int
# To preserve the specific Transfer type
TransferGeneric = TypeVar("TransferGeneric", bound="Transfer")
class EthTransfer(Transfer):
@classmethod
def from_trace(cls, trace: ClassifiedTrace) -> "EthTransfer":
return cls(
block_number=trace.block_number,
transaction_hash=trace.transaction_hash,
trace_address=trace.trace_address,
amount=trace.value,
to_address=trace.to_address,
from_address=trace.from_address,
)
class ERC20Transfer(Transfer):
token_address: str
@classmethod
def from_trace(cls, trace: ClassifiedTrace) -> "ERC20Transfer":
if trace.classification != Classification.transfer or trace.inputs is None:
raise ValueError("Invalid transfer")
if trace.protocol == Protocol.weth:
return cls(
block_number=trace.block_number,
transaction_hash=trace.transaction_hash,
trace_address=trace.trace_address,
amount=trace.inputs["wad"],
to_address=trace.inputs["dst"],
from_address=trace.from_address,
token_address=trace.to_address,
)
else:
return cls(
block_number=trace.block_number,
transaction_hash=trace.transaction_hash,
trace_address=trace.trace_address,
amount=trace.inputs["amount"],
to_address=trace.inputs["recipient"],
from_address=trace.inputs.get("sender", trace.from_address),
token_address=trace.to_address,
)

View File

@ -8,11 +8,11 @@ from mev_inspect.schemas.classified_traces import (
)
from mev_inspect.schemas.classifiers import SwapClassifier
from mev_inspect.schemas.swaps import Swap
from mev_inspect.schemas.transfers import ERC20Transfer
from mev_inspect.schemas.transfers import Transfer
from mev_inspect.traces import get_traces_by_transaction_hash
from mev_inspect.transfers import (
get_child_transfers,
get_erc20_transfer,
get_transfer,
filter_transfers,
remove_child_transfers_of_transfers,
)
@ -31,14 +31,14 @@ def _get_swaps_for_transaction(traces: List[ClassifiedTrace]) -> List[Swap]:
ordered_traces = list(sorted(traces, key=lambda t: t.trace_address))
swaps: List[Swap] = []
prior_transfers: List[ERC20Transfer] = []
prior_transfers: List[Transfer] = []
for trace in ordered_traces:
if not isinstance(trace, DecodedCallTrace):
continue
elif trace.classification == Classification.transfer:
transfer = get_erc20_transfer(trace)
transfer = get_transfer(trace)
if transfer is not None:
prior_transfers.append(transfer)
@ -63,8 +63,8 @@ def _get_swaps_for_transaction(traces: List[ClassifiedTrace]) -> List[Swap]:
def _parse_swap(
trace: DecodedCallTrace,
prior_transfers: List[ERC20Transfer],
child_transfers: List[ERC20Transfer],
prior_transfers: List[Transfer],
child_transfers: List[Transfer],
) -> Optional[Swap]:
pool_address = trace.to_address
recipient_address = _get_recipient_address(trace)

View File

@ -3,40 +3,57 @@ from typing import Dict, List, Optional, Sequence
from mev_inspect.classifiers.specs import get_classifier
from mev_inspect.schemas.classifiers import TransferClassifier
from mev_inspect.schemas.classified_traces import (
Classification,
ClassifiedTrace,
DecodedCallTrace,
)
from mev_inspect.schemas.transfers import ERC20Transfer, EthTransfer, TransferGeneric
from mev_inspect.schemas.transfers import ETH_TOKEN_ADDRESS, Transfer
from mev_inspect.traces import is_child_trace_address, get_child_traces
def get_eth_transfers(traces: List[ClassifiedTrace]) -> List[EthTransfer]:
def get_transfers(traces: List[ClassifiedTrace]) -> List[Transfer]:
transfers = []
for trace in traces:
if trace.value is not None and trace.value > 0:
transfers.append(EthTransfer.from_trace(trace))
transfer = get_transfer(trace)
if transfer is not None:
transfers.append(transfer)
return transfers
def get_transfers(traces: List[ClassifiedTrace]) -> List[ERC20Transfer]:
transfers = []
def get_eth_transfers(traces: List[ClassifiedTrace]) -> List[Transfer]:
transfers = get_transfers(traces)
for trace in traces:
if isinstance(trace, DecodedCallTrace):
transfer = get_erc20_transfer(trace)
if transfer is not None:
transfers.append(transfer)
return transfers
return [
transfer
for transfer in transfers
if transfer.token_address == ETH_TOKEN_ADDRESS
]
def get_erc20_transfer(trace: DecodedCallTrace) -> Optional[ERC20Transfer]:
if not isinstance(trace, DecodedCallTrace):
return None
def get_transfer(trace: ClassifiedTrace) -> Optional[Transfer]:
if trace.value is not None and trace.value > 0:
return _build_eth_transfer(trace)
if isinstance(trace, DecodedCallTrace):
return _build_erc20_transfer(trace)
return None
def _build_eth_transfer(trace: ClassifiedTrace) -> Transfer:
return Transfer(
block_number=trace.block_number,
transaction_hash=trace.transaction_hash,
trace_address=trace.trace_address,
amount=trace.value,
to_address=trace.to_address,
from_address=trace.from_address,
token_address=ETH_TOKEN_ADDRESS,
)
def _build_erc20_transfer(trace: DecodedCallTrace) -> Optional[Transfer]:
classifier = get_classifier(trace)
if classifier is not None and issubclass(classifier, TransferClassifier):
return classifier.get_transfer(trace)
@ -48,25 +65,22 @@ def get_child_transfers(
transaction_hash: str,
parent_trace_address: List[int],
traces: List[ClassifiedTrace],
) -> List[ERC20Transfer]:
) -> List[Transfer]:
child_transfers = []
for child_trace in get_child_traces(transaction_hash, parent_trace_address, traces):
if child_trace.classification == Classification.transfer and isinstance(
child_trace, DecodedCallTrace
):
transfer = get_erc20_transfer(child_trace)
if transfer is not None:
child_transfers.append(transfer)
transfer = get_transfer(child_trace)
if transfer is not None:
child_transfers.append(transfer)
return child_transfers
def filter_transfers(
transfers: Sequence[TransferGeneric],
transfers: Sequence[Transfer],
to_address: Optional[str] = None,
from_address: Optional[str] = None,
) -> List[TransferGeneric]:
) -> List[Transfer]:
filtered_transfers = []
for transfer in transfers:
@ -82,8 +96,8 @@ def filter_transfers(
def remove_child_transfers_of_transfers(
transfers: List[ERC20Transfer],
) -> List[ERC20Transfer]:
transfers: List[Transfer],
) -> List[Transfer]:
updated_transfers = []
transfer_addresses_by_transaction: Dict[str, List[List[int]]] = {}

View File

@ -1,4 +1,4 @@
from mev_inspect.schemas.transfers import ERC20Transfer
from mev_inspect.schemas.transfers import Transfer
from mev_inspect.transfers import remove_child_transfers_of_transfers
@ -13,7 +13,7 @@ def test_remove_child_transfers_of_transfers(get_transaction_hashes, get_address
third_token_address,
] = get_addresses(5)
outer_transfer = ERC20Transfer(
outer_transfer = Transfer(
block_number=123,
transaction_hash=transaction_hash,
trace_address=[0],
@ -23,7 +23,7 @@ def test_remove_child_transfers_of_transfers(get_transaction_hashes, get_address
token_address=first_token_address,
)
inner_transfer = ERC20Transfer(
inner_transfer = Transfer(
**{
**outer_transfer.dict(),
**dict(
@ -33,7 +33,7 @@ def test_remove_child_transfers_of_transfers(get_transaction_hashes, get_address
}
)
other_transfer = ERC20Transfer(
other_transfer = Transfer(
block_number=123,
transaction_hash=transaction_hash,
trace_address=[1],
@ -43,7 +43,7 @@ def test_remove_child_transfers_of_transfers(get_transaction_hashes, get_address
token_address=third_token_address,
)
separate_transaction_transfer = ERC20Transfer(
separate_transaction_transfer = Transfer(
**{
**inner_transfer.dict(),
**dict(transaction_hash=other_transaction_hash),