Skip to content

Commit dae8fbc

Browse files
committed
Add: checks
1 parent 1c4d7c1 commit dae8fbc

3 files changed

Lines changed: 111 additions & 63 deletions

File tree

integrations/silo_finance.py

Lines changed: 0 additions & 45 deletions
This file was deleted.
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
import logging
2+
from rich.console import Console
3+
4+
from constants.silo_finance import SILO_FINANCE_INTEGRATION_ID_TO_START_BLOCK
5+
from constants.summary_columns import SummaryColumn
6+
from integrations.integration_ids import IntegrationID as IntID
7+
from constants.chains import Chain
8+
from utils.silo_finance import SiloFinance
9+
10+
logger = logging.getLogger("Silo Finance LP-eUSDe")
11+
logger.setLevel(logging.INFO)
12+
13+
if __name__ == "__main__":
14+
console = Console()
15+
16+
integration = SiloFinance(
17+
integration_id=IntID.SILO_FINANCE_LP_SUSDE_SEP_25_EXPIRY,
18+
start_block=SILO_FINANCE_INTEGRATION_ID_TO_START_BLOCK[
19+
IntID.SILO_FINANCE_LP_SUSDE_SEP_25_EXPIRY
20+
],
21+
chain=Chain.ETHEREUM,
22+
summary_cols=[SummaryColumn.SILO_FINANCE_LP_SUSDE_SEP_25_EXPIRY_PTS],
23+
reward_multiplier=30,
24+
balance_multiplier=1,
25+
)
26+
27+
# Without cached data
28+
without_cached_data_output = integration.get_block_balances(
29+
cached_data={}, blocks=[22693183, 22755000]
30+
)
31+
console.print("Run without cached data", without_cached_data_output)
32+
# Check that the output is correct~ish
33+
assert without_cached_data_output[22755000] == {
34+
"0x62a4A8f9f5F3AaE9Ee9CEE780285A0D501C12d09": 18.194513,
35+
"0xeb80e76443c1bFa85dF46075f52a43ae1572003a": 30578.64522,
36+
}
37+
38+
# Use cache data to get the next blocks
39+
with_cached_data_output = integration.get_block_balances(
40+
cached_data=without_cached_data_output,
41+
blocks=[22814115],
42+
)
43+
console.print("Run with cached data", with_cached_data_output)
44+
assert with_cached_data_output[22814115] == {
45+
"0x62a4A8f9f5F3AaE9Ee9CEE780285A0D501C12d09": 18.194513,
46+
"0xeb80e76443c1bFa85dF46075f52a43ae1572003a": 30578.64522,
47+
"0x432FD970d8867b56e7197290BCd03C92A325AB7b": 620.451445,
48+
"0xdD84Ce1aDcb3A4908Db61A1dFA3353C3974c5a2B": 145426.301041,
49+
"0x8467241838Bc761D9Ef4F8ae6790Ede292fbA2F9": 1e-6,
50+
"0x23ce39C9AB29D00fCa9B83a50F64A67837c757C5": 4759.421793,
51+
}

utils/silo_finance.py

Lines changed: 60 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ class SiloFinance(CachedBalancesIntegration):
2626
def get_market(self) -> SiloFinanceMarket:
2727
return SILO_FINANCE_INTEGRATION_ID_TO_MARKET[self.integration_id]
2828

