Skip to content
This repository has been archived by the owner on Nov 27, 2024. It is now read-only.

Add JIT Liquidity Classifier #292

Open
wants to merge 45 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
a509f10
Initial JIT Liquidity Classifier Commit
elicbarbieri Apr 20, 2022
0a5518f
Adding typing Union[] to _parse_jit_liquidity_instances and improving…
elicbarbieri Apr 20, 2022
839bced
error skipping invalid/un-implemented JIT liquidity instances
elicbarbieri Apr 20, 2022
4f03d10
Clarifying logic of recursive _get_bot_address
elicbarbieri Apr 20, 2022
2fdc21c
Actually reading the docs and installing the pre-commit
elicbarbieri Apr 20, 2022
ed4dbe0
Refactoring to remove while loops, improve logic, and improve error-h…
elicbarbieri Apr 25, 2022
49dc359
adding alembic migration to create table for JITLiquidityModel
elicbarbieri Apr 25, 2022
293c59d
Adding tests for CRV-WETH JIT & get_net_transfers()
elicbarbieri Apr 29, 2022
6701ff4
Finalizing Docstrings and modifying to use search dict instead of list
elicbarbieri May 2, 2022
ff861fc
removing KeyError cases from _get_bot_address
elicbarbieri May 2, 2022
404cace
Adding __tablename__ to jit_liquidity model
elicbarbieri May 3, 2022
07e0004
correcting error in alembic migration
elicbarbieri May 5, 2022
250bb43
moving alembic upgrade and downgrade functions. correcting error when…
elicbarbieri May 5, 2022
f876451
removing swaps fk from jit_liquidity_swaps join table
elicbarbieri May 5, 2022
15ee8f8
fixing spelling error in crud file and adding nullable field to model
elicbarbieri May 6, 2022
8ce43d2
adding tests for single token mint case and rewriting jit classifier …
elicbarbieri May 6, 2022
4969aed
adding extra check to jit_classifier where burn_tx_hash != mint_tx_hash
elicbarbieri May 7, 2022
01049c5
refactoring jit_liquidity to be more readable and improving error han…
elicbarbieri May 7, 2022
aa0a212
adding test for block 14685550 with complex jit attack on popsicle fi…
elicbarbieri May 7, 2022
811ae05
adding continue on trace error
elicbarbieri May 7, 2022
add06d1
Adding migrations for JIT liquidity tables
elicbarbieri May 10, 2022
c7e5b91
Splitting PR into classifier and migrations
elicbarbieri May 10, 2022
3eeaf86
Initial JIT Liquidity Classifier Commit
elicbarbieri Apr 20, 2022
7cc5b52
Adding typing Union[] to _parse_jit_liquidity_instances and improving…
elicbarbieri Apr 20, 2022
a475a5f
error skipping invalid/un-implemented JIT liquidity instances
elicbarbieri Apr 20, 2022
be79280
Clarifying logic of recursive _get_bot_address
elicbarbieri Apr 20, 2022
5abfc38
Actually reading the docs and installing the pre-commit
elicbarbieri Apr 20, 2022
e717585
Refactoring to remove while loops, improve logic, and improve error-h…
elicbarbieri Apr 25, 2022
90d9dc9
adding alembic migration to create table for JITLiquidityModel
elicbarbieri Apr 25, 2022
53b69f7
Adding tests for CRV-WETH JIT & get_net_transfers()
elicbarbieri Apr 29, 2022
a3a7cee
Finalizing Docstrings and modifying to use search dict instead of list
elicbarbieri May 2, 2022
6472f04
removing KeyError cases from _get_bot_address
elicbarbieri May 2, 2022
642bec2
Adding __tablename__ to jit_liquidity model
elicbarbieri May 3, 2022
b9c628c
correcting error in alembic migration
elicbarbieri May 5, 2022
9e617f5
moving alembic upgrade and downgrade functions. correcting error when…
elicbarbieri May 5, 2022
04e0050
removing swaps fk from jit_liquidity_swaps join table
elicbarbieri May 5, 2022
e1f59aa
fixing spelling error in crud file and adding nullable field to model
elicbarbieri May 6, 2022
03d1846
adding tests for single token mint case and rewriting jit classifier …
elicbarbieri May 6, 2022
8ea2dd6
adding extra check to jit_classifier where burn_tx_hash != mint_tx_hash
elicbarbieri May 7, 2022
225a1b5
refactoring jit_liquidity to be more readable and improving error han…
elicbarbieri May 7, 2022
5b383c4
adding test for block 14685550 with complex jit attack on popsicle fi…
elicbarbieri May 7, 2022
0bd45a5
adding continue on trace error
elicbarbieri May 7, 2022
25724ea
Splitting PR into classifier and migrations
elicbarbieri May 10, 2022
2eb710b
Merge branch 'add-jit-classifier' of https://github.com/elicbarbieri/…
elicbarbieri May 10, 2022
4f2d178
reformatting after rebase
elicbarbieri May 10, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 43 additions & 0 deletions alembic/versions/a46974a623b3_add_jit_liquidity_table.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"""add_jit_liquidity_table

Revision ID: a46974a623b3
Revises: 5c5375de15fd
Create Date: 2022-05-10 12:36:57.139209

"""
import sqlalchemy as sa
from alembic import op

