@@ -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
135174def 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
150190def 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
163205def get_silo_contract (chain : Chain , market : SiloFinanceMarket ) -> Contract :
0 commit comments