29+
def get_silo_contract(self) -> Contract:
30+
market = self.get_market()
31+
return get_silo_contract(chain=self.chain, market=market)
32+
2933
def get_logger(self) -> logging.Logger:
3034
logger = logging.getLogger(self.integration_id.get_column_name())
3135
logger.setLevel(logging.INFO)
@@ -36,7 +40,7 @@ def get_block_balances(
3640
) -> Dict[int, Dict[ChecksumAddress, float]]:
3741
logger = self.get_logger()
3842
market = self.get_market()
39-
logger.warning(f"Getting block data for Silo Finance {market.address}")
43+
logger.info(f"Getting block data for Silo Finance {market.address}")
4044
new_block_data: Dict[int, Dict[ChecksumAddress, float]] = {}
4145
if not blocks:
4246
logging.error(
@@ -56,29 +60,28 @@ def get_block_balances(
5660
f"Found closest cached data for block {block}: {prev_block}"
5761
)
5862
start = prev_block + 1
63+
supply_index = self.fetch_supply_index(block)
64+
logger.info(f"Supply index on block {block}: {supply_index}")
5965
while start <= block:
6066
to_block = min(start + PAGINATION_SIZE, block)
6167
logger.info(
6268
f"fetching transfers for market {market.address} from block {start} to block {to_block}"
6369
)
70+
# Transfers are used to keep track of the user positions.
6471
for transfer in self.fetch_transfers(
6572
market=market, from_block=start, to_block=to_block
6673
):
67-
self.process_transfer_event(transfer=transfer, bals=bals)
74+
self.process_transfer_event(
75+
transfer=transfer, bals=bals, supply_index=supply_index
76+
)
6877
start = to_block + 1
69-
logger.info(
78+
logger.warning(
7079
f"processed transfers for market {market.address} from block {start} to block {to_block}"
7180
)
7281
new_block_data[block] = bals
7382
cache_copy[block] = bals
7483
return new_block_data
7584

76-
"""
77-
Find the closest cached data for a given block.
78-
Returns the block number and the cached data for that block. Create a new instance of the cached data to allow mutations.
79-
If no cached data is found, returns None.
80-
"""
81-
8285
def find_closest_cached_data(
8386
self, block: int, cached_data: Dict[int, Dict[ChecksumAddress, float]]
8487
) -> Optional[Tuple[int, Dict[ChecksumAddress, float]]]:
@@ -91,6 +94,20 @@ def find_closest_cached_data(
9194
return (existing_block, deepcopy(cached_data[existing_block]))
9295
return None
9396

97+
def fetch_supply_index(self, block: int) -> float:
98+
"""
99+
Supply index is the number of assets that 1 share is worth. It's used to convert between shares and assets.
100+
1 shares = 1 * supply_index (assets)
101+
"""
102+
market = self.get_market()
103+
silo_contract = self.get_silo_contract()
104+
return (
105+
silo_contract.functions.convertToAssets(10**market.shares_decimals).call(
106+
block_identifier=block
107+
)
108+
/ 10**market.shares_decimals
109+
)
110+
94111
def fetch_transfers(
95112
self, *, market: SiloFinanceMarket, from_block: int, to_block: int
96113
):
@@ -115,21 +132,43 @@ def fetch_transfers(
115132
)
116133

117134
def process_transfer_event(
118-
self, *, transfer: Dict, bals: Dict[ChecksumAddress, float]
135+
self,
136+
*,
137+
transfer: Dict,
138+
bals: Dict[ChecksumAddress, float],
139+
supply_index: float,
119140
):
120141
sender = transfer["args"]["from"]
121142
receiver = transfer["args"]["to"]
122143
value = transfer["args"]["value"]
123144
if is_null_address(sender):
124145
# Minting
125-
add_to_bals(bals=bals, address=receiver, value=value, decimals=18)
146+
add_to_bals(
147+
bals=bals,
148+
address=receiver,
149+
value=value * supply_index,
150+
decimals=18,
151+
)
126152
elif is_null_address(receiver):
127153
# Burning
128-
subtract_from_bals(bals=bals, address=sender, value=value, decimals=18)
154+
subtract_from_bals(
155+
bals=bals, address=sender, value=value * supply_index, decimals=18
156+
)
129157
else:
130158
# Transfer
131-
add_to_bals(bals=bals, address=sender, value=value, decimals=18)
132-
subtract_from_bals(bals=bals, address=receiver, value=value, decimals=18)
159+
# Convert to assets
160+
add_to_bals(
161+
bals=bals,
162+
address=sender,
163+
value=value * supply_index,
164+
decimals=18,
165+
)
166+
subtract_from_bals(
167+
bals=bals, address=receiver, value=value * supply_index, decimals=18
168+
)
169+
170+
171+
ROUND_DECIMALS = 6
133172

134173

135174
def is_null_address(address: ChecksumAddress) -> bool:
@@ -144,7 +183,8 @@ def add_to_bals(
144183
):
145184
if address not in bals:
146185
bals[address] = 0
147-
bals[address] += round(value / 10**decimals, 6)
186+
bals[address] += round(value / 10**decimals, ROUND_DECIMALS)
187+
bals[address] = round(bals[address], ROUND_DECIMALS)
148188

149189

150190
def subtract_from_bals(
@@ -155,9 +195,11 @@ def subtract_from_bals(
155195
):
156196
if address not in bals:
157197
bals[address] = 0
158-
bals[address] -= round(value / 10**decimals, 6)
159-
# if bals[address] < 0:
160-
# bals[address] = 0
198+
bals[address] -= round(value / 10**decimals, ROUND_DECIMALS)
199+
# If the balance is negative, set it to 0. happens because of rounding errors.
200+
if bals[address] < 0:
201+
bals[address] = 0
202+
bals[address] = round(bals[address], ROUND_DECIMALS)
161203

162204

163205
def get_silo_contract(chain: Chain, market: SiloFinanceMarket) -> Contract:

0 commit comments

Comments
 (0)