@@ -14,6 +14,7 @@ import {
14
14
LIDO_ETH_DESTRIBUTED_EVENT ,
15
15
LIDO_TOKEN_REBASED_EVENT ,
16
16
LIDO_WITHDRAWALS_RECEIVED_EVENT ,
17
+ ONE_WEEK_HOURS ,
17
18
} from './rewards.constants' ;
18
19
import { BigNumber } from '@ethersproject/bignumber' ;
19
20
import { LOGGER_PROVIDER , LoggerService } from '../../common/logger' ;
@@ -61,7 +62,7 @@ export class RewardsService {
61
62
}
62
63
63
64
protected async updateRewards ( ) : Promise < void > {
64
- const rewardsPerFrame = await this . getLastTotalRewardsPerFrame ( ) ;
65
+ const rewardsPerFrame = await this . getMinLastTotalRewardsPerFrame ( ) ;
65
66
66
67
if ( ! rewardsPerFrame ) {
67
68
return ;
@@ -72,15 +73,11 @@ export class RewardsService {
72
73
this . rewardsStorage . setElRewardsPerFrame ( rewardsPerFrame . elRewards ) ;
73
74
}
74
75
75
- public async getLastTotalRewardsPerFrame ( ) : Promise < {
76
- clRewards : BigNumber ;
77
- elRewards : BigNumber ;
78
- allRewards : BigNumber ;
79
- } | null > {
80
- const framesFromLastReport = await this . getFramesFromLastReport ( ) ;
81
- if ( framesFromLastReport === null ) {
76
+ public async getMinLastTotalRewardsPerFrame ( ) {
77
+ const framesFromLastReports = await this . getFramesFromLastReports ( ) ;
78
+ if ( framesFromLastReports === null ) {
82
79
this . logger . warn (
83
- 'last rewards was not updated because last TokenRebase events were not found during last 48 hours .' ,
80
+ 'last reward reports were not found because last TokenRebase events were not found during last week .' ,
84
81
{ service : RewardsService . SERVICE_LOG_NAME } ,
85
82
) ;
86
83
return {
@@ -90,41 +87,58 @@ export class RewardsService {
90
87
} ;
91
88
}
92
89
93
- const { blockNumber, frames } = framesFromLastReport ;
90
+ const rewards = await Promise . all (
91
+ framesFromLastReports . map ( async ( { blockNumber, frames } ) => {
92
+ const { clRewards, elRewards } = await this . getRewardsByBlockNumber ( blockNumber , frames ) ;
94
93
95
- if ( frames . eq ( 0 ) ) {
96
- this . logger . warn ( 'last rewards set to 0 because frames passed from last event is 0.' , {
97
- service : RewardsService . SERVICE_LOG_NAME ,
98
- } ) ;
99
- return {
100
- clRewards : BigNumber . from ( 0 ) ,
101
- elRewards : BigNumber . from ( 0 ) ,
102
- allRewards : BigNumber . from ( 0 ) ,
103
- } ;
104
- }
94
+ return {
95
+ clRewards,
96
+ elRewards,
97
+ } ;
98
+ } ) ,
99
+ ) ;
105
100
106
- const { preCLBalance, postCLBalance } = await this . getEthDistributed ( blockNumber ) ;
107
- const elRewards = ( await this . getElRewards ( blockNumber ) ) ?? BigNumber . from ( 0 ) ;
108
- const withdrawalsReceived = ( await this . getWithdrawalsReceived ( blockNumber ) ) ?? BigNumber . from ( 0 ) ;
101
+ let minCL = rewards [ 0 ] . clRewards ;
102
+ let minEL = rewards [ 0 ] . elRewards ;
109
103
110
- const clValidatorsBalanceDiff = postCLBalance . sub ( preCLBalance ) ;
111
- const clRewards = clValidatorsBalanceDiff . add ( withdrawalsReceived ) ;
104
+ // find minimum for last week
105
+ rewards . forEach ( ( r ) => {
106
+ if ( minCL . lt ( r . clRewards ) ) {
107
+ minCL = r . clRewards ;
108
+ }
109
+
110
+ if ( minEL . lt ( r . elRewards ) ) {
111
+ minEL = r . elRewards ;
112
+ }
113
+ } ) ;
114
+
115
+ const allRewards = minEL . add ( minCL ) ;
112
116
113
- const allRewards = clRewards . add ( elRewards ) . div ( frames ) ;
114
117
this . logger . log ( `rewardsPerFrame are updated to ${ allRewards . toString ( ) } ` , {
115
118
service : RewardsService . SERVICE_LOG_NAME ,
116
119
} ) ;
117
120
118
121
return {
119
- clRewards : clRewards . div ( frames ) ,
120
- elRewards : elRewards . div ( frames ) ,
122
+ clRewards : minCL ,
123
+ elRewards : minEL ,
121
124
allRewards,
122
125
} ;
123
126
}
124
127
125
- protected async get48HoursAgoBlock ( ) {
128
+ protected async getRewardsByBlockNumber ( blockNumber : number , framesPassed : BigNumber ) {
129
+ const { preCLBalance, postCLBalance } = await this . getEthDistributed ( blockNumber ) ;
130
+ const elRewards = ( await this . getElRewards ( blockNumber ) ) ?? BigNumber . from ( 0 ) ;
131
+ const withdrawalsReceived = ( await this . getWithdrawalsReceived ( blockNumber ) ) ?? BigNumber . from ( 0 ) ;
132
+
133
+ const clValidatorsBalanceDiff = postCLBalance . sub ( preCLBalance ) ;
134
+ const clRewards = clValidatorsBalanceDiff . add ( withdrawalsReceived ) ;
135
+
136
+ return { clRewards : clRewards . div ( framesPassed ) , elRewards : elRewards . div ( framesPassed ) } ;
137
+ }
138
+
139
+ protected async getHoursAgoBlock ( hours : number ) {
126
140
const currentBlock = await this . provider . getBlockNumber ( ) ;
127
- return currentBlock - Math . ceil ( ( 2 * 24 * 60 * 60 ) / SECONDS_PER_SLOT ) ;
141
+ return currentBlock - Math . ceil ( ( hours * 60 * 60 ) / SECONDS_PER_SLOT ) ;
128
142
}
129
143
130
144
protected async getElRewards ( fromBlock : number ) : Promise < BigNumber > {
@@ -135,7 +149,7 @@ export class RewardsService {
135
149
fromBlock,
136
150
address : res . address ,
137
151
} ) ;
138
- const lastLog = logs [ logs . length - 1 ] ;
152
+ const lastLog = logs [ 0 ] ;
139
153
140
154
if ( ! lastLog ) {
141
155
return BigNumber . from ( 0 ) ;
@@ -166,7 +180,7 @@ export class RewardsService {
166
180
167
181
this . logger . log ( 'ETHDistributed event logs' , { service : RewardsService . SERVICE_LOG_NAME , logsCount : logs . length } ) ;
168
182
169
- const lastLog = logs [ logs . length - 1 ] ;
183
+ const lastLog = logs [ 0 ] ;
170
184
171
185
if ( ! lastLog ) {
172
186
this . logger . warn ( 'ETHDistributed event is not found for CL balance.' , {
@@ -215,7 +229,7 @@ export class RewardsService {
215
229
logsCount : logs . length ,
216
230
} ) ;
217
231
218
- const lastLog = logs [ logs . length - 1 ] ;
232
+ const lastLog = logs [ 0 ] ;
219
233
if ( ! lastLog ) {
220
234
return BigNumber . from ( 0 ) ;
221
235
}
@@ -233,11 +247,8 @@ export class RewardsService {
233
247
}
234
248
235
249
// reports can be skipped, so we need timeElapsed (time from last report)
236
- protected async getFramesFromLastReport ( ) : Promise < {
237
- blockNumber : number ;
238
- frames : BigNumber ;
239
- } | null > {
240
- const last48HoursAgoBlock = await this . get48HoursAgoBlock ( ) ;
250
+ protected async getFramesFromLastReports ( ) {
251
+ const weekAgoBlock = await this . getHoursAgoBlock ( ONE_WEEK_HOURS ) ;
241
252
242
253
const res = this . contractLido . filters . TokenRebased ( ) ;
243
254
@@ -246,51 +257,55 @@ export class RewardsService {
246
257
{
247
258
topics : res . topics ,
248
259
toBlock : 'latest' ,
249
- fromBlock : last48HoursAgoBlock ,
260
+ fromBlock : weekAgoBlock ,
250
261
address : res . address ,
251
262
} ,
252
263
this . logger ,
253
264
'TokenRebased' ,
254
265
) ;
255
266
256
- this . logger . log ( 'TokenRebase event logs for last 48 hours ' , {
267
+ this . logger . log ( 'TokenRebase event logs for last week ' , {
257
268
service : RewardsService . SERVICE_LOG_NAME ,
258
269
logsCount : logs . length ,
259
270
} ) ;
260
271
261
272
if ( logs . length === 0 ) {
262
- this . logger . warn ( 'TokenRebase events are not found for last 48 hours .' , {
273
+ this . logger . warn ( 'TokenRebase events are not found for last week .' , {
263
274
service : RewardsService . SERVICE_LOG_NAME ,
264
275
} ) ;
265
276
266
277
return null ;
267
278
}
268
279
269
- const lastLog = logs [ logs . length - 1 ] ;
270
- const parser = new Interface ( [ LIDO_TOKEN_REBASED_EVENT ] ) ;
271
- const parsedData = parser . parseLog ( lastLog ) ;
280
+ const rewardsBlocks = logs . map ( ( log ) => {
281
+ const parser = new Interface ( [ LIDO_TOKEN_REBASED_EVENT ] ) ;
282
+ const parsedData = parser . parseLog ( log ) ;
272
283
273
- this . logger . log ( 'last TokenRebase event for last 48 hours' , {
284
+ return {
285
+ blockNumber : log . blockNumber ,
286
+ frames : BigNumber . from ( parsedData . args . getValue ( 'timeElapsed' ) ) . div (
287
+ SECONDS_PER_SLOT * SLOTS_PER_EPOCH * this . contractConfig . getEpochsPerFrame ( ) ,
288
+ ) ,
289
+ } ;
290
+ } ) ;
291
+
292
+ this . logger . log ( 'last TokenRebase events for last week' , {
274
293
service : RewardsService . SERVICE_LOG_NAME ,
275
- args : parsedData . args ,
276
- timeElapsed : parsedData . args . getValue ( 'timeElapsed' ) ,
277
- blockNumber : lastLog . blockNumber ,
294
+ rewardsBlocks,
278
295
} ) ;
279
296
280
- return {
281
- blockNumber : lastLog . blockNumber ,
282
- frames : BigNumber . from ( parsedData . args . getValue ( 'timeElapsed' ) ) . div (
283
- SECONDS_PER_SLOT * SLOTS_PER_EPOCH * this . contractConfig . getEpochsPerFrame ( ) ,
284
- ) ,
285
- } ;
297
+ return rewardsBlocks ;
286
298
}
287
299
288
300
// it includes WithdrawalVault balance and diff between rewards and cached rewards from previous report
289
- async getVaultsBalance ( ) {
301
+ async getVaultsBalance ( blockNumber : number ) {
290
302
const chainId = this . configService . get ( 'CHAIN_ID' ) ;
291
- const withdrawalVaultAddress = await this . lidoLocator . withdrawalVault ( ) ;
292
- const withdrawalVaultBalance = await this . provider . getBalance ( withdrawalVaultAddress ) ;
293
- const rewardsVaultBalance = await this . provider . getBalance ( EXECUTION_REWARDS_VAULT_CONTRACT_ADDRESSES [ chainId ] ) ;
303
+ const withdrawalVaultAddress = await this . lidoLocator . withdrawalVault ( { blockTag : blockNumber } ) ;
304
+ const withdrawalVaultBalance = await this . provider . getBalance ( withdrawalVaultAddress , blockNumber ) ;
305
+ const rewardsVaultBalance = await this . provider . getBalance (
306
+ EXECUTION_REWARDS_VAULT_CONTRACT_ADDRESSES [ chainId ] ,
307
+ blockNumber ,
308
+ ) ;
294
309
const elRewards = this . rewardsStorage . getElRewardsPerFrame ( ) ;
295
310
const clRewards = this . rewardsStorage . getClRewardsPerFrame ( ) ;
296
311
0 commit comments