@@ -203,7 +203,7 @@ impl PoolRewardManager {
203203
204204 let start_time_secs = start_time_secs. max ( clock. unix_timestamp as u64 ) ;
205205
206- if start_time_secs < = end_time_secs {
206+ if start_time_secs > = end_time_secs {
207207 msg ! ( "Pool reward must end after it starts" ) ;
208208 return Err ( LendingError :: MathOverflow . into ( ) ) ;
209209 }
@@ -420,24 +420,7 @@ impl UserRewardManagers {
420420 self . 0 . last_mut ( ) . unwrap ( )
421421 } ;
422422
423- msg ! (
424- "For reserve {} there are {} total shares. \
425- User's previous position was at {} and new is at {}",
426- reserve,
427- pool_reward_manager. total_shares,
428- user_reward_manager. share,
429- new_share
430- ) ;
431-
432- // This works even for migrations.
433- // User's old share is 0 although it shouldn't be bcs they have borrowed
434- // or deposited.
435- // We only now attribute the share to the user which is fine, it's as if
436- // they just now borrowed/deposited.
437- pool_reward_manager. total_shares =
438- pool_reward_manager. total_shares - user_reward_manager. share + new_share;
439-
440- user_reward_manager. share = new_share;
423+ user_reward_manager. set_share ( pool_reward_manager, new_share) ;
441424
442425 Ok ( ( ) )
443426 }
@@ -455,17 +438,42 @@ impl UserRewardManager {
455438 }
456439 }
457440
441+ /// Sets new share value for this manager.
442+ fn set_share ( & mut self , pool_reward_manager : & mut PoolRewardManager , new_share : u64 ) {
443+ msg ! (
444+ "For reserve {} there are {} total shares. \
445+ User's previous position was at {} and new is at {}",
446+ self . reserve,
447+ pool_reward_manager. total_shares,
448+ self . share,
449+ new_share
450+ ) ;
451+
452+ // This works even for migrations.
453+ // User's old share is 0 although it shouldn't be bcs they have borrowed
454+ // or deposited.
455+ // We only now attribute the share to the user which is fine, it's as if
456+ // they just now borrowed/deposited.
457+ pool_reward_manager. total_shares =
458+ pool_reward_manager. total_shares - self . share + new_share;
459+
460+ self . share = new_share;
461+ }
462+
458463 /// Claims all rewards that the user has earned.
459464 /// Returns how many tokens should be transferred to the user.
460465 ///
461466 /// # Note
467+ ///
462468 /// Errors if there is no pool reward with this vault.
463469 pub fn claim_rewards (
464470 & mut self ,
465471 pool_reward_manager : & mut PoolRewardManager ,
466472 vault : Pubkey ,
467473 clock : & Clock ,
468474 ) -> Result < u64 , ProgramError > {
475+ self . update ( pool_reward_manager, clock) ?;
476+
469477 let ( pool_reward_index, pool_reward) = pool_reward_manager
470478 . pool_rewards
471479 . iter ( )
@@ -1024,9 +1032,12 @@ mod tests {
10241032 //! TODO: Calculate test coverage and add tests for missing branches.
10251033
10261034 use super :: * ;
1035+ use pretty_assertions:: assert_eq;
10271036 use proptest:: prelude:: * ;
10281037 use rand:: Rng ;
10291038
1039+ const MILLISECONDS_IN_DAY : u64 = 86_400_000 ;
1040+
10301041 fn pool_reward_manager_strategy ( ) -> impl Strategy < Value = PoolRewardManager > {
10311042 ( 0 ..1u32 ) . prop_perturb ( |_, mut rng| PoolRewardManager :: new_rand ( & mut rng) )
10321043 }
@@ -1109,9 +1120,110 @@ mod tests {
11091120 assert ! ( required_realloc <= MAX_REALLOC ) ;
11101121 }
11111122
1123+ /// This tests replicates calculations from Suilend's
1124+ /// "test_pool_reward_manager_basic" test.
11121125 #[ test]
11131126 fn it_tests_pool_reward_manager_basic ( ) {
1114- // TODO: rewrite Suilend "test_pool_reward_manager_basic" test
1127+ let usdc = Pubkey :: new_unique ( ) ; // reserve pubkey
1128+ let slnd_vault = Pubkey :: new_unique ( ) ; // where rewards are stored
1129+
1130+ let mut clock = Clock {
1131+ unix_timestamp : 0 ,
1132+ ..Default :: default ( )
1133+ } ;
1134+
1135+ let mut pool_reward_manager = PoolRewardManager :: default ( ) ;
1136+ {
1137+ // setup pool reward manager with one reward
1138+
1139+ pool_reward_manager
1140+ . add_pool_reward (
1141+ slnd_vault,
1142+ 0 ,
1143+ 20 * MILLISECONDS_IN_DAY ,
1144+ 100 * 1_000_000 ,
1145+ & clock,
1146+ )
1147+ . expect ( "It adds pool reward" ) ;
1148+ assert_eq ! (
1149+ pool_reward_manager. pool_rewards[ 0 ] ,
1150+ PoolRewardSlot :: Occupied ( Box :: new( PoolReward {
1151+ id: PoolRewardId ( 1 ) ,
1152+ vault: slnd_vault,
1153+ start_time_secs: 0 ,
1154+ duration_secs: 20 * MILLISECONDS_IN_DAY as u32 ,
1155+ total_rewards: 100 * 1_000_000 ,
1156+ cumulative_rewards_per_share: Decimal :: zero( ) ,
1157+ num_user_reward_managers: 0 ,
1158+ } ) )
1159+ ) ;
1160+ }
1161+
1162+ let mut user_reward_manager_1 = UserRewardManager :: new ( usdc, PositionKind :: Deposit , & clock) ;
1163+ {
1164+ // setup user reward manager with 100/100 shares
1165+
1166+ user_reward_manager_1
1167+ . populate ( & mut pool_reward_manager, & clock)
1168+ . expect ( "It populates user reward manager" ) ;
1169+ user_reward_manager_1. set_share ( & mut pool_reward_manager, 100 ) ;
1170+ }
1171+
1172+ {
1173+ // 1/4 of the reward time passes
1174+ clock. unix_timestamp = 5 * MILLISECONDS_IN_DAY as i64 ;
1175+
1176+ let claimed_slnd = user_reward_manager_1
1177+ . claim_rewards ( & mut pool_reward_manager, slnd_vault, & clock)
1178+ . expect ( "It claims rewards" ) ;
1179+ assert_eq ! ( claimed_slnd, 25 * 1_000_000 ) ;
1180+ }
1181+
1182+ let mut user_reward_manager_2 = UserRewardManager :: new ( usdc, PositionKind :: Deposit , & clock) ;
1183+ {
1184+ // setup user reward manager with 400/500 shares
1185+
1186+ user_reward_manager_2
1187+ . populate ( & mut pool_reward_manager, & clock)
1188+ . expect ( "It populates user reward manager" ) ;
1189+ user_reward_manager_2. set_share ( & mut pool_reward_manager, 400 ) ;
1190+ }
1191+
1192+ {
1193+ // 1/2 of the reward time passes
1194+ clock. unix_timestamp = 10 * MILLISECONDS_IN_DAY as i64 ;
1195+
1196+ let claimed_slnd = user_reward_manager_1
1197+ . claim_rewards ( & mut pool_reward_manager, slnd_vault, & clock)
1198+ . expect ( "It claims rewards" ) ;
1199+ assert_eq ! ( claimed_slnd, 5 * 1_000_000 ) ;
1200+
1201+ let claimed_slnd = user_reward_manager_2
1202+ . claim_rewards ( & mut pool_reward_manager, slnd_vault, & clock)
1203+ . expect ( "It claims rewards" ) ;
1204+ assert_eq ! ( claimed_slnd, 20 * 1_000_000 ) ;
1205+ }
1206+
1207+ {
1208+ // set both user reward managers to 250/500 shares
1209+ user_reward_manager_1. set_share ( & mut pool_reward_manager, 250 ) ;
1210+ user_reward_manager_2. set_share ( & mut pool_reward_manager, 250 ) ;
1211+ }
1212+
1213+ {
1214+ // the reward is finished
1215+ clock. unix_timestamp = 20 * MILLISECONDS_IN_DAY as i64 ;
1216+
1217+ let claimed_slnd = user_reward_manager_1
1218+ . claim_rewards ( & mut pool_reward_manager, slnd_vault, & clock)
1219+ . expect ( "It claims rewards" ) ;
1220+ assert_eq ! ( claimed_slnd, 25 * 1_000_000 ) ;
1221+
1222+ let claimed_slnd = user_reward_manager_2
1223+ . claim_rewards ( & mut pool_reward_manager, slnd_vault, & clock)
1224+ . expect ( "It claims rewards" ) ;
1225+ assert_eq ! ( claimed_slnd, 25 * 1_000_000 ) ;
1226+ }
11151227 }
11161228
11171229 #[ test]
0 commit comments