# revision identifiers, used by Alembic.
revision = "a46974a623b3"
down_revision = "5c5375de15fd"
branch_labels = None
depends_on = None


def upgrade():
op.create_table(
"jit_liquidity",
sa.Column("id", sa.String, primary_key=True),
sa.Column("block_number", sa.Numeric(), nullable=False),
sa.Column("bot_address", sa.String(42), nullable=True),
sa.Column("pool_address", sa.String(42), nullable=False),
sa.Column("token0_address", sa.String(42), nullable=True),
sa.Column("token1_address", sa.String(42), nullable=True),
sa.Column("mint_transaction_hash", sa.String(66), nullable=False),
sa.Column("mint_transaction_trace", sa.ARRAY(sa.Integer)),
sa.Column("burn_transaction_hash", sa.String(66), nullable=False),
sa.Column("burn_transaction_trace", sa.ARRAY(sa.Integer)),
sa.Column("mint_token0_amount", sa.Numeric),
sa.Column("mint_token1_amount", sa.Numeric),
sa.Column("burn_token0_amount", sa.Numeric),
sa.Column("burn_token1_amount", sa.Numeric),
sa.Column("token0_swap_volume", sa.Numeric),
sa.Column("token1_swap_volume", sa.Numeric),
)
op.create_index("ix_jit_liquidity_block_number", "jit_liquidity", ["block_number"])


def downgrade():
op.drop_index("ix_jit_liquidity_block_number")
op.drop_table("jit_liquidity")
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"""add_jit_liquidity_swaps_join_table

Revision ID: c77f5db6105e
Revises: a46974a623b3
Create Date: 2022-05-10 12:37:25.275799

"""
import sqlalchemy as sa
from alembic import op

# revision identifiers, used by Alembic.
revision = "c77f5db6105e"
down_revision = "a46974a623b3"
branch_labels = None
depends_on = None


def upgrade():
op.create_table(
"jit_liquidity_swaps",
sa.Column("created_at", sa.TIMESTAMP, server_default=sa.func.now()),
sa.Column("jit_liquidity_id", sa.String(1024), primary_key=True),
sa.Column("swap_transaction_hash", sa.String(66), primary_key=True),
sa.Column("swap_trace_address", sa.ARRAY(sa.Integer), primary_key=True),
sa.ForeignKeyConstraint(
["jit_liquidity_id"], ["jit_liquidity.id"], ondelete="CASCADE"
),
)


def downgrade():
op.drop_table("jit_liquidity_swaps")
18 changes: 16 additions & 2 deletions mev_inspect/classifiers/specs/uniswap.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from typing import List, Optional

from mev_inspect.classifiers.helpers import create_swap_from_pool_transfers
from mev_inspect.schemas.classifiers import ClassifierSpec, SwapClassifier
from mev_inspect.schemas.classifiers import Classifier, ClassifierSpec, SwapClassifier
from mev_inspect.schemas.swaps import Swap
from mev_inspect.schemas.traces import DecodedCallTrace, Protocol
from mev_inspect.schemas.traces import Classification, DecodedCallTrace, Protocol
from mev_inspect.schemas.transfers import Transfer

