From c926fb1e68a81794e3e50551e49d4543fd42be74 Mon Sep 17 00:00:00 2001 From: Vladyslav Burtsevych Date: Thu, 5 Feb 2026 16:09:35 +0100 Subject: [PATCH 1/4] add: new logic for lp programs --- .gitignore | 3 +- data/lp_snapshot.json | 269 +++++++++++++++++++++++++++++++++++ src/daily_points_v2.py | 59 +++----- src/utils/get_points_data.py | 36 +++++ 4 files changed, 329 insertions(+), 38 deletions(-) create mode 100644 data/lp_snapshot.json create mode 100644 src/utils/get_points_data.py diff --git a/.gitignore b/.gitignore index 81186bd..fd235b5 100644 --- a/.gitignore +++ b/.gitignore @@ -2,4 +2,5 @@ data/* .venv/ __pycache__/ .env -!data/lp_balances_snapshot.json \ No newline at end of file +!data/lp_balances_snapshot.json +!data/lp_snapshot.json \ No newline at end of file diff --git a/data/lp_snapshot.json b/data/lp_snapshot.json new file mode 100644 index 0000000..323b8ed --- /dev/null +++ b/data/lp_snapshot.json @@ -0,0 +1,269 @@ +{ + "points_program_start_block": 23985731, + "snapshot": { + "0xa95584c820b5bc990a0572df4faba7fb9f4e210b": [ + { + "balance": 5000000000000000, + "lp_start_date": "2025-11-14" + } + ], + "0x6f9bb7e454f5b3eb2310343f0e99269dc2bb8a1d": [ + { + "balance": 102819000000000000000, + "lp_start_date": "2025-12-02" + } + ], + "0x290ca510021d18699b268f133813f6262a650d94": [ + { + "balance": 2000000000000000000, + "lp_start_date": "2025-11-17" + } + ], + "0xd2c2e84501c63b7b9897df063288d67060119c99": [ + { + "balance": 40000000000000000000, + "lp_start_date": "2025-11-18" + }, + { + "balance": 40000000000000000000, + "lp_start_date": "2026-02-17" + } + ], + "0x12667125770eb9fb46c48db659d3275e8fcd2ed7": [ + { + "balance": 39000000000000000000, + "lp_start_date": "2025-12-02" + } + ], + "0x9ab5b54092a1596a32127163b7b0176445eb1b0a": [ + { + "balance": 36701000000000000000, + "lp_start_date": "2025-11-24" + }, + { + "balance": 36701000000000000000, + "lp_start_date": "2026-02-23" + } + ], + "0xdc6447010c602bbcbdbe2aaff27d24af55fe5b75": [ + { + "balance": 24910000000000000000, + "lp_start_date": "2025-11-29" + } + ], + "0x39d10a4ad72a9b5bf7f1994233fdc331b01c685b": [ + { + "balance": 1002000000000000000, + "lp_start_date": "2025-11-15" + } + ], + "0x91a98fd033434adf63223f88064c95a89e08061c": [ + { + "balance": 8003750565999172549, + "lp_start_date": "2025-11-13" + } + ], + "0x202065dfb813295d0b095a39e36e3b3296210505": [ + { + "balance": 534187211964517143, + "lp_start_date": "2025-12-02" + } + ], + "0x758e5c5c4dd4c6aa1384f0495656a4f7c2f49ec3": [ + { + "balance": 134000000000000000, + "lp_start_date": "2025-11-17" + } + ], + "0xede66ed0fca1a9ebb052cce681c89d7535408ccf": [ + { + "balance": 329887899954383005, + "lp_start_date": "2025-11-17" + } + ], + "0xa0b14f6fe7f647e84b4ac954036865330a9eac5c": [ + { + "balance": 80000000000000000, + "lp_start_date": "2025-11-17" + } + ], + "0x188a7c5b071c01ad31ad80ae7fc28b1b6f389fd6": [ + { + "balance": 32000000000000000000, + "lp_start_date": "2025-11-17" + }, + { + "balance": 32000000000000000000, + "lp_start_date": "2026-02-16" + } + ], + "0x73afef607da2dbd27bd9c83e9e9297ae9ca1fd2b": [ + { + "balance": 25000000000000000000, + "lp_start_date": "2025-11-18" + } + ], + "0x54b3ff56f75671d91d85d44bccedbc9179e09afc": [ + { + "balance": 25000000000000000000, + "lp_start_date": "2025-11-18" + } + ], + "0x5b191f5a2b4a867c4ed71858daccc51fc59c69c0": [ + { + "balance": 30000000000000000000, + "lp_start_date": "2025-11-18" + }, + { + "balance": 30000000000000000000, + "lp_start_date": "2026-02-17" + } + ], + "0xfb40932271fc9db9dbf048e80697e2da4aa57250": [ + { + "balance": 25000000000000000000, + "lp_start_date": "2025-11-18" + } + ], + "0xd5f4cbfadb349be5dba580f9360eb6867a1d590e": [ + { + "balance": 29700000000000000000, + "lp_start_date": "2025-11-28" + } + ], + "0x0450a946a93cf6f81fd72f1e85e16a8826bc9c4d": [ + { + "balance": 25000000000000000000, + "lp_start_date": "2025-11-19" + } + ], + "0xedf3af29040e069a4cbd6e13fbead2500733f2b1": [ + { + "balance": 35000000000000000000, + "lp_start_date": "2025-11-19" + }, + { + "balance": 45000000000000000000, + "lp_start_date": "2026-02-18" + } + ], + "0x8a252b597856b06b3e7efe5d798d73b3c5fbf5ca": [ + { + "balance": 25000000000000000000, + "lp_start_date": "2025-11-19" + }, + { + "balance": 25000000000000000000, + "lp_start_date": "2026-02-18" + } + ], + "0xa52af0e35970783f587b77f7b8db94871435009c": [ + { + "balance": 49918800000000000000, + "lp_start_date": "2025-11-22" + }, + { + "balance": 49918800000000000000, + "lp_start_date": "2026-02-21" + } + ], + "0xb378273190f974e017d13db074976d55f57e0d20": [ + { + "balance": 50000000000000000000, + "lp_start_date": "2025-11-20" + }, + { + "balance": 50000000000000000000, + "lp_start_date": "2026-02-19" + } + ], + "0xdf516f0df67b53f9fc0d4c443a9b07da4ac3174d": [ + { + "balance": 25000000000000000000, + "lp_start_date": "2025-11-20" + }, + { + "balance": 25000000000000000000, + "lp_start_date": "2026-02-19" + } + ], + "0xc3cb47f1d74abc82cc9acd748c9c6714f9c77eff": [ + { + "balance": 25000000000000000000, + "lp_start_date": "2025-11-21" + } + ], + "0x9bcd43b2f6f43cb26032edf584f9e511091f83b0": [ + { + "balance": 25000000000000000000, + "lp_start_date": "2025-11-24" + } + ], + "0x588058a144e22d96e235a5aab6e81c9a5749538e": [ + { + "balance": 34900000000000000000, + "lp_start_date": "2025-11-25" + }, + { + "balance": 34900000000000000000, + "lp_start_date": "2026-02-24" + } + ], + "0xe4e8d412e3dce3357bb420ec24e51f6bcc1a1bc0": [ + { + "balance": 50000000000000000000, + "lp_start_date": "2025-11-27" + } + ], + "0x6c153feae296dd6f0249323cf597724a9ebfff33": [ + { + "balance": 91300000000000000000, + "lp_start_date": "2025-11-28" + } + ], + "0x5fe0cdf0b1c84cd4a92cec746c84816a3a8b21ef": [ + { + "balance": 25000000000000000000, + "lp_start_date": "2025-11-28" + } + ], + "0xdb4efc647a72ed5fb03c20143b85657dafb6a039": [ + { + "balance": 99700000000000000000, + "lp_start_date": "2025-11-29" + }, + { + "balance": 99700000000000000000, + "lp_start_date": "2026-02-28" + } + ], + "0x9b029d74e8770b8a7a88670f5ec69c3c6d33f0e2": [ + { + "balance": 24500000000000000000, + "lp_start_date": "2025-11-30" + } + ], + "0x96fe4e4cd275f1f39eea9d6184447c12006b8536": [ + { + "balance": 29870000000000000000, + "lp_start_date": "2025-12-02" + }, + { + "balance": 29870000000000000000, + "lp_start_date": "2026-03-03" + } + ], + "0x05dac02c4c226da6824e0fd2a944c97ab6a34c5d": [ + { + "balance": 25050000000000000000, + "lp_start_date": "2025-12-02" + } + ], + "0x10B58e5B7eC83E3c0B9e8b3e21Ec335931965B50": [ + { + "balance": 3500000000000000000, + "lp_start_date": "2026-01-26" + } + ] + } +} \ No newline at end of file diff --git a/src/daily_points_v2.py b/src/daily_points_v2.py index 3bf4203..da41e18 100644 --- a/src/daily_points_v2.py +++ b/src/daily_points_v2.py @@ -14,6 +14,7 @@ get_end_block_for_day, get_day_date, ) +from .utils.get_points_data import get_points_data, LpSnapshot from datetime import datetime ZERO_ADDRESS = "0x" + "0" * 40 @@ -52,36 +53,27 @@ def get_user_state_at_day(day_index, state_key): class DailyPointsProcessor: def __init__( self, - lp_balances_snapshot: Dict[str, UserState], - lp_balances_snapshot_start_block: int, + lp_snapshot: LpSnapshot, + points_program_start_block: int, ): - self.lp_balances_snapshot = lp_balances_snapshot - self.lp_balances_snapshot_start_block = lp_balances_snapshot_start_block + self.lp_snapshot = lp_snapshot + self.points_program_start_block = points_program_start_block def get_balance_excluding_snapshot(self, address, user_state, date_unparsed) -> int: - if address not in self.lp_balances_snapshot.keys(): + if address not in self.lp_snapshot.keys(): return user_state.balance - snapshot_entering_day_unparsed = self.lp_balances_snapshot[ - address - ].last_positive_balance_update_day - - if snapshot_entering_day_unparsed == "": - if self.lp_balances_snapshot[address].balance > 0: - raise ValueError( - f"User {address} has balance {self.lp_balances_snapshot[address].balance} but no last positive balance update day" - ) - return user_state.balance - - snapshot_entering_day = datetime.fromisoformat( - snapshot_entering_day_unparsed - ).date() - + balance_to_exclude = 0 date = datetime.fromisoformat(date_unparsed).date() + for program in self.lp_snapshot[address].lp_programs: + days_since_lp_start = (date - program.lp_start_date).days + if ( + days_since_lp_start <= LP_PROGRAM_DURATION_DAYS + and days_since_lp_start >= 0 + ): + balance_to_exclude += program.balance - if (date - snapshot_entering_day).days > LP_PROGRAM_DURATION_DAYS: - return user_state.balance - return max(0, user_state.balance - self.lp_balances_snapshot[address].balance) + return max(0, user_state.balance - balance_to_exclude) def give_points_for_user_state(self, user_state, points, date) -> Dict[str, Points]: for address, user_state in user_state.items(): @@ -111,7 +103,7 @@ def get_points(self, day_index) -> Dict[str, Points]: events = block_number_to_events[block_number] for event in events: user_state = process_event_above_user_state(event, user_state, date) - if block_number > self.lp_balances_snapshot_start_block: + if block_number > self.points_program_start_block: points = self.give_points_for_user_state(user_state, points, date) validate_end_state(day_index, user_state) @@ -151,6 +143,7 @@ def process_points(self) -> List[Dict]: return results + def validate_end_state(day_index, result_user_balances): cached_user_balances = get_user_state_at_day(day_index, "end_state") @@ -193,19 +186,11 @@ def validate_end_state(day_index, result_user_balances): print(f"Verified end state for day {day_index}") -def load_lp_balances_snapshot_data(): - """Load LP balances snapshot data from file and return as tuple (snapshot, start_block).""" - lp_balances_snapshot_data_dir = "data/lp_balances_snapshot.json" - lp_balances_snapshot = get_user_state(lp_balances_snapshot_data_dir, "start_state") - lp_balances_snapshot_start_block = json.load( - open(lp_balances_snapshot_data_dir, "r") - )["start_block"] - return lp_balances_snapshot, lp_balances_snapshot_start_block - def process_points(): - lp_balances_snapshot, lp_balances_snapshot_start_block = load_lp_balances_snapshot_data() - processor = DailyPointsProcessor(lp_balances_snapshot, lp_balances_snapshot_start_block) - processor.process_points() + points_program_start_block, lp_snapshot = get_points_data() + processor = DailyPointsProcessor(lp_snapshot, points_program_start_block) + processor.process_points() + if __name__ == "__main__": - process_points() \ No newline at end of file + process_points() diff --git a/src/utils/get_points_data.py b/src/utils/get_points_data.py new file mode 100644 index 0000000..68a85ff --- /dev/null +++ b/src/utils/get_points_data.py @@ -0,0 +1,36 @@ +import json +import datetime +from typing import List, Dict + + +class LpProgram: + def __init__(self, balance: int, lp_start_date: datetime.date): + self.balance = balance + self.lp_start_date = lp_start_date + + +class UserLpSnapshot: + def __init__(self, lp_programs: List[LpProgram]): + self.lp_programs = lp_programs + + +type Address = str +type LpSnapshot = Dict[Address, UserLpSnapshot] + + +def get_points_data(): + with open("data/lp_snapshot.json", "r") as f: + raw = json.load(f) + points_program_start_block = raw["points_program_start_block"] + lp_snapshot = { + address.lower(): UserLpSnapshot( + [ + LpProgram( + program["balance"], datetime.date.fromisoformat(program["lp_start_date"]) + ) + for program in lp_programs + ] + ) + for address, lp_programs in raw["snapshot"].items() + } + return points_program_start_block, lp_snapshot From 901f5c1dafdf8d31d639c96434dd6a6baf827122 Mon Sep 17 00:00:00 2001 From: Vladyslav Burtsevych Date: Thu, 5 Feb 2026 14:07:38 +0100 Subject: [PATCH 2/4] fix: check lp integrity fix --- data/lp_snapshot.json | 2 +- src/check_lp_integrity.py | 54 ++++------ test/test_check_lp_integrity.py | 173 ++++++++++++++++---------------- 3 files changed, 107 insertions(+), 122 deletions(-) diff --git a/data/lp_snapshot.json b/data/lp_snapshot.json index 323b8ed..2d5c0b5 100644 --- a/data/lp_snapshot.json +++ b/data/lp_snapshot.json @@ -261,7 +261,7 @@ ], "0x10B58e5B7eC83E3c0B9e8b3e21Ec335931965B50": [ { - "balance": 3500000000000000000, + "balance": 3457909000875908150, "lp_start_date": "2026-01-26" } ] diff --git a/src/check_lp_integrity.py b/src/check_lp_integrity.py index ce6ab4c..e8e0576 100644 --- a/src/check_lp_integrity.py +++ b/src/check_lp_integrity.py @@ -10,54 +10,44 @@ get_day_date, ) from .utils.get_days_amount import get_days_amount +from .utils.get_points_data import get_points_data, LpSnapshot from .daily_points_v2 import LP_PROGRAM_DURATION_DAYS from datetime import datetime from .daily_points_v2 import ( get_user_state_at_day, ) from .utils.process_event_above_user_state import UserState -from .daily_points_v2 import load_lp_balances_snapshot_data import sys class LpIntegrityChecker: def __init__( self, - lp_balances_snapshot: Dict[str, UserState], - lp_balances_snapshot_start_block: int, + lp_snapshot: LpSnapshot, + points_program_start_block: int, ): - self.lp_balances_snapshot = lp_balances_snapshot - self.lp_balances_snapshot_start_block = lp_balances_snapshot_start_block + self.lp_snapshot = lp_snapshot + self.points_program_start_block = points_program_start_block def _validate_lp_integrity(self, users_state, date_unparsed) -> dict[str, bool]: - date = datetime.fromisoformat(date_unparsed) + date = datetime.fromisoformat(date_unparsed).date() result = defaultdict(bool) for address, user_state in users_state.items(): user_balance = user_state.balance - if user_state.last_positive_balance_update_day == "": - if user_balance > 0: - raise ValueError( - f"User {address} has balance {user_balance} but no last positive balance update day" - ) - result[address] = False - continue - try: - lp_entering_day = datetime.fromisoformat( - user_state.last_positive_balance_update_day - ) - except: - print( - f"Error converting {user_state.last_positive_balance_update_day} to datetime" - ) - print(type(user_state.last_positive_balance_update_day)) - raise 1 - if (date - lp_entering_day).days > LP_PROGRAM_DURATION_DAYS: + if address not in self.lp_snapshot: result[address] = False continue - is_integrity_broken = ( - user_balance < self.lp_balances_snapshot[address].balance - ) + balance_to_exclude = 0 + for program in self.lp_snapshot[address].lp_programs: + days_since_lp_start = (date - program.lp_start_date).days + if ( + days_since_lp_start <= LP_PROGRAM_DURATION_DAYS + and days_since_lp_start >= 0 + ): + balance_to_exclude += program.balance + + is_integrity_broken = user_balance < balance_to_exclude result[address] = is_integrity_broken return result @@ -70,8 +60,8 @@ def _check_lp_integrity_at_day( user_state = get_user_state_at_day(day_index, "start_state") date_unparsed = get_day_date(day_index) - # We only need to check blocks after the snapshot start block - start_block = max(start_block, self.lp_balances_snapshot_start_block) + # We only need to check blocks after the points program start block + start_block = max(start_block, self.points_program_start_block) for block_number in range(start_block, end_block + 1): events = block_number_to_events[block_number] for event in events: @@ -119,9 +109,7 @@ def check_lp_integrity(self): if __name__ == "__main__": - lp_balances_snapshot, lp_balances_snapshot_start_block = ( - load_lp_balances_snapshot_data() - ) - checker = LpIntegrityChecker(lp_balances_snapshot, lp_balances_snapshot_start_block) + points_program_start_block, lp_snapshot = get_points_data() + checker = LpIntegrityChecker(lp_snapshot, points_program_start_block) exit_code = checker.check_lp_integrity() sys.exit(exit_code) diff --git a/test/test_check_lp_integrity.py b/test/test_check_lp_integrity.py index 361ae73..c898c94 100644 --- a/test/test_check_lp_integrity.py +++ b/test/test_check_lp_integrity.py @@ -1,169 +1,166 @@ from collections import defaultdict import sys from pathlib import Path -from datetime import datetime, timedelta +from datetime import datetime, timedelta, date from unittest.mock import patch # Add parent directory to path to import modules # sys.path.insert(0, str(Path(__file__).parent.parent)) from src.check_lp_integrity import LpIntegrityChecker from src.utils.process_event_above_user_state import UserState +from src.utils.get_points_data import UserLpSnapshot, LpProgram from src.daily_points_v2 import LP_PROGRAM_DURATION_DAYS +def make_lp_snapshot(entries): + """entries: dict[address, list of (balance, lp_start_date)]""" + return { + addr: UserLpSnapshot([LpProgram(b, d) for b, d in programs]) + for addr, programs in entries.items() + } + + class TestValidateLpIntegrity: def test_balance_above_snapshot_no_integrity_issue(self): """Test that balance above snapshot does not indicate integrity issue""" - snapshot_entry = UserState(balance=100) - snapshot_entry.last_positive_balance_update_day = "2026-01-01" - lp_balances_snapshot = { - "0x1111111111111111111111111111111111111111": snapshot_entry - } - checker = LpIntegrityChecker(lp_balances_snapshot, 0) + lp_snapshot = make_lp_snapshot({ + "0x1111111111111111111111111111111111111111": [(100, date(2026, 1, 1))], + }) + checker = LpIntegrityChecker(lp_snapshot, 0) user_state = { "0x1111111111111111111111111111111111111111": UserState(balance=500) } - user_state["0x1111111111111111111111111111111111111111"].last_positive_balance_update_day = "2026-01-01" - date = "2026-01-15" # Within 90 days + date_str = "2026-01-15" # Within 90 days - result = checker._validate_lp_integrity(user_state, date) + result = checker._validate_lp_integrity(user_state, date_str) assert result["0x1111111111111111111111111111111111111111"] == False # No integrity issue def test_balance_below_snapshot_integrity_broken(self): """Test that balance below snapshot indicates integrity issue""" - snapshot_entry = UserState(balance=500) - snapshot_entry.last_positive_balance_update_day = "2026-01-01" - lp_balances_snapshot = { - "0x2222222222222222222222222222222222222222": snapshot_entry - } - checker = LpIntegrityChecker(lp_balances_snapshot, 0) + lp_snapshot = make_lp_snapshot({ + "0x2222222222222222222222222222222222222222": [(500, date(2026, 1, 1))], + }) + checker = LpIntegrityChecker(lp_snapshot, 0) user_state = { "0x2222222222222222222222222222222222222222": UserState(balance=300) } - user_state["0x2222222222222222222222222222222222222222"].last_positive_balance_update_day = "2026-01-01" - date = "2026-01-15" # Within 90 days + date_str = "2026-01-15" # Within 90 days - result = checker._validate_lp_integrity(user_state, date) + result = checker._validate_lp_integrity(user_state, date_str) assert result["0x2222222222222222222222222222222222222222"] == True # Integrity broken def test_balance_equal_to_snapshot_no_integrity_issue(self): """Test that balance equal to snapshot does not indicate integrity issue""" - snapshot_entry = UserState(balance=300) - snapshot_entry.last_positive_balance_update_day = "2026-01-01" - lp_balances_snapshot = { - "0x3333333333333333333333333333333333333333": snapshot_entry - } - checker = LpIntegrityChecker(lp_balances_snapshot, 0) + lp_snapshot = make_lp_snapshot({ + "0x3333333333333333333333333333333333333333": [(300, date(2026, 1, 1))], + }) + checker = LpIntegrityChecker(lp_snapshot, 0) user_state = { "0x3333333333333333333333333333333333333333": UserState(balance=300) } - user_state["0x3333333333333333333333333333333333333333"].last_positive_balance_update_day = "2026-01-01" - date = "2026-01-15" # Within 90 days + date_str = "2026-01-15" # Within 90 days - result = checker._validate_lp_integrity(user_state, date) + result = checker._validate_lp_integrity(user_state, date_str) assert result["0x3333333333333333333333333333333333333333"] == False # No integrity issue def test_user_outside_90_day_period_not_checked(self): - """Test that users outside 90-day period are not checked""" - snapshot_entry = UserState(balance=100) - snapshot_entry.last_positive_balance_update_day = "2026-01-01" - lp_balances_snapshot = { - "0x4444444444444444444444444444444444444444": snapshot_entry - } - checker = LpIntegrityChecker(lp_balances_snapshot, 0) + """Test that programs outside 90-day window contribute zero to balance_to_exclude""" + lp_snapshot = make_lp_snapshot({ + "0x4444444444444444444444444444444444444444": [(100, date(2026, 1, 1))], + }) + checker = LpIntegrityChecker(lp_snapshot, 0) user_state = { "0x4444444444444444444444444444444444444444": UserState(balance=50) # Below snapshot } - user_state["0x4444444444444444444444444444444444444444"].last_positive_balance_update_day = "2026-01-01" - # Date is more than 90 days after last update - last_update_date = datetime(2026, 1, 1).date() - current_date = last_update_date + timedelta(days=LP_PROGRAM_DURATION_DAYS + 10) - date = str(current_date) + # Date is more than 90 days after LP start → balance_to_exclude = 0 → no integrity issue + lp_start = date(2026, 1, 1) + current_date = lp_start + timedelta(days=LP_PROGRAM_DURATION_DAYS + 10) + date_str = str(current_date) - result = checker._validate_lp_integrity(user_state, date) + result = checker._validate_lp_integrity(user_state, date_str) - # Should not be checked (returns False, meaning no integrity issue to check) assert result["0x4444444444444444444444444444444444444444"] == False - def test_user_empty_last_update_day_with_balance_raises_error(self): - """Test that user with empty last_positive_balance_update_day and balance > 0 raises error""" - snapshot_entry = UserState(balance=100) - snapshot_entry.last_positive_balance_update_day = "2026-01-01" - lp_balances_snapshot = { - "0x5555555555555555555555555555555555555555": snapshot_entry - } - checker = LpIntegrityChecker(lp_balances_snapshot, 0) + def test_user_not_in_snapshot_no_integrity_issue(self): + """Test that user not in lp_snapshot is not flagged (result False)""" + lp_snapshot = make_lp_snapshot({ + "0x9999999999999999999999999999999999999999": [(100, date(2026, 1, 1))], + }) + checker = LpIntegrityChecker(lp_snapshot, 0) + # Different address not in snapshot user_state = { "0x5555555555555555555555555555555555555555": UserState(balance=200) } user_state["0x5555555555555555555555555555555555555555"].last_positive_balance_update_day = "" - date = "2026-01-15" + date_str = "2026-01-15" - try: - checker._validate_lp_integrity(user_state, date) - assert False, "Should have raised ValueError" - except ValueError as e: - assert "balance" in str(e).lower() - assert "last positive balance update day" in str(e).lower() + result = checker._validate_lp_integrity(user_state, date_str) + + assert result["0x5555555555555555555555555555555555555555"] == False def test_multiple_users_mixed_scenarios(self): """Test multiple users with different scenarios""" - snapshot_entry1 = UserState(balance=100) - snapshot_entry1.last_positive_balance_update_day = "2026-01-01" - snapshot_entry2 = UserState(balance=500) - snapshot_entry2.last_positive_balance_update_day = "2026-01-01" - snapshot_entry3 = UserState(balance=200) - snapshot_entry3.last_positive_balance_update_day = "2026-01-01" - - lp_balances_snapshot = { - "0x1111111111111111111111111111111111111111": snapshot_entry1, # Above snapshot - "0x2222222222222222222222222222222222222222": snapshot_entry2, # Below snapshot - "0x3333333333333333333333333333333333333333": snapshot_entry3, # Equal to snapshot - } - checker = LpIntegrityChecker(lp_balances_snapshot, 0) + lp_snapshot = make_lp_snapshot({ + "0x1111111111111111111111111111111111111111": [(100, date(2026, 1, 1))], # Above + "0x2222222222222222222222222222222222222222": [(500, date(2026, 1, 1))], # Below + "0x3333333333333333333333333333333333333333": [(200, date(2026, 1, 1))], # Equal + }) + checker = LpIntegrityChecker(lp_snapshot, 0) user_state = { "0x1111111111111111111111111111111111111111": UserState(balance=300), # Above "0x2222222222222222222222222222222222222222": UserState(balance=400), # Below "0x3333333333333333333333333333333333333333": UserState(balance=200), # Equal } - user_state["0x1111111111111111111111111111111111111111"].last_positive_balance_update_day = "2026-01-01" - user_state["0x2222222222222222222222222222222222222222"].last_positive_balance_update_day = "2026-01-01" - user_state["0x3333333333333333333333333333333333333333"].last_positive_balance_update_day = "2026-01-01" - date = "2026-01-15" + date_str = "2026-01-15" - result = checker._validate_lp_integrity(user_state, date) + result = checker._validate_lp_integrity(user_state, date_str) assert result["0x1111111111111111111111111111111111111111"] == False # No issue - assert result["0x2222222222222222222222222222222222222222"] == True # Integrity broken + assert result["0x2222222222222222222222222222222222222222"] == True # Integrity broken assert result["0x3333333333333333333333333333333333333333"] == False # No issue def test_address_matching(self): """Test that addresses must match exactly between snapshot and user state""" - snapshot_entry = UserState(balance=100) - snapshot_entry.last_positive_balance_update_day = "2026-01-01" - # Use lowercase consistently address = "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd" - lp_balances_snapshot = { - address: snapshot_entry - } - checker = LpIntegrityChecker(lp_balances_snapshot, 0) + lp_snapshot = make_lp_snapshot({ + address: [(100, date(2026, 1, 1))], + }) + checker = LpIntegrityChecker(lp_snapshot, 0) user_state = { address: UserState(balance=50) # Below snapshot } - user_state[address].last_positive_balance_update_day = "2026-01-01" - date = "2026-01-15" + date_str = "2026-01-15" + + result = checker._validate_lp_integrity(user_state, date_str) + + assert result[address] == True + + def test_multiple_programs_same_user(self): + """Test user with multiple LP programs: balance_to_exclude is sum of active programs""" + # One program 100 (active), one 200 (active) → balance_to_exclude = 300 + lp_snapshot = make_lp_snapshot({ + "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa": [ + (100, date(2026, 1, 1)), + (200, date(2026, 1, 10)), + ], + }) + checker = LpIntegrityChecker(lp_snapshot, 0) + + user_state = { + "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa": UserState(balance=250) # Below 300 + } + date_str = "2026-01-15" # Both programs within 90 days - result = checker._validate_lp_integrity(user_state, date) + result = checker._validate_lp_integrity(user_state, date_str) - # Should detect integrity issue - assert result[address] == True \ No newline at end of file + assert result["0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"] == True # 250 < 300 \ No newline at end of file From a11249e3031b2a0627348ba888eb2ea36463d963 Mon Sep 17 00:00:00 2001 From: Vladyslav Burtsevych Date: Thu, 5 Feb 2026 16:05:32 +0100 Subject: [PATCH 3/4] add: tests for custom lp duration --- data/lp_snapshot.json | 144 ++++++++++++------- src/check_lp_integrity.py | 3 +- src/daily_points_v2.py | 4 +- src/utils/get_points_data.py | 12 +- test/test_check_lp_integrity.py | 73 ++++++++-- test/test_points.py | 246 +++++++++++++++++++------------- 6 files changed, 309 insertions(+), 173 deletions(-) diff --git a/data/lp_snapshot.json b/data/lp_snapshot.json index 2d5c0b5..a96fa4d 100644 --- a/data/lp_snapshot.json +++ b/data/lp_snapshot.json @@ -4,265 +4,313 @@ "0xa95584c820b5bc990a0572df4faba7fb9f4e210b": [ { "balance": 5000000000000000, - "lp_start_date": "2025-11-14" + "lp_start_date": "2025-11-14", + "lp_program_duration_days": 90 } ], "0x6f9bb7e454f5b3eb2310343f0e99269dc2bb8a1d": [ { "balance": 102819000000000000000, - "lp_start_date": "2025-12-02" + "lp_start_date": "2025-12-02", + "lp_program_duration_days": 90 } ], "0x290ca510021d18699b268f133813f6262a650d94": [ { "balance": 2000000000000000000, - "lp_start_date": "2025-11-17" + "lp_start_date": "2025-11-17", + "lp_program_duration_days": 90 } ], "0xd2c2e84501c63b7b9897df063288d67060119c99": [ { "balance": 40000000000000000000, - "lp_start_date": "2025-11-18" + "lp_start_date": "2025-11-18", + "lp_program_duration_days": 90 }, { "balance": 40000000000000000000, - "lp_start_date": "2026-02-17" + "lp_start_date": "2026-02-17", + "lp_program_duration_days": 180 } ], "0x12667125770eb9fb46c48db659d3275e8fcd2ed7": [ { "balance": 39000000000000000000, - "lp_start_date": "2025-12-02" + "lp_start_date": "2025-12-02", + "lp_program_duration_days": 90 } ], "0x9ab5b54092a1596a32127163b7b0176445eb1b0a": [ { "balance": 36701000000000000000, - "lp_start_date": "2025-11-24" + "lp_start_date": "2025-11-24", + "lp_program_duration_days": 90 }, { "balance": 36701000000000000000, - "lp_start_date": "2026-02-23" + "lp_start_date": "2026-02-23", + "lp_program_duration_days": 180 } ], "0xdc6447010c602bbcbdbe2aaff27d24af55fe5b75": [ { "balance": 24910000000000000000, - "lp_start_date": "2025-11-29" + "lp_start_date": "2025-11-29", + "lp_program_duration_days": 90 } ], "0x39d10a4ad72a9b5bf7f1994233fdc331b01c685b": [ { "balance": 1002000000000000000, - "lp_start_date": "2025-11-15" + "lp_start_date": "2025-11-15", + "lp_program_duration_days": 90 } ], "0x91a98fd033434adf63223f88064c95a89e08061c": [ { "balance": 8003750565999172549, - "lp_start_date": "2025-11-13" + "lp_start_date": "2025-11-13", + "lp_program_duration_days": 90 } ], "0x202065dfb813295d0b095a39e36e3b3296210505": [ { "balance": 534187211964517143, - "lp_start_date": "2025-12-02" + "lp_start_date": "2025-12-02", + "lp_program_duration_days": 90 } ], "0x758e5c5c4dd4c6aa1384f0495656a4f7c2f49ec3": [ { "balance": 134000000000000000, - "lp_start_date": "2025-11-17" + "lp_start_date": "2025-11-17", + "lp_program_duration_days": 90 } ], "0xede66ed0fca1a9ebb052cce681c89d7535408ccf": [ { "balance": 329887899954383005, - "lp_start_date": "2025-11-17" + "lp_start_date": "2025-11-17", + "lp_program_duration_days": 90 } ], "0xa0b14f6fe7f647e84b4ac954036865330a9eac5c": [ { "balance": 80000000000000000, - "lp_start_date": "2025-11-17" + "lp_start_date": "2025-11-17", + "lp_program_duration_days": 90 } ], "0x188a7c5b071c01ad31ad80ae7fc28b1b6f389fd6": [ { "balance": 32000000000000000000, - "lp_start_date": "2025-11-17" + "lp_start_date": "2025-11-17", + "lp_program_duration_days": 90 }, { "balance": 32000000000000000000, - "lp_start_date": "2026-02-16" + "lp_start_date": "2026-02-16", + "lp_program_duration_days": 180 } ], "0x73afef607da2dbd27bd9c83e9e9297ae9ca1fd2b": [ { "balance": 25000000000000000000, - "lp_start_date": "2025-11-18" + "lp_start_date": "2025-11-18", + "lp_program_duration_days": 90 } ], "0x54b3ff56f75671d91d85d44bccedbc9179e09afc": [ { "balance": 25000000000000000000, - "lp_start_date": "2025-11-18" + "lp_start_date": "2025-11-18", + "lp_program_duration_days": 90 } ], "0x5b191f5a2b4a867c4ed71858daccc51fc59c69c0": [ { "balance": 30000000000000000000, - "lp_start_date": "2025-11-18" + "lp_start_date": "2025-11-18", + "lp_program_duration_days": 90 }, { "balance": 30000000000000000000, - "lp_start_date": "2026-02-17" + "lp_start_date": "2026-02-17", + "lp_program_duration_days": 180 } ], "0xfb40932271fc9db9dbf048e80697e2da4aa57250": [ { "balance": 25000000000000000000, - "lp_start_date": "2025-11-18" + "lp_start_date": "2025-11-18", + "lp_program_duration_days": 90 } ], "0xd5f4cbfadb349be5dba580f9360eb6867a1d590e": [ { "balance": 29700000000000000000, - "lp_start_date": "2025-11-28" + "lp_start_date": "2025-11-28", + "lp_program_duration_days": 90 } ], "0x0450a946a93cf6f81fd72f1e85e16a8826bc9c4d": [ { "balance": 25000000000000000000, - "lp_start_date": "2025-11-19" + "lp_start_date": "2025-11-19", + "lp_program_duration_days": 90 } ], "0xedf3af29040e069a4cbd6e13fbead2500733f2b1": [ { "balance": 35000000000000000000, - "lp_start_date": "2025-11-19" + "lp_start_date": "2025-11-19", + "lp_program_duration_days": 90 }, { "balance": 45000000000000000000, - "lp_start_date": "2026-02-18" + "lp_start_date": "2026-02-18", + "lp_program_duration_days": 180 } ], "0x8a252b597856b06b3e7efe5d798d73b3c5fbf5ca": [ { "balance": 25000000000000000000, - "lp_start_date": "2025-11-19" + "lp_start_date": "2025-11-19", + "lp_program_duration_days": 90 }, { "balance": 25000000000000000000, - "lp_start_date": "2026-02-18" + "lp_start_date": "2026-02-18", + "lp_program_duration_days": 180 } ], "0xa52af0e35970783f587b77f7b8db94871435009c": [ { "balance": 49918800000000000000, - "lp_start_date": "2025-11-22" + "lp_start_date": "2025-11-22", + "lp_program_duration_days": 90 }, { "balance": 49918800000000000000, - "lp_start_date": "2026-02-21" + "lp_start_date": "2026-02-21", + "lp_program_duration_days": 180 } ], "0xb378273190f974e017d13db074976d55f57e0d20": [ { "balance": 50000000000000000000, - "lp_start_date": "2025-11-20" + "lp_start_date": "2025-11-20", + "lp_program_duration_days": 90 }, { "balance": 50000000000000000000, - "lp_start_date": "2026-02-19" + "lp_start_date": "2026-02-19", + "lp_program_duration_days": 180 } ], "0xdf516f0df67b53f9fc0d4c443a9b07da4ac3174d": [ { "balance": 25000000000000000000, - "lp_start_date": "2025-11-20" + "lp_start_date": "2025-11-20", + "lp_program_duration_days": 90 }, { "balance": 25000000000000000000, - "lp_start_date": "2026-02-19" + "lp_start_date": "2026-02-19", + "lp_program_duration_days": 180 } ], "0xc3cb47f1d74abc82cc9acd748c9c6714f9c77eff": [ { "balance": 25000000000000000000, - "lp_start_date": "2025-11-21" + "lp_start_date": "2025-11-21", + "lp_program_duration_days": 90 } ], "0x9bcd43b2f6f43cb26032edf584f9e511091f83b0": [ { "balance": 25000000000000000000, - "lp_start_date": "2025-11-24" + "lp_start_date": "2025-11-24", + "lp_program_duration_days": 90 } ], "0x588058a144e22d96e235a5aab6e81c9a5749538e": [ { "balance": 34900000000000000000, - "lp_start_date": "2025-11-25" + "lp_start_date": "2025-11-25", + "lp_program_duration_days": 90 }, { "balance": 34900000000000000000, - "lp_start_date": "2026-02-24" + "lp_start_date": "2026-02-24", + "lp_program_duration_days": 180 } ], "0xe4e8d412e3dce3357bb420ec24e51f6bcc1a1bc0": [ { "balance": 50000000000000000000, - "lp_start_date": "2025-11-27" + "lp_start_date": "2025-11-27", + "lp_program_duration_days": 90 } ], "0x6c153feae296dd6f0249323cf597724a9ebfff33": [ { "balance": 91300000000000000000, - "lp_start_date": "2025-11-28" + "lp_start_date": "2025-11-28", + "lp_program_duration_days": 90 } ], "0x5fe0cdf0b1c84cd4a92cec746c84816a3a8b21ef": [ { "balance": 25000000000000000000, - "lp_start_date": "2025-11-28" + "lp_start_date": "2025-11-28", + "lp_program_duration_days": 90 } ], "0xdb4efc647a72ed5fb03c20143b85657dafb6a039": [ { "balance": 99700000000000000000, - "lp_start_date": "2025-11-29" + "lp_start_date": "2025-11-29", + "lp_program_duration_days": 90 }, { "balance": 99700000000000000000, - "lp_start_date": "2026-02-28" + "lp_start_date": "2026-02-28", + "lp_program_duration_days": 180 } ], "0x9b029d74e8770b8a7a88670f5ec69c3c6d33f0e2": [ { "balance": 24500000000000000000, - "lp_start_date": "2025-11-30" + "lp_start_date": "2025-11-30", + "lp_program_duration_days": 90 } ], "0x96fe4e4cd275f1f39eea9d6184447c12006b8536": [ { "balance": 29870000000000000000, - "lp_start_date": "2025-12-02" + "lp_start_date": "2025-12-02", + "lp_program_duration_days": 90 }, { "balance": 29870000000000000000, - "lp_start_date": "2026-03-03" + "lp_start_date": "2026-03-03", + "lp_program_duration_days": 180 } ], "0x05dac02c4c226da6824e0fd2a944c97ab6a34c5d": [ { "balance": 25050000000000000000, - "lp_start_date": "2025-12-02" + "lp_start_date": "2025-12-02", + "lp_program_duration_days": 90 } ], "0x10B58e5B7eC83E3c0B9e8b3e21Ec335931965B50": [ { "balance": 3457909000875908150, - "lp_start_date": "2026-01-26" + "lp_start_date": "2026-01-26", + "lp_program_duration_days": 180 } ] } diff --git a/src/check_lp_integrity.py b/src/check_lp_integrity.py index e8e0576..d661a5d 100644 --- a/src/check_lp_integrity.py +++ b/src/check_lp_integrity.py @@ -11,7 +11,6 @@ ) from .utils.get_days_amount import get_days_amount from .utils.get_points_data import get_points_data, LpSnapshot -from .daily_points_v2 import LP_PROGRAM_DURATION_DAYS from datetime import datetime from .daily_points_v2 import ( get_user_state_at_day, @@ -42,7 +41,7 @@ def _validate_lp_integrity(self, users_state, date_unparsed) -> dict[str, bool]: for program in self.lp_snapshot[address].lp_programs: days_since_lp_start = (date - program.lp_start_date).days if ( - days_since_lp_start <= LP_PROGRAM_DURATION_DAYS + days_since_lp_start <= program.lp_program_duration_days and days_since_lp_start >= 0 ): balance_to_exclude += program.balance diff --git a/src/daily_points_v2.py b/src/daily_points_v2.py index da41e18..d841ed8 100644 --- a/src/daily_points_v2.py +++ b/src/daily_points_v2.py @@ -22,8 +22,6 @@ POINTS_PER_PILOT_VAULT_TOKEN = 1500 POINTS_PER_PILOT_VAULT_TOKEN_FOR_NFT = (142 * 1500) // 100 # 1.42 -LP_PROGRAM_DURATION_DAYS = 90 - type Points = int @@ -68,7 +66,7 @@ def get_balance_excluding_snapshot(self, address, user_state, date_unparsed) -> for program in self.lp_snapshot[address].lp_programs: days_since_lp_start = (date - program.lp_start_date).days if ( - days_since_lp_start <= LP_PROGRAM_DURATION_DAYS + days_since_lp_start <= program.lp_program_duration_days and days_since_lp_start >= 0 ): balance_to_exclude += program.balance diff --git a/src/utils/get_points_data.py b/src/utils/get_points_data.py index 68a85ff..fb0f774 100644 --- a/src/utils/get_points_data.py +++ b/src/utils/get_points_data.py @@ -4,9 +4,15 @@ class LpProgram: - def __init__(self, balance: int, lp_start_date: datetime.date): + def __init__( + self, + balance: int, + lp_start_date: datetime.date, + lp_program_duration_days: int, + ): self.balance = balance self.lp_start_date = lp_start_date + self.lp_program_duration_days = lp_program_duration_days class UserLpSnapshot: @@ -26,7 +32,9 @@ def get_points_data(): address.lower(): UserLpSnapshot( [ LpProgram( - program["balance"], datetime.date.fromisoformat(program["lp_start_date"]) + program["balance"], + datetime.date.fromisoformat(program["lp_start_date"]), + program["lp_program_duration_days"], ) for program in lp_programs ] diff --git a/test/test_check_lp_integrity.py b/test/test_check_lp_integrity.py index c898c94..17cdf31 100644 --- a/test/test_check_lp_integrity.py +++ b/test/test_check_lp_integrity.py @@ -9,13 +9,14 @@ from src.check_lp_integrity import LpIntegrityChecker from src.utils.process_event_above_user_state import UserState from src.utils.get_points_data import UserLpSnapshot, LpProgram -from src.daily_points_v2 import LP_PROGRAM_DURATION_DAYS + +LP_PROGRAM_DURATION_DAYS = 90 # test constant matching lp_snapshot.json def make_lp_snapshot(entries): - """entries: dict[address, list of (balance, lp_start_date)]""" + """entries: dict[address, list of (balance, lp_start_date, lp_program_duration_days)]""" return { - addr: UserLpSnapshot([LpProgram(b, d) for b, d in programs]) + addr: UserLpSnapshot([LpProgram(b, d, dur) for b, d, dur in programs]) for addr, programs in entries.items() } @@ -24,7 +25,7 @@ class TestValidateLpIntegrity: def test_balance_above_snapshot_no_integrity_issue(self): """Test that balance above snapshot does not indicate integrity issue""" lp_snapshot = make_lp_snapshot({ - "0x1111111111111111111111111111111111111111": [(100, date(2026, 1, 1))], + "0x1111111111111111111111111111111111111111": [(100, date(2026, 1, 1), LP_PROGRAM_DURATION_DAYS)], }) checker = LpIntegrityChecker(lp_snapshot, 0) @@ -40,7 +41,7 @@ def test_balance_above_snapshot_no_integrity_issue(self): def test_balance_below_snapshot_integrity_broken(self): """Test that balance below snapshot indicates integrity issue""" lp_snapshot = make_lp_snapshot({ - "0x2222222222222222222222222222222222222222": [(500, date(2026, 1, 1))], + "0x2222222222222222222222222222222222222222": [(500, date(2026, 1, 1), LP_PROGRAM_DURATION_DAYS)], }) checker = LpIntegrityChecker(lp_snapshot, 0) @@ -56,7 +57,7 @@ def test_balance_below_snapshot_integrity_broken(self): def test_balance_equal_to_snapshot_no_integrity_issue(self): """Test that balance equal to snapshot does not indicate integrity issue""" lp_snapshot = make_lp_snapshot({ - "0x3333333333333333333333333333333333333333": [(300, date(2026, 1, 1))], + "0x3333333333333333333333333333333333333333": [(300, date(2026, 1, 1), LP_PROGRAM_DURATION_DAYS)], }) checker = LpIntegrityChecker(lp_snapshot, 0) @@ -72,7 +73,7 @@ def test_balance_equal_to_snapshot_no_integrity_issue(self): def test_user_outside_90_day_period_not_checked(self): """Test that programs outside 90-day window contribute zero to balance_to_exclude""" lp_snapshot = make_lp_snapshot({ - "0x4444444444444444444444444444444444444444": [(100, date(2026, 1, 1))], + "0x4444444444444444444444444444444444444444": [(100, date(2026, 1, 1), LP_PROGRAM_DURATION_DAYS)], }) checker = LpIntegrityChecker(lp_snapshot, 0) @@ -91,7 +92,7 @@ def test_user_outside_90_day_period_not_checked(self): def test_user_not_in_snapshot_no_integrity_issue(self): """Test that user not in lp_snapshot is not flagged (result False)""" lp_snapshot = make_lp_snapshot({ - "0x9999999999999999999999999999999999999999": [(100, date(2026, 1, 1))], + "0x9999999999999999999999999999999999999999": [(100, date(2026, 1, 1), LP_PROGRAM_DURATION_DAYS)], }) checker = LpIntegrityChecker(lp_snapshot, 0) @@ -109,9 +110,9 @@ def test_user_not_in_snapshot_no_integrity_issue(self): def test_multiple_users_mixed_scenarios(self): """Test multiple users with different scenarios""" lp_snapshot = make_lp_snapshot({ - "0x1111111111111111111111111111111111111111": [(100, date(2026, 1, 1))], # Above - "0x2222222222222222222222222222222222222222": [(500, date(2026, 1, 1))], # Below - "0x3333333333333333333333333333333333333333": [(200, date(2026, 1, 1))], # Equal + "0x1111111111111111111111111111111111111111": [(100, date(2026, 1, 1), LP_PROGRAM_DURATION_DAYS)], # Above + "0x2222222222222222222222222222222222222222": [(500, date(2026, 1, 1), LP_PROGRAM_DURATION_DAYS)], # Below + "0x3333333333333333333333333333333333333333": [(200, date(2026, 1, 1), LP_PROGRAM_DURATION_DAYS)], # Equal }) checker = LpIntegrityChecker(lp_snapshot, 0) @@ -132,7 +133,7 @@ def test_address_matching(self): """Test that addresses must match exactly between snapshot and user state""" address = "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd" lp_snapshot = make_lp_snapshot({ - address: [(100, date(2026, 1, 1))], + address: [(100, date(2026, 1, 1), LP_PROGRAM_DURATION_DAYS)], }) checker = LpIntegrityChecker(lp_snapshot, 0) @@ -150,8 +151,8 @@ def test_multiple_programs_same_user(self): # One program 100 (active), one 200 (active) → balance_to_exclude = 300 lp_snapshot = make_lp_snapshot({ "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa": [ - (100, date(2026, 1, 1)), - (200, date(2026, 1, 10)), + (100, date(2026, 1, 1), LP_PROGRAM_DURATION_DAYS), + (200, date(2026, 1, 10), LP_PROGRAM_DURATION_DAYS), ], }) checker = LpIntegrityChecker(lp_snapshot, 0) @@ -163,4 +164,46 @@ def test_multiple_programs_same_user(self): result = checker._validate_lp_integrity(user_state, date_str) - assert result["0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"] == True # 250 < 300 \ No newline at end of file + assert result["0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"] == True # 250 < 300 + + def test_180_day_duration_program(self): + """Test that LP program with 180-day duration correctly validates integrity""" + LP_180_DAYS = 180 + lp_snapshot = make_lp_snapshot({ + "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb": [(400, date(2026, 1, 1), LP_180_DAYS)], + }) + checker = LpIntegrityChecker(lp_snapshot, 0) + + user_state = { + "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb": UserState(balance=300) # Below snapshot + } + # Date is 100 days after LP start (within 180-day duration, but outside 90-day duration) + lp_start = date(2026, 1, 1) + current_date = lp_start + timedelta(days=100) + date_str = str(current_date) + + result = checker._validate_lp_integrity(user_state, date_str) + + # Should flag integrity issue since 300 < 400 and program is still active (within 180 days) + assert result["0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb"] == True # Integrity broken + + def test_180_day_duration_program_unlocked(self): + """Test that LP program with 180-day duration doesn't check integrity after 180 days""" + LP_180_DAYS = 180 + lp_snapshot = make_lp_snapshot({ + "0xcccccccccccccccccccccccccccccccccccccccc": [(500, date(2026, 1, 1), LP_180_DAYS)], + }) + checker = LpIntegrityChecker(lp_snapshot, 0) + + user_state = { + "0xcccccccccccccccccccccccccccccccccccccccc": UserState(balance=200) # Below snapshot + } + # Date is 190 days after LP start (outside 180-day duration) + lp_start = date(2026, 1, 1) + current_date = lp_start + timedelta(days=190) + date_str = str(current_date) + + result = checker._validate_lp_integrity(user_state, date_str) + + # Should not flag integrity issue since program is outside 180-day duration + assert result["0xcccccccccccccccccccccccccccccccccccccccc"] == False # No integrity issue \ No newline at end of file diff --git a/test/test_points.py b/test/test_points.py index e6ff164..cb3372e 100644 --- a/test/test_points.py +++ b/test/test_points.py @@ -3,14 +3,24 @@ import json from collections import defaultdict import sys -from datetime import datetime, timedelta +from datetime import datetime, timedelta, date # Add parent directory to path to import daily_points_v2 sys.path.insert(0, str(Path(__file__).parent.parent)) -from src.daily_points_v2 import DailyPointsProcessor, POINTS_PER_PILOT_VAULT_TOKEN, POINTS_PER_PILOT_VAULT_TOKEN_FOR_NFT, LP_PROGRAM_DURATION_DAYS +from src.daily_points_v2 import DailyPointsProcessor, POINTS_PER_PILOT_VAULT_TOKEN, POINTS_PER_PILOT_VAULT_TOKEN_FOR_NFT from src.utils.process_event_above_user_state import UserState +from src.utils.get_points_data import UserLpSnapshot, LpProgram DATA_DIR = Path("data") +LP_PROGRAM_DURATION_DAYS = 90 # test constant matching lp_snapshot.json + + +def make_lp_snapshot(entries): + """entries: dict[address, list of (balance, lp_start_date, lp_program_duration_days)]""" + return { + addr: UserLpSnapshot([LpProgram(b, d, dur) for b, d, dur in programs]) + for addr, programs in entries.items() + } def load_points_sorted(): @@ -98,21 +108,19 @@ def test_user_balance_changed(self): def test_give_points_user_without_nft(self): """Test that users without NFT get POINTS_PER_PILOT_VAULT_TOKEN per token""" - snapshot_entry = UserState(balance=100) - snapshot_entry.last_positive_balance_update_day = "2026-01-01" - lp_balances_snapshot = { - "0x1234567890123456789012345678901234567890": snapshot_entry - } - processor = DailyPointsProcessor(lp_balances_snapshot, 0) + lp_snapshot = make_lp_snapshot({ + "0x1234567890123456789012345678901234567890": [(100, date(2026, 1, 1), LP_PROGRAM_DURATION_DAYS)], + }) + processor = DailyPointsProcessor(lp_snapshot, 0) user_state = { "0x1234567890123456789012345678901234567890": UserState(balance=500, nft_ids=set()) } user_state["0x1234567890123456789012345678901234567890"].last_positive_balance_update_day = "2026-01-01" points = defaultdict(int) - date = "2026-01-15" # Within 90 days, so should subtract snapshot + test_date = "2026-01-15" # Within 90 days, so should subtract snapshot - result = processor.give_points_for_user_state(user_state, points, date) + result = processor.give_points_for_user_state(user_state, points, test_date) balance_excluding_snapshot = max(0, 500 - 100) # 400 expected_points = balance_excluding_snapshot * POINTS_PER_PILOT_VAULT_TOKEN # 400 * 1500 = 600000 @@ -122,21 +130,19 @@ def test_give_points_user_without_nft(self): def test_give_points_user_with_nft(self): """Test that users with NFT get POINTS_PER_PILOT_VAULT_TOKEN_FOR_NFT per token""" - snapshot_entry = UserState(balance=200) - snapshot_entry.last_positive_balance_update_day = "2026-01-01" - lp_balances_snapshot = { - "0xABCDEFABCDEFABCDEFABCDEFABCDEFABCDEFABCD": snapshot_entry - } - processor = DailyPointsProcessor(lp_balances_snapshot, 0) + lp_snapshot = make_lp_snapshot({ + "0xABCDEFABCDEFABCDEFABCDEFABCDEFABCDEFABCD": [(200, date(2026, 1, 1), LP_PROGRAM_DURATION_DAYS)], + }) + processor = DailyPointsProcessor(lp_snapshot, 0) user_state = { "0xABCDEFABCDEFABCDEFABCDEFABCDEFABCDEFABCD": UserState(balance=1000, nft_ids={1, 2, 3}) } user_state["0xABCDEFABCDEFABCDEFABCDEFABCDEFABCDEFABCD"].last_positive_balance_update_day = "2026-01-01" points = defaultdict(int) - date = "2026-01-15" # Within 90 days, so should subtract snapshot + test_date = "2026-01-15" # Within 90 days, so should subtract snapshot - result = processor.give_points_for_user_state(user_state, points, date) + result = processor.give_points_for_user_state(user_state, points, test_date) balance_excluding_snapshot = max(0, 1000 - 200) # 800 expected_points = balance_excluding_snapshot * POINTS_PER_PILOT_VAULT_TOKEN_FOR_NFT # 800 * 1420 * 1.5 = 1704000 @@ -146,40 +152,38 @@ def test_give_points_user_with_nft(self): def test_give_points_balance_excluding_snapshot(self): """Test that balance_excluding_snapshot correctly subtracts snapshot balance""" - snapshot_entry = UserState(balance=1000) - snapshot_entry.last_positive_balance_update_day = "2026-01-01" - lp_balances_snapshot = { - "0x1111111111111111111111111111111111111111": snapshot_entry - } - processor = DailyPointsProcessor(lp_balances_snapshot, 0) + lp_snapshot = make_lp_snapshot({ + "0x1111111111111111111111111111111111111111": [(1000, date(2026, 1, 1), LP_PROGRAM_DURATION_DAYS)], + }) + processor = DailyPointsProcessor(lp_snapshot, 0) user_state = { "0x1111111111111111111111111111111111111111": UserState(balance=500, nft_ids=set()) } user_state["0x1111111111111111111111111111111111111111"].last_positive_balance_update_day = "2026-01-01" points = defaultdict(int) - date = "2026-01-15" # Within 90 days, so should subtract snapshot + test_date = "2026-01-15" # Within 90 days, so should subtract snapshot - result = processor.give_points_for_user_state(user_state, points, date) + result = processor.give_points_for_user_state(user_state, points, test_date) # balance_excluding_snapshot should be max(0, 500 - 1000) = 0 assert result["0x1111111111111111111111111111111111111111"] == 0 def test_give_points_address_lowercasing(self): """Test that addresses are properly lowercased""" - lp_balances_snapshot = { - "0xABCDEFABCDEFABCDEFABCDEFABCDEFABCDEFABCD": UserState(balance=0) - } - processor = DailyPointsProcessor(lp_balances_snapshot, 0) + lp_snapshot = make_lp_snapshot({ + "0xABCDEFABCDEFABCDEFABCDEFABCDEFABCDEFABCD": [(0, date(2026, 1, 1), LP_PROGRAM_DURATION_DAYS)], + }) + processor = DailyPointsProcessor(lp_snapshot, 0) user_state = { "0xABCDEFABCDEFABCDEFABCDEFABCDEFABCDEFABCD": UserState(balance=100, nft_ids=set()) } user_state["0xABCDEFABCDEFABCDEFABCDEFABCDEFABCDEFABCD"].last_positive_balance_update_day = "2026-01-01" points = defaultdict(int) - date = "2026-01-15" # Within 90 days, so should subtract snapshot + test_date = "2026-01-15" # Within 90 days, so should subtract snapshot - result = processor.give_points_for_user_state(user_state, points, date) + result = processor.give_points_for_user_state(user_state, points, test_date) # Should use lowercase address as key assert "0xabcdefabcdefabcdefabcdefabcdefabcdefabcd" in result @@ -188,10 +192,10 @@ def test_give_points_address_lowercasing(self): def test_give_points_points_accumulation(self): """Test that points are accumulated (added to existing points)""" - lp_balances_snapshot = { - "0x2222222222222222222222222222222222222222": UserState(balance=0) - } - processor = DailyPointsProcessor(lp_balances_snapshot, 0) + lp_snapshot = make_lp_snapshot({ + "0x2222222222222222222222222222222222222222": [(0, date(2026, 1, 1), LP_PROGRAM_DURATION_DAYS)], + }) + processor = DailyPointsProcessor(lp_snapshot, 0) user_state = { "0x2222222222222222222222222222222222222222": UserState(balance=100, nft_ids=set()) @@ -199,9 +203,9 @@ def test_give_points_points_accumulation(self): user_state["0x2222222222222222222222222222222222222222"].last_positive_balance_update_day = "2026-01-01" points = defaultdict(int) points["0x2222222222222222222222222222222222222222"] = 5000 # Existing points - date = "2026-01-15" # Within 90 days, so should subtract snapshot + test_date = "2026-01-15" # Within 90 days, so should subtract snapshot - result = processor.give_points_for_user_state(user_state, points, date) + result = processor.give_points_for_user_state(user_state, points, test_date) expected_new_points = 100 * POINTS_PER_PILOT_VAULT_TOKEN # 150000 assert result["0x2222222222222222222222222222222222222222"] == 5000 + expected_new_points @@ -209,15 +213,11 @@ def test_give_points_points_accumulation(self): def test_give_points_multiple_users(self): """Test that multiple users are handled correctly""" - snapshot_entry1 = UserState(balance=100) - snapshot_entry1.last_positive_balance_update_day = "2026-01-01" - snapshot_entry2 = UserState(balance=200) - snapshot_entry2.last_positive_balance_update_day = "2026-01-01" - lp_balances_snapshot = { - "0x1111111111111111111111111111111111111111": snapshot_entry1, - "0x2222222222222222222222222222222222222222": snapshot_entry2, - } - processor = DailyPointsProcessor(lp_balances_snapshot, 0) + lp_snapshot = make_lp_snapshot({ + "0x1111111111111111111111111111111111111111": [(100, date(2026, 1, 1), LP_PROGRAM_DURATION_DAYS)], + "0x2222222222222222222222222222222222222222": [(200, date(2026, 1, 1), LP_PROGRAM_DURATION_DAYS)], + }) + processor = DailyPointsProcessor(lp_snapshot, 0) user_state = { "0x1111111111111111111111111111111111111111": UserState(balance=500, nft_ids=set()), @@ -226,9 +226,9 @@ def test_give_points_multiple_users(self): user_state["0x1111111111111111111111111111111111111111"].last_positive_balance_update_day = "2026-01-01" user_state["0x2222222222222222222222222222222222222222"].last_positive_balance_update_day = "2026-01-01" points = defaultdict(int) - date = "2026-01-15" # Within 90 days, so should subtract snapshot + test_date = "2026-01-15" # Within 90 days, so should subtract snapshot - result = processor.give_points_for_user_state(user_state, points, date) + result = processor.give_points_for_user_state(user_state, points, test_date) # User 1: no NFT, balance_excluding_snapshot = 500 - 100 = 400 assert result["0x1111111111111111111111111111111111111111"] == 400 * POINTS_PER_PILOT_VAULT_TOKEN @@ -238,64 +238,60 @@ def test_give_points_multiple_users(self): def test_give_points_zero_balance_excluding_snapshot(self): """Test that zero balance_excluding_snapshot results in zero points""" - snapshot_entry = UserState(balance=500) - snapshot_entry.last_positive_balance_update_day = "2026-01-01" - lp_balances_snapshot = { - "0x3333333333333333333333333333333333333333": snapshot_entry - } - processor = DailyPointsProcessor(lp_balances_snapshot, 0) + lp_snapshot = make_lp_snapshot({ + "0x3333333333333333333333333333333333333333": [(500, date(2026, 1, 1), LP_PROGRAM_DURATION_DAYS)], + }) + processor = DailyPointsProcessor(lp_snapshot, 0) user_state = { "0x3333333333333333333333333333333333333333": UserState(balance=500, nft_ids=set()) } user_state["0x3333333333333333333333333333333333333333"].last_positive_balance_update_day = "2026-01-01" points = defaultdict(int) - date = "2026-01-15" # Within 90 days, so should subtract snapshot + test_date = "2026-01-15" # Within 90 days, so should subtract snapshot - result = processor.give_points_for_user_state(user_state, points, date) + result = processor.give_points_for_user_state(user_state, points, test_date) # balance_excluding_snapshot = max(0, 500 - 500) = 0 assert result["0x3333333333333333333333333333333333333333"] == 0 def test_give_points_empty_nft_set(self): """Test that empty NFT set is treated as no NFT""" - lp_balances_snapshot = { - "0x4444444444444444444444444444444444444444": UserState(balance=0) - } - processor = DailyPointsProcessor(lp_balances_snapshot, 0) + lp_snapshot = make_lp_snapshot({ + "0x4444444444444444444444444444444444444444": [(0, date(2026, 1, 1), LP_PROGRAM_DURATION_DAYS)], + }) + processor = DailyPointsProcessor(lp_snapshot, 0) user_state = { "0x4444444444444444444444444444444444444444": UserState(balance=100, nft_ids=set()) } user_state["0x4444444444444444444444444444444444444444"].last_positive_balance_update_day = "2026-01-01" points = defaultdict(int) - date = "2026-01-15" # Within 90 days, so should subtract snapshot + test_date = "2026-01-15" # Within 90 days, so should subtract snapshot - result = processor.give_points_for_user_state(user_state, points, date) + result = processor.give_points_for_user_state(user_state, points, test_date) # Empty set should use POINTS_PER_PILOT_VAULT_TOKEN (not FOR_NFT) assert result["0x4444444444444444444444444444444444444444"] == 100 * POINTS_PER_PILOT_VAULT_TOKEN def test_give_points_unlocked_rewards_without_nft(self): """Test that rewards are unlocked (full balance used) when date > last_positive_balance_update_day + 90 days""" - snapshot_entry = UserState(balance=200) - snapshot_entry.last_positive_balance_update_day = "2026-01-01" - lp_balances_snapshot = { - "0x5555555555555555555555555555555555555555": snapshot_entry - } - processor = DailyPointsProcessor(lp_balances_snapshot, 0) + lp_snapshot = make_lp_snapshot({ + "0x5555555555555555555555555555555555555555": [(200, date(2026, 1, 1), LP_PROGRAM_DURATION_DAYS)], + }) + processor = DailyPointsProcessor(lp_snapshot, 0) user_state = { "0x5555555555555555555555555555555555555555": UserState(balance=500, nft_ids=set()) } - # Set last update to 100 days ago - last_update_date = datetime(2026, 1, 1).date() + # Set date 100 days after LP start so program is outside duration + last_update_date = date(2026, 1, 1) current_date = last_update_date + timedelta(days=LP_PROGRAM_DURATION_DAYS + 10) # 100 days later user_state["0x5555555555555555555555555555555555555555"].last_positive_balance_update_day = str(last_update_date) points = defaultdict(int) - date = str(current_date) + test_date = str(current_date) - result = processor.give_points_for_user_state(user_state, points, date) + result = processor.give_points_for_user_state(user_state, points, test_date) # Should use full balance (500), not subtract snapshot (200) expected_points = 500 * POINTS_PER_PILOT_VAULT_TOKEN # 750000 @@ -304,24 +300,22 @@ def test_give_points_unlocked_rewards_without_nft(self): def test_give_points_unlocked_rewards_with_nft(self): """Test that rewards are unlocked (full balance used) when date > last_positive_balance_update_day + 90 days for users with NFT""" - snapshot_entry = UserState(balance=300) - snapshot_entry.last_positive_balance_update_day = "2026-01-01" - lp_balances_snapshot = { - "0x6666666666666666666666666666666666666666": snapshot_entry - } - processor = DailyPointsProcessor(lp_balances_snapshot, 0) + lp_snapshot = make_lp_snapshot({ + "0x6666666666666666666666666666666666666666": [(300, date(2026, 1, 1), LP_PROGRAM_DURATION_DAYS)], + }) + processor = DailyPointsProcessor(lp_snapshot, 0) user_state = { "0x6666666666666666666666666666666666666666": UserState(balance=1000, nft_ids={1, 2}) } - # Set last update to 100 days ago - last_update_date = datetime(2026, 1, 1).date() + # Set date 100 days after LP start so program is outside duration + last_update_date = date(2026, 1, 1) current_date = last_update_date + timedelta(days=LP_PROGRAM_DURATION_DAYS + 10) # 100 days later user_state["0x6666666666666666666666666666666666666666"].last_positive_balance_update_day = str(last_update_date) points = defaultdict(int) - date = str(current_date) + test_date = str(current_date) - result = processor.give_points_for_user_state(user_state, points, date) + result = processor.give_points_for_user_state(user_state, points, test_date) # Should use full balance (1000), not subtract snapshot (300) expected_points = 1000 * POINTS_PER_PILOT_VAULT_TOKEN_FOR_NFT # 2130000 @@ -330,24 +324,22 @@ def test_give_points_unlocked_rewards_with_nft(self): def test_give_points_not_unlocked_within_90_days(self): """Test that rewards are NOT unlocked when date <= last_positive_balance_update_day + 90 days""" - snapshot_entry = UserState(balance=200) - snapshot_entry.last_positive_balance_update_day = "2026-01-01" - lp_balances_snapshot = { - "0x7777777777777777777777777777777777777777": snapshot_entry - } - processor = DailyPointsProcessor(lp_balances_snapshot, 0) + lp_snapshot = make_lp_snapshot({ + "0x7777777777777777777777777777777777777777": [(200, date(2026, 1, 1), LP_PROGRAM_DURATION_DAYS)], + }) + processor = DailyPointsProcessor(lp_snapshot, 0) user_state = { "0x7777777777777777777777777777777777777777": UserState(balance=500, nft_ids=set()) } - # Set last update to 50 days ago (within 90 day period) - last_update_date = datetime(2026, 1, 1).date() + # Set date 50 days after LP start (within 90 day period) + last_update_date = date(2026, 1, 1) current_date = last_update_date + timedelta(days=50) # 50 days later user_state["0x7777777777777777777777777777777777777777"].last_positive_balance_update_day = str(last_update_date) points = defaultdict(int) - date = str(current_date) + test_date = str(current_date) - result = processor.give_points_for_user_state(user_state, points, date) + result = processor.give_points_for_user_state(user_state, points, test_date) # Should subtract snapshot: max(0, 500 - 200) = 300 expected_points = 300 * POINTS_PER_PILOT_VAULT_TOKEN # 450000 @@ -356,26 +348,74 @@ def test_give_points_not_unlocked_within_90_days(self): def test_give_points_unlocked_exactly_90_days(self): """Test that rewards are NOT unlocked exactly at 90 days (must be > 90 days)""" - snapshot_entry = UserState(balance=100) - snapshot_entry.last_positive_balance_update_day = "2026-01-01" - lp_balances_snapshot = { - "0x8888888888888888888888888888888888888888": snapshot_entry - } - processor = DailyPointsProcessor(lp_balances_snapshot, 0) + lp_snapshot = make_lp_snapshot({ + "0x8888888888888888888888888888888888888888": [(100, date(2026, 1, 1), LP_PROGRAM_DURATION_DAYS)], + }) + processor = DailyPointsProcessor(lp_snapshot, 0) user_state = { "0x8888888888888888888888888888888888888888": UserState(balance=500, nft_ids=set()) } - # Set last update to exactly 90 days ago - last_update_date = datetime(2026, 1, 1).date() + # Set date exactly 90 days after LP start (still within duration) + last_update_date = date(2026, 1, 1) current_date = last_update_date + timedelta(days=LP_PROGRAM_DURATION_DAYS) # Exactly 90 days later user_state["0x8888888888888888888888888888888888888888"].last_positive_balance_update_day = str(last_update_date) points = defaultdict(int) - date = str(current_date) + test_date = str(current_date) - result = processor.give_points_for_user_state(user_state, points, date) + result = processor.give_points_for_user_state(user_state, points, test_date) # Should still subtract snapshot since date is not > 90 days: max(0, 500 - 100) = 400 expected_points = 400 * POINTS_PER_PILOT_VAULT_TOKEN # 600000 assert result["0x8888888888888888888888888888888888888888"] == expected_points assert result["0x8888888888888888888888888888888888888888"] == 600000 + + def test_give_points_180_day_duration(self): + """Test that LP program with 180-day duration correctly excludes balance at day 100""" + LP_180_DAYS = 180 + lp_snapshot = make_lp_snapshot({ + "0x9999999999999999999999999999999999999999": [(200, date(2026, 1, 1), LP_180_DAYS)], + }) + processor = DailyPointsProcessor(lp_snapshot, 0) + + user_state = { + "0x9999999999999999999999999999999999999999": UserState(balance=500, nft_ids=set()) + } + # Set date 100 days after LP start (within 180-day duration, but would be outside 90-day duration) + last_update_date = date(2026, 1, 1) + current_date = last_update_date + timedelta(days=100) # 100 days later + user_state["0x9999999999999999999999999999999999999999"].last_positive_balance_update_day = str(last_update_date) + points = defaultdict(int) + test_date = str(current_date) + + result = processor.give_points_for_user_state(user_state, points, test_date) + + # Should subtract snapshot since date is within 180-day duration: max(0, 500 - 200) = 300 + expected_points = 300 * POINTS_PER_PILOT_VAULT_TOKEN # 450000 + assert result["0x9999999999999999999999999999999999999999"] == expected_points + assert result["0x9999999999999999999999999999999999999999"] == 450000 + + def test_give_points_180_day_duration_unlocked(self): + """Test that LP program with 180-day duration unlocks after 180 days""" + LP_180_DAYS = 180 + lp_snapshot = make_lp_snapshot({ + "0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": [(150, date(2026, 1, 1), LP_180_DAYS)], + }) + processor = DailyPointsProcessor(lp_snapshot, 0) + + user_state = { + "0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA": UserState(balance=600, nft_ids=set()) + } + # Set date 190 days after LP start (outside 180-day duration) + last_update_date = date(2026, 1, 1) + current_date = last_update_date + timedelta(days=190) # 190 days later + user_state["0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"].last_positive_balance_update_day = str(last_update_date) + points = defaultdict(int) + test_date = str(current_date) + + result = processor.give_points_for_user_state(user_state, points, test_date) + + # Should use full balance (600), not subtract snapshot (150) since outside 180-day duration + expected_points = 600 * POINTS_PER_PILOT_VAULT_TOKEN # 900000 + assert result["0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"] == expected_points + assert result["0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"] == 900000 From 361ac70c01a394e773eee3375bee98697f0f8eee Mon Sep 17 00:00:00 2001 From: Vladyslav Burtsevych Date: Thu, 5 Feb 2026 16:11:07 +0100 Subject: [PATCH 4/4] remove: old file --- .gitignore | 1 - data/lp_balances_snapshot.json | 2021 -------------------------------- test/test_nft_balance.py | 2 +- test/test_user_balance.py | 2 +- 4 files changed, 2 insertions(+), 2024 deletions(-) delete mode 100644 data/lp_balances_snapshot.json diff --git a/.gitignore b/.gitignore index fd235b5..3a65c35 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,4 @@ data/* .venv/ __pycache__/ .env -!data/lp_balances_snapshot.json !data/lp_snapshot.json \ No newline at end of file diff --git a/data/lp_balances_snapshot.json b/data/lp_balances_snapshot.json deleted file mode 100644 index 4f56798..0000000 --- a/data/lp_balances_snapshot.json +++ /dev/null @@ -1,2021 +0,0 @@ -{ - "start_block": 23985731, - "end_block": 23992864, - "date": "2025-12-11", - "day_index": 78, - "nft": { - "start_state": { - "0xeb1050ec6160fcf3db72b2adcd950993a23e48b3": [ - 9, - 10, - 13, - 16, - 18, - 19 - ], - "0xa95584c820b5bc990a0572df4faba7fb9f4e210b": [ - 1, - 43 - ], - "0x1350149385d5fdadbfa5527f830d4065f77df2d5": [ - 44 - ], - "0x6f9bb7e454f5b3eb2310343f0e99269dc2bb8a1d": [ - 45, - 22 - ], - "0x0b304924faa64b0f040dca67bc5175dd6078db52": [ - 46 - ], - "0x74630370197b4c4795bfeef6645ee14f8cf8997d": [ - 47 - ], - "0xa362a6b387a80180286ef40d8e6ec6ca2657a9fa": [ - 48 - ], - "0x74be7c259c22b82354c93e0f94f203f986af1423": [ - 49 - ], - "0x89fee8e11e2a238579fb0d59f5ce1dd90c85fe15": [ - 50 - ], - "0x4c82cff7398f3d43b36e41b10ff6f42b14dd9385": [ - 51 - ], - "0x546d241f237b98bb2b807625744af279d54272d0": [ - 52 - ], - "0xb66a0ee5a0ef1a60f11ef102b6a3828f1823d136": [ - 53 - ], - "0x48d683f6bc178285e3e9bfa92f93dec7d502c552": [ - 54 - ], - "0xce04951dae0559ee6c61830ef893c2ac85ee83b1": [ - 55 - ], - "0x585989769f6a97c6dab2c462076be2dd0a5286f7": [ - 56 - ], - "0xdec0de987db64adbe297dac3762178a1b103014e": [ - 57 - ], - "0x52d0fc347560cc997f87984200f4a9344ecdc597": [ - 58 - ], - "0x081076bc1b250650f009bf802425ec4979569a59": [ - 59 - ], - "0xb439b0844d0d9af237ff37dc2379f07b6cd06171": [ - 60 - ], - "0x3a0b6f2023ca63764424b8b3cc84710e42aad151": [ - 61 - ], - "0x290ca510021d18699b268f133813f6262a650d94": [ - 21, - 62 - ], - "0x4cb2776a2550ed12b51e7f27f25287874f576a08": [ - 63 - ], - "0x984a69a51f06044e6b79294c652fae499b333f49": [ - 64 - ], - "0x625a1a58897f3b250a9c68afd52ec283ec94a03d": [ - 65 - ], - "0x693eeae27374b57673bb009e0faa88d908985a30": [ - 66 - ], - "0x5f0ab641ec7240bd9f6885b6d8c15b177f1a8cae": [ - 67 - ], - "0x17a3831b39cc557296d0c322f9c2d42c0b3a8f3f": [ - 68 - ], - "0xcdbd980e0a3a854c11d5d869e622f6c1e1c40c23": [ - 69 - ], - "0x4e3fa58a4e23d408908ade21b48e995fca99072f": [ - 71 - ], - "0x3b0e45ff406c28624aa4013a414e48afffa00a7e": [ - 72 - ], - "0xd6ed1100ac5a3ff39de64937f3ea58fe4a975213": [ - 73 - ], - "0xd23d8aead200401091022e5c4304b32b56042808": [ - 74 - ], - "0x37481b2687f58a8706eca8ee37ccaa090497e7ad": [ - 75 - ], - "0x4980cdcff7ddf6c501266df644e5c685793567e7": [ - 76 - ], - "0xce203f74e732ce2dd6975e4bfd3911599eb431fc": [ - 77 - ], - "0x10b549dfea119302a96f23d7e53f49a059b50037": [ - 78 - ], - "0x9330065a70e54ad29cf60c2c013e69900da13d73": [ - 79 - ], - "0x693a10f33974fda182e34d0d179c5247874897a3": [ - 80 - ], - "0xb7308a79a35c3a24cd5fc8d11c37aada0234b71d": [ - 81 - ], - "0xab3454f4198940432f89872023ebbd64495293b0": [ - 82 - ], - "0x21518af0c47c4113df3ecf7bb232cb3a33083676": [ - 83 - ], - "0x9fd8788496e2edb846789d788eee952bb8f65014": [ - 84 - ], - "0x8ddf6783761cadaac0621a455d595cc7fcd60524": [ - 86 - ], - "0xe386af9ffb851557e294593689b579cd8afa0758": [ - 87 - ], - "0x338c40deba0e9511fa9bafa4f706302aa976f9b5": [ - 88 - ], - "0x09cb05c212ef384ca54825947a72d37c94743ac8": [ - 89 - ], - "0x1aad33f754e47d693562dde3e944332420d27493": [ - 90 - ], - "0xc309151865a7493dd51f611b27d7d5b0323b240e": [ - 91 - ], - "0x40f832b71d2c525a9aa4b4908ec511ed93c8a308": [ - 92 - ], - "0xed2c2cdec695be3a4dc421c1a8a6756dc5a927b6": [ - 93 - ], - "0x48e756eae97c0123cc88c660987793b49e48afa3": [ - 94 - ], - "0xb6e2ae25a80411a1d928f2f613600a6a3a36476c": [ - 95 - ], - "0x06453f99650515950478a7f396fb266e33d2e453": [ - 96 - ], - "0xd2c2e84501c63b7b9897df063288d67060119c99": [ - 97, - 31 - ], - "0x79072f96b6a5e8d69a66e0eaaef49674ef0dd8d3": [ - 98 - ], - "0x4b8c1c25c89ca27434c0ac64a48c360765c7aa5a": [ - 99 - ], - "0xe0a35b164f5c5e44e26d357e4ac88e1b8714090f": [ - 100 - ], - "0x6ce618ec1312fab2ff4985d9498b3514cbce401a": [ - 101 - ], - "0x12667125770eb9fb46c48db659d3275e8fcd2ed7": [ - 32, - 102 - ], - "0x74aadae2c7aa9321314a0a6f53a70eda5ebe103a": [ - 103 - ], - "0x8e1be56368f91eecf8a06cb3be07daf29564a189": [ - 104 - ], - "0x6204c3e753123168fa4b596476aa321f50c9d2c2": [ - 105 - ], - "0x16318b4784ea41cddbcf5a3f2fd8a7a4dbba1bde": [ - 106 - ], - "0x699beef82677d611f97c6cac21ce83891b5683ed": [ - 107 - ], - "0x6067f3605a6deecab3ac78e19c40b6874d847101": [ - 108 - ], - "0xed95cbd2185924807e3b893b7e7ac5dfe2efe33f": [ - 109 - ], - "0x8252a1a673796110ca091344fdae1729e7aea94b": [ - 110 - ], - "0xb10f3ea007de364448d8c379bde4875ba1acba3b": [ - 111 - ], - "0x01695a44f7628f62ad020acf4df26cd0552afa99": [ - 112 - ], - "0xfbb041e1e292e34f90c1333e5360f5ff2f3f6450": [ - 113 - ], - "0x269f6c970581372523a58a630dc462d6568b61a6": [ - 115 - ], - "0x0fb56c793ae84667961fd72d8f2ccbb13082e898": [ - 116 - ], - "0x9799fb7dd26e14b5bebda156a7ff7b870a2429ef": [ - 117 - ], - "0x616c18b6e555c62570fa6a513637c3135cee3871": [ - 118 - ], - "0x9b68cb6aff0a3b6eb591e414c653737324d80485": [ - 119 - ], - "0xba55bdbf959df826da6c35487eb15fad2164662d": [ - 120 - ], - "0x9ab5b54092a1596a32127163b7b0176445eb1b0a": [ - 121, - 25 - ], - "0xdc3e00cc50dc4b79d1aa26ef35b03d99ab213974": [ - 122 - ], - "0xd6bba09dee0ddc465c22a23cb8548a524eb994c8": [ - 123 - ], - "0x2f476a1680d2e1fc79fa3ca03a629d94dc2b148c": [ - 124 - ], - "0x46688024f0022d9bdcd69feec88b7a5990d258de": [ - 125 - ], - "0xc49b6c714feaf22b12eb02a01521dab6edd1fcbd": [ - 126 - ], - "0x307e1b27659a9b00a7a93059b64637d024fd017d": [ - 211, - 127 - ], - "0x07953ec0617854fbfbf9323268547d604a0b1a8b": [ - 128 - ], - "0xf3a57bc7ebd5be52604c08d8954673e24330e2b1": [ - 129 - ], - "0x715955bb4c12450eed13c2033fa7fe750df593e3": [ - 130 - ], - "0xbbf42ca0b874fdc113a957370502b8c8b3af7480": [ - 131 - ], - "0xf60667353bdb1d73cf94c7feab49f76c9a3a4c76": [ - 132 - ], - "0xe59267a4420d3988caab50e840f9d6f179ffdee6": [ - 133 - ], - "0x97d34c151214875fa2c42e6a7d54ff8e967fa208": [ - 134 - ], - "0x86a12a8a886a218986ed1c42382457d15d333890": [ - 135 - ], - "0xfe37ca693e70fd8b333d6d861ebe271e1d10f94c": [ - 136 - ], - "0xf109731b8fe0f4c03ddc28e6da7b210f8adcc722": [ - 137 - ], - "0xa4fcccd4faa32dbe95637f7457010ba243c65e19": [ - 138 - ], - "0xc2456529b5b93ef85264ca178d29b6c660fac5a7": [ - 139 - ], - "0x7a006f71f27626ea7697b0e46633d7c9b82b40a2": [ - 140 - ], - "0x8f9dce6ae6d0c6abf5e8f36cb6c75d7389bbee84": [ - 141 - ], - "0xab59cf03b23bcdffbe73e837dc34e5765b2920d4": [ - 142 - ], - "0xef8b64f30aa834384c85a1759c9719a6dd39eabd": [ - 143 - ], - "0x86b461b490e581a988f59607d8bf30c389cd3d6f": [ - 144 - ], - "0xfc32ec311f4d388b0f4405f97bb46a8c4fbada29": [ - 145 - ], - "0xd800f95673773551f9b0aaeb917b4ed7c8729fed": [ - 146 - ], - "0xac6ad2e9eff402007965927387505710e9744371": [ - 147 - ], - "0x3f6e2af7a45ddbffb5d5686e4e44f23e906d4233": [ - 148 - ], - "0x8fa14c10a998d0ec3b8f2209b5d439b30d41090a": [ - 149 - ], - "0x7a5611cc35c99dbe266078f56c09edd193ff9280": [ - 150 - ], - "0x41d293f4804b390a84ea3c3898833c21a2f04423": [ - 151 - ], - "0x9ed770b170f215aa846c999677f572105f4a48fb": [ - 152 - ], - "0x3abfe7806c2bddcc9795b8cdd68d619fb5f7e3ef": [ - 153 - ], - "0x06a632fa59e213f03f17a70bd6da16b99a6f205a": [ - 154 - ], - "0xe33f7d15b469afabeddf80a2fb90f32411053267": [ - 155 - ], - "0xb2788f9e443bc3eb44bd6388215748c79b517d4e": [ - 156 - ], - "0x14d92832265eeafdef9e526356fefc90105966c3": [ - 157 - ], - "0x7f66edeccefdaa57ce61983e6c7eb89450feb024": [ - 158 - ], - "0xf44217a8b6b3f258bffead635c226528aa516aea": [ - 159 - ], - "0x6b56bdc58dde8cccacb03c28ce36c129bd42a083": [ - 160 - ], - "0x40bba49b15d5efbf9e45d47ef219656c9b04321f": [ - 161 - ], - "0xec0431a9c8d2e12a6c411d77e7bb0183f86913c2": [ - 162 - ], - "0xeb073a004fb6927ec44230226b0cbdedbee4ed97": [ - 163 - ], - "0x6ffc0290cf7f88637fbb1f920b9df9d264b3783d": [ - 164 - ], - "0xdc377dc2d3f497f8d24a3b1d7f80bd476473a2bb": [ - 165 - ], - "0xeb81f7f62d9cd0e9a9aa2617ff2ee8c0b01f6bbb": [ - 166 - ], - "0x741950e9c579a8c1c9a2e60cb6597fc33da2d37c": [ - 167 - ], - "0xb0eb8b4003fdd74f3c7994fbe5fce95ad10e3bcc": [ - 168 - ], - "0x0499491b005243073c3f0ee8873885ce2a2b2206": [ - 169 - ], - "0xd7f33cf1de3e9339978afb25a64562cf4615dd9e": [ - 170 - ], - "0xf96d09c553db50ef8198eed965df9e660133c23a": [ - 171 - ], - "0x2e15b6aa2f32896f024a139559464ec55bb0da00": [ - 172 - ], - "0xf84454985b6636ba2d643cfbcc6c30c51892e8bf": [ - 173 - ], - "0x8637054754d4a18c8aa2f3be4190745bf92a0054": [ - 174 - ], - "0x9dc4e75b05ef3fcc258040471a6bc8ab1fddebbb": [ - 175 - ], - "0xc9e7d61bbdef3f821da08bfdb19a2bf7e0ec60b7": [ - 178 - ], - "0x057ca4a6e2c11565be71a8453a9f3f86b5f2bba7": [ - 179 - ], - "0x3b4daa9fbd96445faff116164ff634c976f3ad58": [ - 180 - ], - "0x8b0b0a73cc2a0a10e63b2d24b37f4c9f78ba4904": [ - 181 - ], - "0x1e8ee48d0621289297693fc98914da2efdce1477": [ - 182 - ], - "0xc0f962face7e5a0ee212d6d71bd60f5336b10d1a": [ - 183 - ], - "0x4e0c09589d862485d724f3f8c1ff5745a52e0570": [ - 184 - ], - "0x62625318578756f7f429a0124e5fdfba7c89f534": [ - 185 - ], - "0xdc6447010c602bbcbdbe2aaff27d24af55fe5b75": [ - 186, - 267 - ], - "0x01c3137ee9751663ddd96c47a6c44df7b48faae7": [ - 187 - ], - "0xcb7952f98f198a56af4b764b28b1bd165e2ceeef": [ - 188 - ], - "0xa3f35c425f31410741a0a455cbc23b1314ac5dc7": [ - 189 - ], - "0xdd4b82486b606d70de0a1ad1a5446dd724fc793a": [ - 190 - ], - "0xe2d9a9e35f2e657804f6d2149f9bea9db06176ff": [ - 191 - ], - "0x88650dddf2c281d73ee26e1e5416dab11ce87f69": [ - 192 - ], - "0x11419d53a310375e690356eef380da6b9254d99b": [ - 193 - ], - "0x58a3feb357d7dabc120910c31b6b33d453bc6022": [ - 194 - ], - "0xc92e7fb11c535579cc0807d655464e2999583d20": [ - 195 - ], - "0x3df85ebb5a2f7d1178e3482bd56523037d850f71": [ - 196 - ], - "0x5bf94136af40fce25de77ed59782a7483fd0dc3b": [ - 197 - ], - "0x6d6f9ae649fec4fca9065752acd8286e1c7c5e3e": [ - 198 - ], - "0xb6ef5ef50445797a88d9eae000c577d5df626f00": [ - 199 - ], - "0x2655a14770b9c5f04346475d3b2f1f9220ac55bb": [ - 200 - ], - "0x59f54d4d3aa9905aa3c0046b219fc1e9be5df13e": [ - 201 - ], - "0xe21619a0c4e7156de1238e6cdd2bbece8d1adadb": [ - 202 - ], - "0x8c2f4724c7a5b7e46965671b1b301e7e6b67f87c": [ - 203 - ], - "0xc1ba551d7d410d6352f8380795ba6cad7ac6fc64": [ - 204 - ], - "0x947a5a2e5b096752f0f3663964dd52151e3ad2b9": [ - 205 - ], - "0xc08d8a00960666eac963591cef25b9db27f97200": [ - 206 - ], - "0x416a3427414b6c98adab70f48a2a904d1cf3f446": [ - 207 - ], - "0x5984bb82f11171cb1dc2287e2a6935c44d491538": [ - 208 - ], - "0xa12810ce00eef03951877aafe2c9b16d3041fa19": [ - 209 - ], - "0x640d4b5181f4f89ddd01a78d04ef079171ab2474": [ - 210 - ], - "0x8cd0e624102974b6636ce653573d62b98b2b4e85": [ - 213 - ], - "0x036e1b95308e68fed27067df4b497ee8bd669db7": [ - 214 - ], - "0x6d526f6b4c86fbdc8e359e6bef4cd6a42acea2d7": [ - 215 - ], - "0x39c31a899662da8bba43862c82c8ba531dc61390": [ - 216 - ], - "0x6842824216c3476753ba6c52a2388fb8d6bd20a4": [ - 217 - ], - "0x7452e7d530078dbd6a2ed65007bea00a4d60f138": [ - 218 - ], - "0xd67f15a5401df029218df828a9bda0a551609578": [ - 219 - ], - "0xea6ae8c291897a9a88f847d76e055ca2c7b49f9f": [ - 220 - ], - "0x100cc424f8c049cb2882ce9d3ce2f8ca63bd80e0": [ - 221 - ], - "0x508f5587e20dba23ae0e2a4577709af23c6537cd": [ - 222 - ], - "0x16951212197b6e995ab4cecc5cf6dbea976782dd": [ - 223 - ], - "0x5e5788ced34c51d2d20e950bd0dd4a28e7e78e27": [ - 224 - ], - "0xb080e60ea6251cf7212d1ccb30b683c55d11f3e4": [ - 225 - ], - "0x2a1500fe1d41c73589667376fe5403c34dd2ab20": [ - 226 - ], - "0x5a1e05051788ce38a52e7e757d39767b4d91edba": [ - 227 - ], - "0x0fe534525898f0a571b97abeda632cf0968fa62a": [ - 228 - ], - "0xb2f456886367c8e50566377ec6d9293d4da5bb81": [ - 229 - ], - "0x1a36d989434f8b7743d645ebf53d5124a4bcae2d": [ - 230 - ], - "0x0813e1b0a5b1d0d67ceac68696591f5aecc613c7": [ - 231 - ], - "0x3805c1400a22b39ea349c08be3604a43a22fa445": [ - 232 - ], - "0xbb68dcf509480f648e3c501d2dbbc5636b82f689": [ - 234 - ], - "0x210351fcc900c1e5ef4c7b1bf3d37ab33ca87114": [ - 235 - ], - "0xa136a3abc184bf70de3614822b2a6e6d8df018e5": [ - 236 - ], - "0xbda87f0bd638cd702973745cd908f758e075e723": [ - 237 - ], - "0xde0e14e314ec13cabc21272f9dd27dec0c92b504": [ - 238 - ], - "0x9cd5f86e1690daa9167ce702f30e8e83d4d9352e": [ - 239 - ], - "0xdc70a024af3e898837b3c04677581146a746ecb7": [ - 240 - ], - "0xf3d476566bcc8e882a3910f1471428522449d89e": [ - 241 - ], - "0x612dd12feff854a04db3ef0a56f88e5cd16ee4c6": [ - 242 - ], - "0x9a4249c3c0511beb1acb4d49ec9143e886759a84": [ - 233 - ], - "0x78b1a53dec02c2c8ff6ba7da9f6cca1f5c044c6e": [ - 212 - ], - "0x406fdeeaa6a4fd93103390306a11a6cec5d25445": [ - 177 - ], - "0x27e39999cc3cc148d579cadf4febc946008dd48b": [ - 176 - ], - "0xd1f4778903c3473b61c8b265ec60173d2670b17e": [ - 243 - ], - "0x296e0c21db4061ebf971e55d5db85011e7ff9797": [ - 244 - ], - "0x3e2dee92f81607f4210636ec21525c6523609d84": [ - 245 - ], - "0x6bc2a8f837ffa631fb7f969b7c70f7c7e46b24d3": [ - 246 - ], - "0x728754bf437ec16d197e06af053c7b006b89e330": [ - 247 - ], - "0x037771a4c189d3b9c0b9db7b7cb2c4ea6629bb61": [ - 248 - ], - "0x39d10a4ad72a9b5bf7f1994233fdc331b01c685b": [ - 249, - 11 - ], - "0x91a98fd033434adf63223f88064c95a89e08061c": [ - 2 - ], - "0x4ae607c31760bdbfef336d9ff999aea69150b872": [ - 250 - ], - "0x758e5c5c4dd4c6aa1384f0495656a4f7c2f49ec3": [ - 4 - ], - "0x8485b2522425f5449fc1d2e54579f719fca88a02": [ - 3 - ], - "0xede66ed0fca1a9ebb052cce681c89d7535408ccf": [ - 24 - ], - "0xa0b14f6fe7f647e84b4ac954036865330a9eac5c": [ - 5 - ], - "0x188a7c5b071c01ad31ad80ae7fc28b1b6f389fd6": [ - 35 - ], - "0x73afef607da2dbd27bd9c83e9e9297ae9ca1fd2b": [ - 40 - ], - "0x54b3ff56f75671d91d85d44bccedbc9179e09afc": [ - 272, - 70 - ], - "0x5b191f5a2b4a867c4ed71858daccc51fc59c69c0": [ - 251, - 36 - ], - "0xfb40932271fc9db9dbf048e80697e2da4aa57250": [ - 269 - ], - "0xd5f4cbfadb349be5dba580f9360eb6867a1d590e": [ - 41 - ], - "0x0450a946a93cf6f81fd72f1e85e16a8826bc9c4d": [ - 270 - ], - "0xedf3af29040e069a4cbd6e13fbead2500733f2b1": [ - 33 - ], - "0x8a252b597856b06b3e7efe5d798d73b3c5fbf5ca": [ - 20 - ], - "0xa52af0e35970783f587b77f7b8db94871435009c": [ - 26, - 252 - ], - "0xd8c860d789ec1c6ae9631b680e6555f25bc28331": [ - 253 - ], - "0xbf970e507672b30abce90bde4520e3939d423adb": [ - 254 - ], - "0xafd8fb69e850d2da8ac47e4443b0140f4de5fb4f": [ - 255 - ], - "0xb378273190f974e017d13db074976d55f57e0d20": [ - 29 - ], - "0xdf516f0df67b53f9fc0d4c443a9b07da4ac3174d": [ - 271 - ], - "0x027c348c69fcf6f311334c7bedef7ddf7eeffff9": [ - 256 - ], - "0xc3cb47f1d74abc82cc9acd748c9c6714f9c77eff": [ - 39 - ], - "0xa084cd6767a27dfa4292b5ace980e7c6d9e12b27": [ - 257 - ], - "0x362930cb6695b4623b300b96755cf1841a9b6766": [ - 114 - ], - "0x9bcd43b2f6f43cb26032edf584f9e511091f83b0": [ - 273, - 258 - ], - "0x588058a144e22d96e235a5aab6e81c9a5749538e": [ - 34 - ], - "0xda9558ddd9e70e74130825bc69ccbd28c7078ecc": [ - 259 - ], - "0xe4e8d412e3dce3357bb420ec24e51f6bcc1a1bc0": [ - 30 - ], - "0x6c153feae296dd6f0249323cf597724a9ebfff33": [ - 28 - ], - "0x5fe0cdf0b1c84cd4a92cec746c84816a3a8b21ef": [ - 268 - ], - "0x2175b1e9f07566bf5f0f99a3325721a2d5760d5b": [ - 260 - ], - "0x6cf8d194568c54ceda4b0dcc148c2d75ec25de5b": [ - 261 - ], - "0xdb4efc647a72ed5fb03c20143b85657dafb6a039": [ - 23 - ], - "0x9b029d74e8770b8a7a88670f5ec69c3c6d33f0e2": [ - 27 - ], - "0x7af5ba6291b15c5053d6dda6bb2cd89909dac39d": [ - 85 - ], - "0x96fe4e4cd275f1f39eea9d6184447c12006b8536": [ - 37 - ], - "0x05dac02c4c226da6824e0fd2a944c97ab6a34c5d": [ - 38 - ], - "0x3692854ae1ce9a91aa0db6888105b466c767e112": [ - 262 - ], - "0x9c271f7a72c036b707f78c8385f99def5d247da0": [ - 263 - ], - "0x5c7305f9a0ad9bbf6a9a98fe1d28bec88b53ad84": [ - 264 - ], - "0x865e8a72e84a19b7218023de3075b157a3860f03": [ - 265 - ], - "0xd7089c7a9071d69325ed37aec4ae385f990391b8": [ - 266 - ], - "0xfc5a5cf12eaff17fd3be6e5e5d0e2259d5cb1a6f": [ - 277 - ], - "0xfdd9405c74824e5e4012b3cad14858b4b5f3532e": [ - 6 - ], - "0x03cbea8c5c2d4218d70e174131a8d8bf37dc0ee0": [ - 7 - ], - "0x9ea8f475e8db91c2fc9ea34c2ded0c1dadec0fd0": [ - 8 - ], - "0x45eed8f7730838a51beef3cf7385efaedb2baaaf": [ - 12 - ], - "0x2f71fbe3acf8d033f721892aa340c4bea59df5aa": [ - 14 - ], - "0x753be339b1bbdf012b6a82e1045bc86f967bf06c": [ - 15 - ], - "0xb7541bd4b6d3829f918d225e4a2fcc36f48c6ec1": [ - 17 - ], - "0x12433d62c99ceea5c8167428e72766eef931ca17": [ - 42 - ], - "0x49b1c333a7285f598a4b68dedcaaf761ecadf0eb": [ - 274 - ], - "0x26071f70cb35ef12154a5e1a52dcad6fe07a3286": [ - 275 - ], - "0x1c1e91b858a503ddcccb81f9ab4194b99d040f6f": [ - 276 - ] - }, - "end_state": { - "0xeb1050ec6160fcf3db72b2adcd950993a23e48b3": [ - 9, - 10, - 13, - 16, - 18, - 19 - ], - "0xa95584c820b5bc990a0572df4faba7fb9f4e210b": [ - 1, - 43 - ], - "0x1350149385d5fdadbfa5527f830d4065f77df2d5": [ - 44 - ], - "0x6f9bb7e454f5b3eb2310343f0e99269dc2bb8a1d": [ - 45, - 22 - ], - "0x0b304924faa64b0f040dca67bc5175dd6078db52": [ - 46 - ], - "0x74630370197b4c4795bfeef6645ee14f8cf8997d": [ - 47 - ], - "0xa362a6b387a80180286ef40d8e6ec6ca2657a9fa": [ - 48 - ], - "0x74be7c259c22b82354c93e0f94f203f986af1423": [ - 49 - ], - "0x89fee8e11e2a238579fb0d59f5ce1dd90c85fe15": [ - 50 - ], - "0x4c82cff7398f3d43b36e41b10ff6f42b14dd9385": [ - 51 - ], - "0x546d241f237b98bb2b807625744af279d54272d0": [ - 52 - ], - "0xb66a0ee5a0ef1a60f11ef102b6a3828f1823d136": [ - 53 - ], - "0x48d683f6bc178285e3e9bfa92f93dec7d502c552": [ - 54 - ], - "0xce04951dae0559ee6c61830ef893c2ac85ee83b1": [ - 55 - ], - "0x585989769f6a97c6dab2c462076be2dd0a5286f7": [ - 56 - ], - "0xdec0de987db64adbe297dac3762178a1b103014e": [ - 57 - ], - "0x52d0fc347560cc997f87984200f4a9344ecdc597": [ - 58 - ], - "0x081076bc1b250650f009bf802425ec4979569a59": [ - 59 - ], - "0xb439b0844d0d9af237ff37dc2379f07b6cd06171": [ - 60 - ], - "0x3a0b6f2023ca63764424b8b3cc84710e42aad151": [ - 61 - ], - "0x290ca510021d18699b268f133813f6262a650d94": [ - 21, - 62 - ], - "0x4cb2776a2550ed12b51e7f27f25287874f576a08": [ - 63 - ], - "0x984a69a51f06044e6b79294c652fae499b333f49": [ - 64 - ], - "0x625a1a58897f3b250a9c68afd52ec283ec94a03d": [ - 65 - ], - "0x693eeae27374b57673bb009e0faa88d908985a30": [ - 66 - ], - "0x5f0ab641ec7240bd9f6885b6d8c15b177f1a8cae": [ - 67 - ], - "0x17a3831b39cc557296d0c322f9c2d42c0b3a8f3f": [ - 68 - ], - "0xcdbd980e0a3a854c11d5d869e622f6c1e1c40c23": [ - 69 - ], - "0x4e3fa58a4e23d408908ade21b48e995fca99072f": [ - 71 - ], - "0x3b0e45ff406c28624aa4013a414e48afffa00a7e": [ - 72 - ], - "0xd6ed1100ac5a3ff39de64937f3ea58fe4a975213": [ - 73 - ], - "0xd23d8aead200401091022e5c4304b32b56042808": [ - 74 - ], - "0x37481b2687f58a8706eca8ee37ccaa090497e7ad": [ - 75 - ], - "0x4980cdcff7ddf6c501266df644e5c685793567e7": [ - 76 - ], - "0xce203f74e732ce2dd6975e4bfd3911599eb431fc": [ - 77 - ], - "0x10b549dfea119302a96f23d7e53f49a059b50037": [ - 78 - ], - "0x9330065a70e54ad29cf60c2c013e69900da13d73": [ - 79 - ], - "0x693a10f33974fda182e34d0d179c5247874897a3": [ - 80 - ], - "0xb7308a79a35c3a24cd5fc8d11c37aada0234b71d": [ - 81 - ], - "0xab3454f4198940432f89872023ebbd64495293b0": [ - 82 - ], - "0x21518af0c47c4113df3ecf7bb232cb3a33083676": [ - 83 - ], - "0x9fd8788496e2edb846789d788eee952bb8f65014": [ - 84 - ], - "0x8ddf6783761cadaac0621a455d595cc7fcd60524": [ - 86 - ], - "0xe386af9ffb851557e294593689b579cd8afa0758": [ - 87 - ], - "0x338c40deba0e9511fa9bafa4f706302aa976f9b5": [ - 88 - ], - "0x09cb05c212ef384ca54825947a72d37c94743ac8": [ - 89 - ], - "0x1aad33f754e47d693562dde3e944332420d27493": [ - 90 - ], - "0xc309151865a7493dd51f611b27d7d5b0323b240e": [ - 91 - ], - "0x40f832b71d2c525a9aa4b4908ec511ed93c8a308": [ - 92 - ], - "0xed2c2cdec695be3a4dc421c1a8a6756dc5a927b6": [ - 93 - ], - "0x48e756eae97c0123cc88c660987793b49e48afa3": [ - 94 - ], - "0xb6e2ae25a80411a1d928f2f613600a6a3a36476c": [ - 95 - ], - "0x06453f99650515950478a7f396fb266e33d2e453": [ - 96 - ], - "0xd2c2e84501c63b7b9897df063288d67060119c99": [ - 97, - 31 - ], - "0x79072f96b6a5e8d69a66e0eaaef49674ef0dd8d3": [ - 98 - ], - "0x4b8c1c25c89ca27434c0ac64a48c360765c7aa5a": [ - 99 - ], - "0xe0a35b164f5c5e44e26d357e4ac88e1b8714090f": [ - 100 - ], - "0x6ce618ec1312fab2ff4985d9498b3514cbce401a": [ - 101 - ], - "0x12667125770eb9fb46c48db659d3275e8fcd2ed7": [ - 32, - 102 - ], - "0x74aadae2c7aa9321314a0a6f53a70eda5ebe103a": [ - 103 - ], - "0x8e1be56368f91eecf8a06cb3be07daf29564a189": [ - 104 - ], - "0x6204c3e753123168fa4b596476aa321f50c9d2c2": [ - 105 - ], - "0x16318b4784ea41cddbcf5a3f2fd8a7a4dbba1bde": [ - 106 - ], - "0x699beef82677d611f97c6cac21ce83891b5683ed": [ - 107 - ], - "0x6067f3605a6deecab3ac78e19c40b6874d847101": [ - 108 - ], - "0xed95cbd2185924807e3b893b7e7ac5dfe2efe33f": [ - 109 - ], - "0x8252a1a673796110ca091344fdae1729e7aea94b": [ - 110 - ], - "0xb10f3ea007de364448d8c379bde4875ba1acba3b": [ - 111 - ], - "0x01695a44f7628f62ad020acf4df26cd0552afa99": [ - 112 - ], - "0xfbb041e1e292e34f90c1333e5360f5ff2f3f6450": [ - 113 - ], - "0x269f6c970581372523a58a630dc462d6568b61a6": [ - 115 - ], - "0x0fb56c793ae84667961fd72d8f2ccbb13082e898": [ - 116 - ], - "0x9799fb7dd26e14b5bebda156a7ff7b870a2429ef": [ - 117 - ], - "0x616c18b6e555c62570fa6a513637c3135cee3871": [ - 118 - ], - "0x9b68cb6aff0a3b6eb591e414c653737324d80485": [ - 119 - ], - "0xba55bdbf959df826da6c35487eb15fad2164662d": [ - 120 - ], - "0x9ab5b54092a1596a32127163b7b0176445eb1b0a": [ - 121, - 25 - ], - "0xdc3e00cc50dc4b79d1aa26ef35b03d99ab213974": [ - 122 - ], - "0xd6bba09dee0ddc465c22a23cb8548a524eb994c8": [ - 123 - ], - "0x2f476a1680d2e1fc79fa3ca03a629d94dc2b148c": [ - 124 - ], - "0x46688024f0022d9bdcd69feec88b7a5990d258de": [ - 125 - ], - "0xc49b6c714feaf22b12eb02a01521dab6edd1fcbd": [ - 126 - ], - "0x307e1b27659a9b00a7a93059b64637d024fd017d": [ - 211, - 127 - ], - "0x07953ec0617854fbfbf9323268547d604a0b1a8b": [ - 128 - ], - "0xf3a57bc7ebd5be52604c08d8954673e24330e2b1": [ - 129 - ], - "0x715955bb4c12450eed13c2033fa7fe750df593e3": [ - 130 - ], - "0xbbf42ca0b874fdc113a957370502b8c8b3af7480": [ - 131 - ], - "0xf60667353bdb1d73cf94c7feab49f76c9a3a4c76": [ - 132 - ], - "0xe59267a4420d3988caab50e840f9d6f179ffdee6": [ - 133 - ], - "0x97d34c151214875fa2c42e6a7d54ff8e967fa208": [ - 134 - ], - "0x86a12a8a886a218986ed1c42382457d15d333890": [ - 135 - ], - "0xfe37ca693e70fd8b333d6d861ebe271e1d10f94c": [ - 136 - ], - "0xf109731b8fe0f4c03ddc28e6da7b210f8adcc722": [ - 137 - ], - "0xa4fcccd4faa32dbe95637f7457010ba243c65e19": [ - 138 - ], - "0xc2456529b5b93ef85264ca178d29b6c660fac5a7": [ - 139 - ], - "0x7a006f71f27626ea7697b0e46633d7c9b82b40a2": [ - 140 - ], - "0x8f9dce6ae6d0c6abf5e8f36cb6c75d7389bbee84": [ - 141 - ], - "0xab59cf03b23bcdffbe73e837dc34e5765b2920d4": [ - 142 - ], - "0xef8b64f30aa834384c85a1759c9719a6dd39eabd": [ - 143 - ], - "0x86b461b490e581a988f59607d8bf30c389cd3d6f": [ - 144 - ], - "0xfc32ec311f4d388b0f4405f97bb46a8c4fbada29": [ - 145 - ], - "0xd800f95673773551f9b0aaeb917b4ed7c8729fed": [ - 146 - ], - "0xac6ad2e9eff402007965927387505710e9744371": [ - 147 - ], - "0x3f6e2af7a45ddbffb5d5686e4e44f23e906d4233": [ - 148 - ], - "0x8fa14c10a998d0ec3b8f2209b5d439b30d41090a": [ - 149 - ], - "0x7a5611cc35c99dbe266078f56c09edd193ff9280": [ - 150 - ], - "0x41d293f4804b390a84ea3c3898833c21a2f04423": [ - 151 - ], - "0x9ed770b170f215aa846c999677f572105f4a48fb": [ - 152 - ], - "0x3abfe7806c2bddcc9795b8cdd68d619fb5f7e3ef": [ - 153 - ], - "0x06a632fa59e213f03f17a70bd6da16b99a6f205a": [ - 154 - ], - "0xe33f7d15b469afabeddf80a2fb90f32411053267": [ - 155 - ], - "0xb2788f9e443bc3eb44bd6388215748c79b517d4e": [ - 156 - ], - "0x14d92832265eeafdef9e526356fefc90105966c3": [ - 157 - ], - "0x7f66edeccefdaa57ce61983e6c7eb89450feb024": [ - 158 - ], - "0xf44217a8b6b3f258bffead635c226528aa516aea": [ - 159 - ], - "0x6b56bdc58dde8cccacb03c28ce36c129bd42a083": [ - 160 - ], - "0x40bba49b15d5efbf9e45d47ef219656c9b04321f": [ - 161 - ], - "0xec0431a9c8d2e12a6c411d77e7bb0183f86913c2": [ - 162 - ], - "0xeb073a004fb6927ec44230226b0cbdedbee4ed97": [ - 163 - ], - "0x6ffc0290cf7f88637fbb1f920b9df9d264b3783d": [ - 164 - ], - "0xdc377dc2d3f497f8d24a3b1d7f80bd476473a2bb": [ - 165 - ], - "0xeb81f7f62d9cd0e9a9aa2617ff2ee8c0b01f6bbb": [ - 166 - ], - "0x741950e9c579a8c1c9a2e60cb6597fc33da2d37c": [ - 167 - ], - "0xb0eb8b4003fdd74f3c7994fbe5fce95ad10e3bcc": [ - 168 - ], - "0x0499491b005243073c3f0ee8873885ce2a2b2206": [ - 169 - ], - "0xd7f33cf1de3e9339978afb25a64562cf4615dd9e": [ - 170 - ], - "0xf96d09c553db50ef8198eed965df9e660133c23a": [ - 171 - ], - "0x2e15b6aa2f32896f024a139559464ec55bb0da00": [ - 172 - ], - "0xf84454985b6636ba2d643cfbcc6c30c51892e8bf": [ - 173 - ], - "0x8637054754d4a18c8aa2f3be4190745bf92a0054": [ - 174 - ], - "0x9dc4e75b05ef3fcc258040471a6bc8ab1fddebbb": [ - 175 - ], - "0xc9e7d61bbdef3f821da08bfdb19a2bf7e0ec60b7": [ - 178 - ], - "0x057ca4a6e2c11565be71a8453a9f3f86b5f2bba7": [ - 179 - ], - "0x3b4daa9fbd96445faff116164ff634c976f3ad58": [ - 180 - ], - "0x8b0b0a73cc2a0a10e63b2d24b37f4c9f78ba4904": [ - 181 - ], - "0x1e8ee48d0621289297693fc98914da2efdce1477": [ - 182 - ], - "0xc0f962face7e5a0ee212d6d71bd60f5336b10d1a": [ - 183 - ], - "0x4e0c09589d862485d724f3f8c1ff5745a52e0570": [ - 184 - ], - "0x62625318578756f7f429a0124e5fdfba7c89f534": [ - 185 - ], - "0xdc6447010c602bbcbdbe2aaff27d24af55fe5b75": [ - 186, - 267 - ], - "0x01c3137ee9751663ddd96c47a6c44df7b48faae7": [ - 187 - ], - "0xcb7952f98f198a56af4b764b28b1bd165e2ceeef": [ - 188 - ], - "0xa3f35c425f31410741a0a455cbc23b1314ac5dc7": [ - 189 - ], - "0xdd4b82486b606d70de0a1ad1a5446dd724fc793a": [ - 190 - ], - "0xe2d9a9e35f2e657804f6d2149f9bea9db06176ff": [ - 191 - ], - "0x88650dddf2c281d73ee26e1e5416dab11ce87f69": [ - 192 - ], - "0x11419d53a310375e690356eef380da6b9254d99b": [ - 193 - ], - "0x58a3feb357d7dabc120910c31b6b33d453bc6022": [ - 194 - ], - "0xc92e7fb11c535579cc0807d655464e2999583d20": [ - 195 - ], - "0x3df85ebb5a2f7d1178e3482bd56523037d850f71": [ - 196 - ], - "0x5bf94136af40fce25de77ed59782a7483fd0dc3b": [ - 197 - ], - "0x6d6f9ae649fec4fca9065752acd8286e1c7c5e3e": [ - 198 - ], - "0xb6ef5ef50445797a88d9eae000c577d5df626f00": [ - 199 - ], - "0x2655a14770b9c5f04346475d3b2f1f9220ac55bb": [ - 200 - ], - "0x59f54d4d3aa9905aa3c0046b219fc1e9be5df13e": [ - 201 - ], - "0xe21619a0c4e7156de1238e6cdd2bbece8d1adadb": [ - 202 - ], - "0x8c2f4724c7a5b7e46965671b1b301e7e6b67f87c": [ - 203 - ], - "0xc1ba551d7d410d6352f8380795ba6cad7ac6fc64": [ - 204 - ], - "0x947a5a2e5b096752f0f3663964dd52151e3ad2b9": [ - 205 - ], - "0xc08d8a00960666eac963591cef25b9db27f97200": [ - 206 - ], - "0x416a3427414b6c98adab70f48a2a904d1cf3f446": [ - 207 - ], - "0x5984bb82f11171cb1dc2287e2a6935c44d491538": [ - 208 - ], - "0xa12810ce00eef03951877aafe2c9b16d3041fa19": [ - 209 - ], - "0x640d4b5181f4f89ddd01a78d04ef079171ab2474": [ - 210 - ], - "0x8cd0e624102974b6636ce653573d62b98b2b4e85": [ - 213 - ], - "0x036e1b95308e68fed27067df4b497ee8bd669db7": [ - 214 - ], - "0x6d526f6b4c86fbdc8e359e6bef4cd6a42acea2d7": [ - 215 - ], - "0x39c31a899662da8bba43862c82c8ba531dc61390": [ - 216 - ], - "0x6842824216c3476753ba6c52a2388fb8d6bd20a4": [ - 217 - ], - "0x7452e7d530078dbd6a2ed65007bea00a4d60f138": [ - 218 - ], - "0xd67f15a5401df029218df828a9bda0a551609578": [ - 219 - ], - "0xea6ae8c291897a9a88f847d76e055ca2c7b49f9f": [ - 220 - ], - "0x100cc424f8c049cb2882ce9d3ce2f8ca63bd80e0": [ - 221 - ], - "0x508f5587e20dba23ae0e2a4577709af23c6537cd": [ - 222 - ], - "0x16951212197b6e995ab4cecc5cf6dbea976782dd": [ - 223 - ], - "0x5e5788ced34c51d2d20e950bd0dd4a28e7e78e27": [ - 224 - ], - "0xb080e60ea6251cf7212d1ccb30b683c55d11f3e4": [ - 225 - ], - "0x2a1500fe1d41c73589667376fe5403c34dd2ab20": [ - 226 - ], - "0x5a1e05051788ce38a52e7e757d39767b4d91edba": [ - 227 - ], - "0x0fe534525898f0a571b97abeda632cf0968fa62a": [ - 228 - ], - "0xb2f456886367c8e50566377ec6d9293d4da5bb81": [ - 229 - ], - "0x1a36d989434f8b7743d645ebf53d5124a4bcae2d": [ - 230 - ], - "0x0813e1b0a5b1d0d67ceac68696591f5aecc613c7": [ - 231 - ], - "0x3805c1400a22b39ea349c08be3604a43a22fa445": [ - 232 - ], - "0xbb68dcf509480f648e3c501d2dbbc5636b82f689": [ - 234 - ], - "0x210351fcc900c1e5ef4c7b1bf3d37ab33ca87114": [ - 235 - ], - "0xa136a3abc184bf70de3614822b2a6e6d8df018e5": [ - 236 - ], - "0xbda87f0bd638cd702973745cd908f758e075e723": [ - 237 - ], - "0xde0e14e314ec13cabc21272f9dd27dec0c92b504": [ - 238 - ], - "0x9cd5f86e1690daa9167ce702f30e8e83d4d9352e": [ - 239 - ], - "0xdc70a024af3e898837b3c04677581146a746ecb7": [ - 240 - ], - "0xf3d476566bcc8e882a3910f1471428522449d89e": [ - 241 - ], - "0x612dd12feff854a04db3ef0a56f88e5cd16ee4c6": [ - 242 - ], - "0x9a4249c3c0511beb1acb4d49ec9143e886759a84": [ - 233 - ], - "0x78b1a53dec02c2c8ff6ba7da9f6cca1f5c044c6e": [ - 212 - ], - "0x406fdeeaa6a4fd93103390306a11a6cec5d25445": [ - 177 - ], - "0x27e39999cc3cc148d579cadf4febc946008dd48b": [ - 176 - ], - "0xd1f4778903c3473b61c8b265ec60173d2670b17e": [ - 243 - ], - "0x296e0c21db4061ebf971e55d5db85011e7ff9797": [ - 244 - ], - "0x3e2dee92f81607f4210636ec21525c6523609d84": [ - 245 - ], - "0x6bc2a8f837ffa631fb7f969b7c70f7c7e46b24d3": [ - 246 - ], - "0x728754bf437ec16d197e06af053c7b006b89e330": [ - 247 - ], - "0x037771a4c189d3b9c0b9db7b7cb2c4ea6629bb61": [ - 248 - ], - "0x39d10a4ad72a9b5bf7f1994233fdc331b01c685b": [ - 249, - 11 - ], - "0x91a98fd033434adf63223f88064c95a89e08061c": [ - 2 - ], - "0x4ae607c31760bdbfef336d9ff999aea69150b872": [ - 250 - ], - "0x758e5c5c4dd4c6aa1384f0495656a4f7c2f49ec3": [ - 4 - ], - "0x8485b2522425f5449fc1d2e54579f719fca88a02": [ - 3 - ], - "0xede66ed0fca1a9ebb052cce681c89d7535408ccf": [ - 24 - ], - "0xa0b14f6fe7f647e84b4ac954036865330a9eac5c": [ - 5 - ], - "0x188a7c5b071c01ad31ad80ae7fc28b1b6f389fd6": [ - 35 - ], - "0x73afef607da2dbd27bd9c83e9e9297ae9ca1fd2b": [ - 40 - ], - "0x54b3ff56f75671d91d85d44bccedbc9179e09afc": [ - 272, - 70 - ], - "0x5b191f5a2b4a867c4ed71858daccc51fc59c69c0": [ - 251, - 36 - ], - "0xfb40932271fc9db9dbf048e80697e2da4aa57250": [ - 269 - ], - "0xd5f4cbfadb349be5dba580f9360eb6867a1d590e": [ - 41 - ], - "0x0450a946a93cf6f81fd72f1e85e16a8826bc9c4d": [ - 270 - ], - "0xedf3af29040e069a4cbd6e13fbead2500733f2b1": [ - 33 - ], - "0x8a252b597856b06b3e7efe5d798d73b3c5fbf5ca": [ - 20 - ], - "0xa52af0e35970783f587b77f7b8db94871435009c": [ - 26, - 252 - ], - "0xd8c860d789ec1c6ae9631b680e6555f25bc28331": [ - 253 - ], - "0xbf970e507672b30abce90bde4520e3939d423adb": [ - 254 - ], - "0xafd8fb69e850d2da8ac47e4443b0140f4de5fb4f": [ - 255 - ], - "0xb378273190f974e017d13db074976d55f57e0d20": [ - 29 - ], - "0xdf516f0df67b53f9fc0d4c443a9b07da4ac3174d": [ - 271 - ], - "0x027c348c69fcf6f311334c7bedef7ddf7eeffff9": [ - 256 - ], - "0xc3cb47f1d74abc82cc9acd748c9c6714f9c77eff": [ - 39 - ], - "0xa084cd6767a27dfa4292b5ace980e7c6d9e12b27": [ - 257 - ], - "0x362930cb6695b4623b300b96755cf1841a9b6766": [ - 114 - ], - "0x9bcd43b2f6f43cb26032edf584f9e511091f83b0": [ - 273, - 258 - ], - "0x588058a144e22d96e235a5aab6e81c9a5749538e": [ - 34 - ], - "0xda9558ddd9e70e74130825bc69ccbd28c7078ecc": [ - 259 - ], - "0xe4e8d412e3dce3357bb420ec24e51f6bcc1a1bc0": [ - 30 - ], - "0x6c153feae296dd6f0249323cf597724a9ebfff33": [ - 28 - ], - "0x5fe0cdf0b1c84cd4a92cec746c84816a3a8b21ef": [ - 268 - ], - "0x2175b1e9f07566bf5f0f99a3325721a2d5760d5b": [ - 260 - ], - "0x6cf8d194568c54ceda4b0dcc148c2d75ec25de5b": [ - 261 - ], - "0xdb4efc647a72ed5fb03c20143b85657dafb6a039": [ - 23 - ], - "0x9b029d74e8770b8a7a88670f5ec69c3c6d33f0e2": [ - 27 - ], - "0x7af5ba6291b15c5053d6dda6bb2cd89909dac39d": [ - 85 - ], - "0x96fe4e4cd275f1f39eea9d6184447c12006b8536": [ - 37 - ], - "0x05dac02c4c226da6824e0fd2a944c97ab6a34c5d": [ - 38 - ], - "0x3692854ae1ce9a91aa0db6888105b466c767e112": [ - 262 - ], - "0x9c271f7a72c036b707f78c8385f99def5d247da0": [ - 263 - ], - "0x5c7305f9a0ad9bbf6a9a98fe1d28bec88b53ad84": [ - 264 - ], - "0x865e8a72e84a19b7218023de3075b157a3860f03": [ - 265 - ], - "0xd7089c7a9071d69325ed37aec4ae385f990391b8": [ - 266 - ], - "0xfc5a5cf12eaff17fd3be6e5e5d0e2259d5cb1a6f": [ - 277 - ], - "0xfdd9405c74824e5e4012b3cad14858b4b5f3532e": [ - 6 - ], - "0x03cbea8c5c2d4218d70e174131a8d8bf37dc0ee0": [ - 7 - ], - "0x9ea8f475e8db91c2fc9ea34c2ded0c1dadec0fd0": [ - 8 - ], - "0x45eed8f7730838a51beef3cf7385efaedb2baaaf": [ - 12 - ], - "0x2f71fbe3acf8d033f721892aa340c4bea59df5aa": [ - 14 - ], - "0x753be339b1bbdf012b6a82e1045bc86f967bf06c": [ - 15 - ], - "0xb7541bd4b6d3829f918d225e4a2fcc36f48c6ec1": [ - 17 - ], - "0x12433d62c99ceea5c8167428e72766eef931ca17": [ - 42 - ], - "0x49b1c333a7285f598a4b68dedcaaf761ecadf0eb": [ - 274 - ], - "0x26071f70cb35ef12154a5e1a52dcad6fe07a3286": [ - 275 - ], - "0x1c1e91b858a503ddcccb81f9ab4194b99d040f6f": [ - 276 - ], - "0x8abc16e919c61d5863b34f920dfb4dc4a97bf036": [ - 278 - ] - } - }, - "pilot_vault": { - "start_state": { - "0xa95584c820b5bc990a0572df4faba7fb9f4e210b": { - "balance": 5000000000000000, - "last_positive_balance_update_day": "2025-11-14", - "last_negative_balance_update_day": "2025-11-14" - }, - "0x6f9bb7e454f5b3eb2310343f0e99269dc2bb8a1d": { - "balance": 102819000000000000000, - "last_positive_balance_update_day": "2025-12-02", - "last_negative_balance_update_day": "" - }, - "0x290ca510021d18699b268f133813f6262a650d94": { - "balance": 2000000000000000000, - "last_positive_balance_update_day": "2025-11-17", - "last_negative_balance_update_day": "" - }, - "0xd2c2e84501c63b7b9897df063288d67060119c99": { - "balance": 40000000000000000000, - "last_positive_balance_update_day": "2025-11-18", - "last_negative_balance_update_day": "" - }, - "0x12667125770eb9fb46c48db659d3275e8fcd2ed7": { - "balance": 39000000000000000000, - "last_positive_balance_update_day": "2025-12-02", - "last_negative_balance_update_day": "" - }, - "0x9ab5b54092a1596a32127163b7b0176445eb1b0a": { - "balance": 36701000000000000000, - "last_positive_balance_update_day": "2025-11-24", - "last_negative_balance_update_day": "" - }, - "0xdc6447010c602bbcbdbe2aaff27d24af55fe5b75": { - "balance": 24910000000000000000, - "last_positive_balance_update_day": "2025-11-29", - "last_negative_balance_update_day": "" - }, - "0x39d10a4ad72a9b5bf7f1994233fdc331b01c685b": { - "balance": 1002000000000000000, - "last_positive_balance_update_day": "2025-11-15", - "last_negative_balance_update_day": "" - }, - "0x91a98fd033434adf63223f88064c95a89e08061c": { - "balance": 8003750565999172549, - "last_positive_balance_update_day": "2025-11-13", - "last_negative_balance_update_day": "2025-11-12" - }, - "0x202065dfb813295d0b095a39e36e3b3296210505": { - "balance": 534187211964517143, - "last_positive_balance_update_day": "2025-12-02", - "last_negative_balance_update_day": "2025-11-13" - }, - "0x758e5c5c4dd4c6aa1384f0495656a4f7c2f49ec3": { - "balance": 134000000000000000, - "last_positive_balance_update_day": "2025-11-17", - "last_negative_balance_update_day": "2025-11-15" - }, - "0xede66ed0fca1a9ebb052cce681c89d7535408ccf": { - "balance": 329887899954383005, - "last_positive_balance_update_day": "2025-11-17", - "last_negative_balance_update_day": "" - }, - "0xa0b14f6fe7f647e84b4ac954036865330a9eac5c": { - "balance": 80000000000000000, - "last_positive_balance_update_day": "2025-11-17", - "last_negative_balance_update_day": "" - }, - "0x188a7c5b071c01ad31ad80ae7fc28b1b6f389fd6": { - "balance": 32000000000000000000, - "last_positive_balance_update_day": "2025-11-17", - "last_negative_balance_update_day": "" - }, - "0x73afef607da2dbd27bd9c83e9e9297ae9ca1fd2b": { - "balance": 25000000000000000000, - "last_positive_balance_update_day": "2025-11-18", - "last_negative_balance_update_day": "" - }, - "0x54b3ff56f75671d91d85d44bccedbc9179e09afc": { - "balance": 25000000000000000000, - "last_positive_balance_update_day": "2025-11-18", - "last_negative_balance_update_day": "" - }, - "0x5b191f5a2b4a867c4ed71858daccc51fc59c69c0": { - "balance": 30000000000000000000, - "last_positive_balance_update_day": "2025-11-18", - "last_negative_balance_update_day": "" - }, - "0xfb40932271fc9db9dbf048e80697e2da4aa57250": { - "balance": 25000000000000000000, - "last_positive_balance_update_day": "2025-11-18", - "last_negative_balance_update_day": "" - }, - "0xd5f4cbfadb349be5dba580f9360eb6867a1d590e": { - "balance": 29700000000000000000, - "last_positive_balance_update_day": "2025-11-28", - "last_negative_balance_update_day": "" - }, - "0x0450a946a93cf6f81fd72f1e85e16a8826bc9c4d": { - "balance": 25000000000000000000, - "last_positive_balance_update_day": "2025-11-19", - "last_negative_balance_update_day": "" - }, - "0xedf3af29040e069a4cbd6e13fbead2500733f2b1": { - "balance": 35000000000000000000, - "last_positive_balance_update_day": "2025-11-19", - "last_negative_balance_update_day": "" - }, - "0x8a252b597856b06b3e7efe5d798d73b3c5fbf5ca": { - "balance": 25000000000000000000, - "last_positive_balance_update_day": "2025-11-19", - "last_negative_balance_update_day": "" - }, - "0xa52af0e35970783f587b77f7b8db94871435009c": { - "balance": 49918800000000000000, - "last_positive_balance_update_day": "2025-11-22", - "last_negative_balance_update_day": "" - }, - "0xb378273190f974e017d13db074976d55f57e0d20": { - "balance": 50000000000000000000, - "last_positive_balance_update_day": "2025-11-20", - "last_negative_balance_update_day": "" - }, - "0xdf516f0df67b53f9fc0d4c443a9b07da4ac3174d": { - "balance": 25000000000000000000, - "last_positive_balance_update_day": "2025-11-20", - "last_negative_balance_update_day": "" - }, - "0xc3cb47f1d74abc82cc9acd748c9c6714f9c77eff": { - "balance": 25000000000000000000, - "last_positive_balance_update_day": "2025-11-21", - "last_negative_balance_update_day": "" - }, - "0x9bcd43b2f6f43cb26032edf584f9e511091f83b0": { - "balance": 25000000000000000000, - "last_positive_balance_update_day": "2025-11-24", - "last_negative_balance_update_day": "" - }, - "0x588058a144e22d96e235a5aab6e81c9a5749538e": { - "balance": 34900000000000000000, - "last_positive_balance_update_day": "2025-11-25", - "last_negative_balance_update_day": "" - }, - "0xe4e8d412e3dce3357bb420ec24e51f6bcc1a1bc0": { - "balance": 50000000000000000000, - "last_positive_balance_update_day": "2025-11-27", - "last_negative_balance_update_day": "" - }, - "0x6c153feae296dd6f0249323cf597724a9ebfff33": { - "balance": 91300000000000000000, - "last_positive_balance_update_day": "2025-11-28", - "last_negative_balance_update_day": "" - }, - "0x5fe0cdf0b1c84cd4a92cec746c84816a3a8b21ef": { - "balance": 25000000000000000000, - "last_positive_balance_update_day": "2025-11-28", - "last_negative_balance_update_day": "" - }, - "0xdb4efc647a72ed5fb03c20143b85657dafb6a039": { - "balance": 99700000000000000000, - "last_positive_balance_update_day": "2025-11-29", - "last_negative_balance_update_day": "" - }, - "0x9b029d74e8770b8a7a88670f5ec69c3c6d33f0e2": { - "balance": 24500000000000000000, - "last_positive_balance_update_day": "2025-11-30", - "last_negative_balance_update_day": "" - }, - "0x96fe4e4cd275f1f39eea9d6184447c12006b8536": { - "balance": 29870000000000000000, - "last_positive_balance_update_day": "2025-12-02", - "last_negative_balance_update_day": "" - }, - "0x05dac02c4c226da6824e0fd2a944c97ab6a34c5d": { - "balance": 25050000000000000000, - "last_positive_balance_update_day": "2025-12-02", - "last_negative_balance_update_day": "" - } - }, - "end_state": { - "0xa95584c820b5bc990a0572df4faba7fb9f4e210b": { - "balance": 5000000000000000, - "last_positive_balance_update_day": "2025-11-14", - "last_negative_balance_update_day": "2025-11-14" - }, - "0x6f9bb7e454f5b3eb2310343f0e99269dc2bb8a1d": { - "balance": 102819000000000000000, - "last_positive_balance_update_day": "2025-12-02", - "last_negative_balance_update_day": "" - }, - "0x52d0fc347560cc997f87984200f4a9344ecdc597": { - "balance": 10333853293515596790, - "last_positive_balance_update_day": "2025-12-11", - "last_negative_balance_update_day": "" - }, - "0x290ca510021d18699b268f133813f6262a650d94": { - "balance": 2000000000000000000, - "last_positive_balance_update_day": "2025-11-17", - "last_negative_balance_update_day": "" - }, - "0xe386af9ffb851557e294593689b579cd8afa0758": { - "balance": 100055503276642809, - "last_positive_balance_update_day": "2025-12-11", - "last_negative_balance_update_day": "" - }, - "0xd2c2e84501c63b7b9897df063288d67060119c99": { - "balance": 40000000000000000000, - "last_positive_balance_update_day": "2025-11-18", - "last_negative_balance_update_day": "" - }, - "0x12667125770eb9fb46c48db659d3275e8fcd2ed7": { - "balance": 39000000000000000000, - "last_positive_balance_update_day": "2025-12-02", - "last_negative_balance_update_day": "" - }, - "0x8252a1a673796110ca091344fdae1729e7aea94b": { - "balance": 9935723976098399651, - "last_positive_balance_update_day": "2025-12-11", - "last_negative_balance_update_day": "" - }, - "0xfbb041e1e292e34f90c1333e5360f5ff2f3f6450": { - "balance": 4968881026988266501, - "last_positive_balance_update_day": "2025-12-11", - "last_negative_balance_update_day": "" - }, - "0x9ab5b54092a1596a32127163b7b0176445eb1b0a": { - "balance": 36701000000000000000, - "last_positive_balance_update_day": "2025-11-24", - "last_negative_balance_update_day": "" - }, - "0xdc6447010c602bbcbdbe2aaff27d24af55fe5b75": { - "balance": 24910000000000000000, - "last_positive_balance_update_day": "2025-11-29", - "last_negative_balance_update_day": "" - }, - "0x210351fcc900c1e5ef4c7b1bf3d37ab33ca87114": { - "balance": 948902577169175117, - "last_positive_balance_update_day": "2025-12-11", - "last_negative_balance_update_day": "" - }, - "0x728754bf437ec16d197e06af053c7b006b89e330": { - "balance": 312018837922214793, - "last_positive_balance_update_day": "2025-12-11", - "last_negative_balance_update_day": "" - }, - "0x39d10a4ad72a9b5bf7f1994233fdc331b01c685b": { - "balance": 1002000000000000000, - "last_positive_balance_update_day": "2025-11-15", - "last_negative_balance_update_day": "" - }, - "0x91a98fd033434adf63223f88064c95a89e08061c": { - "balance": 8003750565999172549, - "last_positive_balance_update_day": "2025-11-13", - "last_negative_balance_update_day": "2025-11-12" - }, - "0x202065dfb813295d0b095a39e36e3b3296210505": { - "balance": 1056298019096578403, - "last_positive_balance_update_day": "2025-12-11", - "last_negative_balance_update_day": "2025-11-13" - }, - "0x758e5c5c4dd4c6aa1384f0495656a4f7c2f49ec3": { - "balance": 134000000000000000, - "last_positive_balance_update_day": "2025-11-17", - "last_negative_balance_update_day": "2025-11-15" - }, - "0xede66ed0fca1a9ebb052cce681c89d7535408ccf": { - "balance": 329887899954383005, - "last_positive_balance_update_day": "2025-11-17", - "last_negative_balance_update_day": "" - }, - "0xa0b14f6fe7f647e84b4ac954036865330a9eac5c": { - "balance": 80000000000000000, - "last_positive_balance_update_day": "2025-11-17", - "last_negative_balance_update_day": "" - }, - "0x188a7c5b071c01ad31ad80ae7fc28b1b6f389fd6": { - "balance": 32000000000000000000, - "last_positive_balance_update_day": "2025-11-17", - "last_negative_balance_update_day": "" - }, - "0x73afef607da2dbd27bd9c83e9e9297ae9ca1fd2b": { - "balance": 25000000000000000000, - "last_positive_balance_update_day": "2025-11-18", - "last_negative_balance_update_day": "" - }, - "0x54b3ff56f75671d91d85d44bccedbc9179e09afc": { - "balance": 25000000000000000000, - "last_positive_balance_update_day": "2025-11-18", - "last_negative_balance_update_day": "" - }, - "0x5b191f5a2b4a867c4ed71858daccc51fc59c69c0": { - "balance": 30000000000000000000, - "last_positive_balance_update_day": "2025-11-18", - "last_negative_balance_update_day": "" - }, - "0xfb40932271fc9db9dbf048e80697e2da4aa57250": { - "balance": 25000000000000000000, - "last_positive_balance_update_day": "2025-11-18", - "last_negative_balance_update_day": "" - }, - "0xd5f4cbfadb349be5dba580f9360eb6867a1d590e": { - "balance": 29700000000000000000, - "last_positive_balance_update_day": "2025-11-28", - "last_negative_balance_update_day": "" - }, - "0x0450a946a93cf6f81fd72f1e85e16a8826bc9c4d": { - "balance": 25000000000000000000, - "last_positive_balance_update_day": "2025-11-19", - "last_negative_balance_update_day": "" - }, - "0xedf3af29040e069a4cbd6e13fbead2500733f2b1": { - "balance": 35000000000000000000, - "last_positive_balance_update_day": "2025-11-19", - "last_negative_balance_update_day": "" - }, - "0x8a252b597856b06b3e7efe5d798d73b3c5fbf5ca": { - "balance": 25000000000000000000, - "last_positive_balance_update_day": "2025-11-19", - "last_negative_balance_update_day": "" - }, - "0xa52af0e35970783f587b77f7b8db94871435009c": { - "balance": 49918800000000000000, - "last_positive_balance_update_day": "2025-11-22", - "last_negative_balance_update_day": "" - }, - "0xafd8fb69e850d2da8ac47e4443b0140f4de5fb4f": { - "balance": 41733193364711737, - "last_positive_balance_update_day": "2025-12-11", - "last_negative_balance_update_day": "" - }, - "0xb378273190f974e017d13db074976d55f57e0d20": { - "balance": 50000000000000000000, - "last_positive_balance_update_day": "2025-11-20", - "last_negative_balance_update_day": "" - }, - "0xdf516f0df67b53f9fc0d4c443a9b07da4ac3174d": { - "balance": 25000000000000000000, - "last_positive_balance_update_day": "2025-11-20", - "last_negative_balance_update_day": "" - }, - "0xc3cb47f1d74abc82cc9acd748c9c6714f9c77eff": { - "balance": 25000000000000000000, - "last_positive_balance_update_day": "2025-11-21", - "last_negative_balance_update_day": "" - }, - "0x362930cb6695b4623b300b96755cf1841a9b6766": { - "balance": 1093400000000000000, - "last_positive_balance_update_day": "2025-12-11", - "last_negative_balance_update_day": "" - }, - "0x9bcd43b2f6f43cb26032edf584f9e511091f83b0": { - "balance": 25000000000000000000, - "last_positive_balance_update_day": "2025-11-24", - "last_negative_balance_update_day": "" - }, - "0x588058a144e22d96e235a5aab6e81c9a5749538e": { - "balance": 34900000000000000000, - "last_positive_balance_update_day": "2025-11-25", - "last_negative_balance_update_day": "" - }, - "0xda9558ddd9e70e74130825bc69ccbd28c7078ecc": { - "balance": 54656871953679352, - "last_positive_balance_update_day": "2025-12-11", - "last_negative_balance_update_day": "" - }, - "0xe4e8d412e3dce3357bb420ec24e51f6bcc1a1bc0": { - "balance": 50000000000000000000, - "last_positive_balance_update_day": "2025-11-27", - "last_negative_balance_update_day": "" - }, - "0x6c153feae296dd6f0249323cf597724a9ebfff33": { - "balance": 91300000000000000000, - "last_positive_balance_update_day": "2025-11-28", - "last_negative_balance_update_day": "" - }, - "0x5fe0cdf0b1c84cd4a92cec746c84816a3a8b21ef": { - "balance": 25000000000000000000, - "last_positive_balance_update_day": "2025-11-28", - "last_negative_balance_update_day": "" - }, - "0xdb4efc647a72ed5fb03c20143b85657dafb6a039": { - "balance": 99700000000000000000, - "last_positive_balance_update_day": "2025-11-29", - "last_negative_balance_update_day": "" - }, - "0x9b029d74e8770b8a7a88670f5ec69c3c6d33f0e2": { - "balance": 24500000000000000000, - "last_positive_balance_update_day": "2025-11-30", - "last_negative_balance_update_day": "" - }, - "0x96fe4e4cd275f1f39eea9d6184447c12006b8536": { - "balance": 29870000000000000000, - "last_positive_balance_update_day": "2025-12-02", - "last_negative_balance_update_day": "" - }, - "0x05dac02c4c226da6824e0fd2a944c97ab6a34c5d": { - "balance": 25050000000000000000, - "last_positive_balance_update_day": "2025-12-02", - "last_negative_balance_update_day": "" - }, - "0x9c271f7a72c036b707f78c8385f99def5d247da0": { - "balance": 5961705151466418460, - "last_positive_balance_update_day": "2025-12-11", - "last_negative_balance_update_day": "" - }, - "0xfc5a5cf12eaff17fd3be6e5e5d0e2259d5cb1a6f": { - "balance": 784828804165223, - "last_positive_balance_update_day": "2025-12-11", - "last_negative_balance_update_day": "" - }, - "0x49b1c333a7285f598a4b68dedcaaf761ecadf0eb": { - "balance": 993756350401335689, - "last_positive_balance_update_day": "2025-12-11", - "last_negative_balance_update_day": "" - } - } - } -} \ No newline at end of file diff --git a/test/test_nft_balance.py b/test/test_nft_balance.py index b36e1f4..0ceeff5 100644 --- a/test/test_nft_balance.py +++ b/test/test_nft_balance.py @@ -3,7 +3,7 @@ from collections import defaultdict -use_state_file = ["../lp_balances_snapshot.json", "84.json"] +use_state_file = ["132.json", "84.json"] # ERC721 ABI for balanceOf and ownerOf functions ERC721_ABI = [ diff --git a/test/test_user_balance.py b/test/test_user_balance.py index a2b3f33..ef178bb 100644 --- a/test/test_user_balance.py +++ b/test/test_user_balance.py @@ -2,7 +2,7 @@ from test.utils.compare_state_and_onchain_data import compare_state_and_onchain_data -use_state_file = ["../lp_balances_snapshot.json", "84.json"] +use_state_file = ["132.json", "84.json"] use_state_file_index = 0 ERC20_ABI = [