UNISWAP_V2_PAIR_ABI_NAME = "UniswapV2Pair"
Expand Down Expand Up @@ -42,6 +42,18 @@ def parse_swap(
return swap


class LiquidityMintClassifier(Classifier):
@staticmethod
def get_classification() -> Classification:
return Classification.liquidity_mint


class LiquidityBurnClassifier(Classifier):
@staticmethod
def get_classification() -> Classification:
return Classification.liquidity_burn


UNISWAP_V3_CONTRACT_SPECS = [
ClassifierSpec(
abi_name="UniswapV3Factory",
Expand Down Expand Up @@ -106,6 +118,8 @@ def parse_swap(
protocol=Protocol.uniswap_v3,
classifiers={
"swap(address,bool,int256,uint160,bytes)": UniswapV3SwapClassifier,
"mint(address,int24,int24,uint128,bytes)": LiquidityMintClassifier,
"burn(int24,int24,uint128)": LiquidityBurnClassifier,
},
),
ClassifierSpec(
Expand Down
75 changes: 75 additions & 0 deletions mev_inspect/crud/jit_liquidity.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
from typing import List
from uuid import uuid4

from mev_inspect.models.jit_liquidity import JITLiquidityModel
from mev_inspect.schemas.jit_liquidity import JITLiquidity

from .shared import delete_by_block_range


def delete_jit_liquidity_for_blocks(
db_session,
after_block_number: int,
before_block_number: int,
) -> None:
delete_by_block_range(
db_session,
JITLiquidityModel,
after_block_number,
before_block_number,
)
db_session.commit()


def write_jit_liquidity(
db_session,
jit_liquidity_instances: List[JITLiquidity],
) -> None:
jit_liquidity_models = []
swap_jit_liquidity_ids = []

for jit_liquidity in jit_liquidity_instances:
jit_liquidity_id = str(uuid4())
jit_liquidity_models.append(
JITLiquidityModel(
id=jit_liquidity_id,
block_number=jit_liquidity.block_number,
bot_address=jit_liquidity.bot_address,
pool_address=jit_liquidity.pool_address,
token0_address=jit_liquidity.token0_address,
token1_address=jit_liquidity.token1_address,
mint_transaction_hash=jit_liquidity.mint_transaction_hash,
mint_transaction_trace=jit_liquidity.mint_trace,
burn_transaction_hash=jit_liquidity.burn_transaction_hash,
burn_transaction_trace=jit_liquidity.burn_trace,
mint_token0_amount=jit_liquidity.mint_token0_amount,
mint_token1_amount=jit_liquidity.mint_token1_amount,
burn_token0_amount=jit_liquidity.burn_token0_amount,
burn_token1_amount=jit_liquidity.burn_token1_amount,
token0_swap_volume=jit_liquidity.token0_swap_volume,
token1_swap_volume=jit_liquidity.token1_swap_volume,
)
)

for swap in jit_liquidity.swaps:
swap_jit_liquidity_ids.append(
{
"jit_liquidity_id": jit_liquidity_id,
"swap_transaction_hash": swap.transaction_hash,
"swap_trace_address": swap.trace_address,
}
)

if len(jit_liquidity_models) > 0:
db_session.bulk_save_objects(jit_liquidity_models)
db_session.execute(
"""
INSERT INTO jit_liquidity_swaps
(jit_liquidity_id, swap_transaction_hash, swap_trace_address)
VALUES
(:jit_liquidity_id, :swap_transaction_hash, :swap_trace_address)
""",
params=swap_jit_liquidity_ids,
)

db_session.commit()
19 changes: 19 additions & 0 deletions mev_inspect/inspect_block.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
from mev_inspect.classifiers.trace import TraceClassifier
from mev_inspect.crud.arbitrages import delete_arbitrages_for_blocks, write_arbitrages
from mev_inspect.crud.blocks import delete_blocks, write_blocks
from mev_inspect.crud.jit_liquidity import (
delete_jit_liquidity_for_blocks,
write_jit_liquidity,
)
from mev_inspect.crud.liquidations import (
delete_liquidations_for_blocks,
write_liquidations,
Expand All @@ -34,13 +38,15 @@
write_classified_traces,
)
from mev_inspect.crud.transfers import delete_transfers_for_blocks, write_transfers
from mev_inspect.jit_liquidity import get_jit_liquidity
from mev_inspect.liquidations import get_liquidations
from mev_inspect.miner_payments import get_miner_payments
from mev_inspect.nft_trades import get_nft_trades
from mev_inspect.punks import get_punk_bid_acceptances, get_punk_bids, get_punk_snipes
from mev_inspect.sandwiches import get_sandwiches
from mev_inspect.schemas.arbitrages import Arbitrage
from mev_inspect.schemas.blocks import Block
from mev_inspect.schemas.jit_liquidity import JITLiquidity
from mev_inspect.schemas.liquidations import Liquidation
from mev_inspect.schemas.miner_payments import MinerPayment
from mev_inspect.schemas.nft_trades import NftTrade
Expand Down Expand Up @@ -100,6 +106,7 @@ async def inspect_many_blocks(
all_miner_payments: List[MinerPayment] = []

all_nft_trades: List[NftTrade] = []
all_jit_liquidity: List[JITLiquidity] = []

for block_number in range(after_block_number, before_block_number):
block = await create_from_block_number(
Expand Down Expand Up @@ -149,6 +156,11 @@ async def inspect_many_blocks(
nft_trades = get_nft_trades(classified_traces)
logger.info(f"Block: {block_number} -- Found {len(nft_trades)} nft trades")

jit_liquidity = get_jit_liquidity(classified_traces, swaps)
logger.info(
f"Block: {block_number} -- Found {len(jit_liquidity)} jit liquidity instances"
)

miner_payments = get_miner_payments(
block.miner, block.base_fee_per_gas, classified_traces, block.receipts
)
Expand All @@ -167,6 +179,8 @@ async def inspect_many_blocks(

all_nft_trades.extend(nft_trades)

all_jit_liquidity.extend(jit_liquidity)

all_miner_payments.extend(miner_payments)

logger.info("Writing data")
Expand Down Expand Up @@ -222,6 +236,11 @@ async def inspect_many_blocks(
)
write_nft_trades(inspect_db_session, all_nft_trades)

delete_jit_liquidity_for_blocks(
inspect_db_session, after_block_number, before_block_number
)
write_jit_liquidity(inspect_db_session, all_jit_liquidity)

delete_miner_payments_for_blocks(
inspect_db_session, after_block_number, before_block_number
)
Expand Down
Loading