@@ -53,26 +53,26 @@ fn it_sets_rewards_allowance_with_genesis_defaults_automatically_in_on_finalize_
5353// same timestamp for all the blocks and tests below.
5454fn it_distributes_rewards_automatically_in_on_finalize_for_default_amount ( ) {
5555 new_test_ext ( ) . execute_with ( || {
56- setup_bonding ( NORMAL_AMOUNT , TEN_DHX ) ;
56+ let r = setup_bonding ( NORMAL_AMOUNT , TEN_DHX ) ;
5757
5858 setup_treasury_balance ( ) ;
5959
6060 setup_multiplier ( ) ;
6161
62- distribute_rewards ( NORMAL_AMOUNT ) ;
62+ distribute_rewards ( NORMAL_AMOUNT , r ) ;
6363 } )
6464}
6565
6666#[ test]
6767fn it_distributes_rewards_automatically_in_on_finalize_for_large_amount ( ) {
6868 new_test_ext ( ) . execute_with ( || {
69- setup_bonding ( LARGE_AMOUNT_DHX , TEN_DHX ) ;
69+ let r = setup_bonding ( LARGE_AMOUNT_DHX , TEN_DHX ) ;
7070
7171 setup_treasury_balance ( ) ;
7272
7373 setup_multiplier ( ) ;
7474
75- distribute_rewards ( LARGE_AMOUNT_DHX ) ;
75+ distribute_rewards ( LARGE_AMOUNT_DHX , r ) ;
7676 } )
7777}
7878
@@ -282,7 +282,7 @@ fn it_allows_us_to_retrieve_genesis_value_for_min_mpower_daily() {
282282 } ) ;
283283}
284284
285- fn distribute_rewards ( amount_bonded_each_miner : u128 ) {
285+ fn distribute_rewards ( amount_bonded_each_miner : u128 , referendum_index : u32 ) {
286286 assert_ok ! ( MiningRewardsAllowanceTestModule :: set_registered_dhx_miner( Origin :: signed( 1 ) ) ) ;
287287 assert_ok ! ( MiningRewardsAllowanceTestModule :: set_registered_dhx_miner( Origin :: signed( 2 ) ) ) ;
288288 assert_ok ! ( MiningRewardsAllowanceTestModule :: set_registered_dhx_miner( Origin :: signed( 3 ) ) ) ;
@@ -300,6 +300,93 @@ fn distribute_rewards(amount_bonded_each_miner: u128) {
300300 assert_eq ! ( MiningRewardsAllowanceTestModule :: cooling_off_period_days( ) , Some ( 1 ) ) ;
301301 assert_eq ! ( MiningRewardsAllowanceTestModule :: rewards_allowance_dhx_daily( ) , Some ( FIVE_THOUSAND_DHX ) ) ;
302302
303+ check_eligible_for_rewards_after_cooling_off_period_if_suffient_bonded ( amount_bonded_each_miner. clone ( ) ) ;
304+
305+ // check that rewards multiplier increases by multiplier every period days and that days total and remaining are reset
306+ check_rewards_double_each_multiplier_period ( ) ;
307+
308+ // check that after the multiplier doubles, they are no longer eligible to receive the rewards
309+ // if they have the same amount bonded (since they’d then need twice the amount bonded as ratio changes from 10:1 to 20:1),
310+ // even if they have sufficient mpower
311+ check_ineligible_for_rewards_and_cooling_down_period_starts_if_insufficient_bonded ( amount_bonded_each_miner. clone ( ) , referendum_index. clone ( ) ) ;
312+ }
313+
314+ fn setup_bonding ( amount_bonded_each_miner : u128 , min_bonding_dhx_daily : u128 ) -> u32 {
315+ assert_ok ! ( MiningRewardsAllowanceTestModule :: set_min_bonded_dhx_daily(
316+ Origin :: signed( 1 ) ,
317+ min_bonding_dhx_daily. clone( ) ,
318+ ) ) ;
319+ assert_eq ! ( MiningRewardsAllowanceTestModule :: min_bonded_dhx_daily( ) , Some ( min_bonding_dhx_daily. clone( ) ) ) ;
320+
321+ // create a test that instead of using a hard-coded value for `locks_first_amount_as_u128`
322+ // that is in the implementation, it instead sets the locked value of each of them using frame_balances
323+ // for the 3x miners, since we can then store that with `set_bonded_dhx_of_account_for_date` and
324+ // then use that easier for the tests too for trying different values that they have bonded.
325+ //
326+ // in this test we'll test that it distributes rewards when each of their account balances are very large
327+ // (i.e. a third of the total supply) ONE_THIRD_OF_TOTAL_SUPPLY_DHX
328+
329+ assert_ok ! ( Balances :: set_balance( Origin :: root( ) , 1 , amount_bonded_each_miner, 0 ) ) ;
330+ assert_ok ! ( Balances :: set_balance( Origin :: root( ) , 2 , amount_bonded_each_miner, 0 ) ) ;
331+ assert_ok ! ( Balances :: set_balance( Origin :: root( ) , 3 , amount_bonded_each_miner, 0 ) ) ;
332+
333+ assert_eq ! ( Balances :: free_balance( & 1 ) , amount_bonded_each_miner) ;
334+ assert_eq ! ( Balances :: free_balance( & 2 ) , amount_bonded_each_miner) ;
335+ assert_eq ! ( Balances :: free_balance( & 3 ) , amount_bonded_each_miner) ;
336+
337+ assert_eq ! ( Balances :: reserved_balance( & 1 ) , 0 ) ;
338+
339+ let pre_image_hash = BlakeTwo256 :: hash ( b"test" ) ;
340+ // params: end block, proposal hash, threshold, delay
341+ let r = Democracy :: inject_referendum ( 1 , pre_image_hash. clone ( ) , VoteThreshold :: SuperMajorityApprove , 2 ) ;
342+ // lock the whole balance of account 1, 2, and 3 in voting
343+ let v1a1 = AccountVote :: Standard { vote : AYE , balance : Balances :: free_balance ( 1 ) } ;
344+ let v1a2 = AccountVote :: Standard { vote : AYE , balance : Balances :: free_balance ( 2 ) } ;
345+ let v1a3 = AccountVote :: Standard { vote : AYE , balance : Balances :: free_balance ( 3 ) } ;
346+ // vote on referenda using time-lock voting with a conviction to scale the vote power
347+ // note: second parameter is the referendum index being voted on
348+ assert_ok ! ( Democracy :: vote( Origin :: signed( 1 ) , r, v1a1) ) ;
349+ assert_ok ! ( Democracy :: vote( Origin :: signed( 2 ) , r, v1a2) ) ;
350+ assert_ok ! ( Democracy :: vote( Origin :: signed( 3 ) , r, v1a3) ) ;
351+
352+ // // assert_eq!(tally(r), Tally { ayes: 0, nays: 0, turnout: 0 });
353+ assert_eq ! ( Balances :: locks( 1 ) [ 0 ] ,
354+ BalanceLock {
355+ id: [ 100 , 101 , 109 , 111 , 99 , 114 , 97 , 99 ] ,
356+ amount: amount_bonded_each_miner,
357+ reasons: Reasons :: Misc
358+ }
359+ ) ;
360+
361+ return r;
362+ }
363+
364+ fn setup_multiplier ( ) {
365+ assert_ok ! ( MiningRewardsAllowanceTestModule :: set_rewards_multiplier_operation(
366+ Origin :: signed( 0 ) ,
367+ 1u8 ,
368+ ) ) ;
369+
370+ // in the tests we want the period between each 10:1, 20:1 cycle to be just 2 days instead of 90 days
371+ // since we don't want to wait so long to check that it changes each cycle in the tests
372+ assert_ok ! ( MiningRewardsAllowanceTestModule :: set_rewards_multiplier_default_period_days(
373+ Origin :: signed( 0 ) ,
374+ 2u32 ,
375+ ) ) ;
376+
377+ assert_ok ! ( MiningRewardsAllowanceTestModule :: set_rewards_multiplier_next_period_days(
378+ Origin :: signed( 0 ) ,
379+ 2u32 ,
380+ ) ) ;
381+ }
382+
383+ fn setup_treasury_balance ( ) {
384+ // set the balance of the treasury so it distributes rewards
385+ Balances :: set_balance ( Origin :: root ( ) , Treasury :: account_id ( ) , INIT_DAO_BALANCE_DHX , 0 ) ;
386+ assert_eq ! ( Balances :: usable_balance( & Treasury :: account_id( ) ) , INIT_DAO_BALANCE_DHX ) ;
387+ }
388+
389+ fn check_eligible_for_rewards_after_cooling_off_period_if_suffient_bonded ( amount_bonded_each_miner : u128 ) {
303390 // since the timestamp is 0 (corresponds to 1970-01-01) at block number #1, we early exit from on_initialize in
304391 // that block in the implementation and do not set any storage values associated with the date until block #2.
305392 // in the tests we could set the timestamp before we run on_initialize(1), but that wouldn't reflect reality.
@@ -339,6 +426,8 @@ fn distribute_rewards(amount_bonded_each_miner: u128) {
339426 // 29th August 2021 @ 12am is 1630195200000 (start of day)
340427 Timestamp :: set_timestamp ( 1630195200000u64 ) ;
341428 MiningRewardsAllowanceTestModule :: on_initialize ( 4 ) ;
429+ // a day before we start the new multiplier period and change from 10:1 to 20:1 since no more days remaining
430+ assert_eq ! ( MiningRewardsAllowanceTestModule :: rewards_multiplier_current_period_days_remaining( ) , Some ( ( 1630022400000 , 1630195200000 , 2u32 , 0u32 ) ) ) ;
342431
343432 assert_eq ! ( MiningRewardsAllowanceTestModule :: bonded_dhx_of_account_for_date( ( 1630195200000 , 1 ) ) , Some ( amount_bonded_each_miner) ) ;
344433 assert_eq ! ( MiningRewardsAllowanceTestModule :: bonded_dhx_of_account_for_date( ( 1630195200000 , 2 ) ) , Some ( amount_bonded_each_miner) ) ;
@@ -397,85 +486,6 @@ fn distribute_rewards(amount_bonded_each_miner: u128) {
397486 // Update: difficult to add a test to check they are reset before next day, just check it works using the logs.
398487 // assert_eq!(MiningRewardsAllowanceTestModule::rewards_aggregated_dhx_for_all_miners_for_date(1630281600000), Some(0u128));
399488 // assert_eq!(MiningRewardsAllowanceTestModule::rewards_accumulated_dhx_for_miner_for_date((1630281600000, 1)), Some(0u128));
400-
401- check_rewards_double_each_multiplier_period ( ) ;
402- }
403-
404- fn setup_bonding ( amount_bonded_each_miner : u128 , min_bonding_dhx_daily : u128 ) {
405- assert_ok ! ( MiningRewardsAllowanceTestModule :: set_min_bonded_dhx_daily(
406- Origin :: signed( 1 ) ,
407- min_bonding_dhx_daily. clone( ) ,
408- ) ) ;
409- assert_eq ! ( MiningRewardsAllowanceTestModule :: min_bonded_dhx_daily( ) , Some ( min_bonding_dhx_daily. clone( ) ) ) ;
410-
411- // create a test that instead of using a hard-coded value for `locks_first_amount_as_u128`
412- // that is in the implementation, it instead sets the locked value of each of them using frame_balances
413- // for the 3x miners, since we can then store that with `set_bonded_dhx_of_account_for_date` and
414- // then use that easier for the tests too for trying different values that they have bonded.
415- //
416- // in this test we'll test that it distributes rewards when each of their account balances are very large
417- // (i.e. a third of the total supply) ONE_THIRD_OF_TOTAL_SUPPLY_DHX
418-
419- assert_ok ! ( Balances :: set_balance( Origin :: root( ) , 1 , amount_bonded_each_miner, 0 ) ) ;
420- assert_ok ! ( Balances :: set_balance( Origin :: root( ) , 2 , amount_bonded_each_miner, 0 ) ) ;
421- assert_ok ! ( Balances :: set_balance( Origin :: root( ) , 3 , amount_bonded_each_miner, 0 ) ) ;
422-
423- assert_eq ! ( Balances :: free_balance( & 1 ) , amount_bonded_each_miner) ;
424- assert_eq ! ( Balances :: free_balance( & 2 ) , amount_bonded_each_miner) ;
425- assert_eq ! ( Balances :: free_balance( & 3 ) , amount_bonded_each_miner) ;
426-
427- assert_eq ! ( Balances :: reserved_balance( & 1 ) , 0 ) ;
428-
429- let pre_image_hash = BlakeTwo256 :: hash ( b"test" ) ;
430- let r = Democracy :: inject_referendum ( 1 , pre_image_hash. clone ( ) , VoteThreshold :: SuperMajorityApprove , 2 ) ;
431- // lock the whole balance of account 1, 2, and 3 in voting
432- let v1a1 = AccountVote :: Standard { vote : AYE , balance : Balances :: free_balance ( 1 ) } ;
433- let v1a2 = AccountVote :: Standard { vote : AYE , balance : Balances :: free_balance ( 2 ) } ;
434- let v1a3 = AccountVote :: Standard { vote : AYE , balance : Balances :: free_balance ( 3 ) } ;
435- // vote on referenda using time-lock voting with a conviction to scale the vote power
436- // note: second parameter is the referendum index being voted on
437- assert_ok ! ( Democracy :: vote( Origin :: signed( 1 ) , r, v1a1) ) ;
438- assert_ok ! ( Democracy :: vote( Origin :: signed( 2 ) , r, v1a2) ) ;
439- assert_ok ! ( Democracy :: vote( Origin :: signed( 3 ) , r, v1a3) ) ;
440- // let v2 = AccountVote::Split { aye: 1, nay: 2 };
441- // assert_ok!(Democracy::vote(Origin::signed(1), r, v2));
442-
443- // TODO - use this later to simulate that unbonding works
444- // // assert_ok!(Democracy::remove_vote(Origin::signed(1), r));
445- // // assert_eq!(tally(r), Tally { ayes: 0, nays: 0, turnout: 0 });
446- // // assert_ok!(Democracy::unlock(Origin::signed(1), 5));
447- assert_eq ! ( Balances :: locks( 1 ) [ 0 ] ,
448- BalanceLock {
449- id: [ 100 , 101 , 109 , 111 , 99 , 114 , 97 , 99 ] ,
450- amount: amount_bonded_each_miner,
451- reasons: Reasons :: Misc
452- }
453- ) ;
454- }
455-
456- fn setup_multiplier ( ) {
457- assert_ok ! ( MiningRewardsAllowanceTestModule :: set_rewards_multiplier_operation(
458- Origin :: signed( 0 ) ,
459- 1u8 ,
460- ) ) ;
461-
462- // in the tests we want the period between each 10:1, 20:1 cycle to be just 2 days instead of 90 days
463- // since we don't want to wait so long to check that it changes each cycle in the tests
464- assert_ok ! ( MiningRewardsAllowanceTestModule :: set_rewards_multiplier_default_period_days(
465- Origin :: signed( 0 ) ,
466- 2u32 ,
467- ) ) ;
468-
469- assert_ok ! ( MiningRewardsAllowanceTestModule :: set_rewards_multiplier_next_period_days(
470- Origin :: signed( 0 ) ,
471- 2u32 ,
472- ) ) ;
473- }
474-
475- fn setup_treasury_balance ( ) {
476- // set the balance of the treasury so it distributes rewards
477- Balances :: set_balance ( Origin :: root ( ) , Treasury :: account_id ( ) , INIT_DAO_BALANCE_DHX , 0 ) ;
478- assert_eq ! ( Balances :: usable_balance( & Treasury :: account_id( ) ) , INIT_DAO_BALANCE_DHX ) ;
479489}
480490
481491fn check_rewards_double_each_multiplier_period ( ) {
@@ -506,3 +516,69 @@ fn check_rewards_double_each_multiplier_period() {
506516 // check that the min_bonded_dhx_daily doubled after 3 months (we're only doing it after 2 days in the tests though) from 20 DHX to 30 DHX
507517 assert_eq ! ( MiningRewardsAllowanceTestModule :: min_bonded_dhx_daily( ) , Some ( THIRTY_DHX ) ) ;
508518}
519+
520+ fn check_ineligible_for_rewards_and_cooling_down_period_starts_if_insufficient_bonded ( amount_bonded_each_miner : u128 , referendum_index : u32 ) {
521+ // 3rd Sept 2021 @ ~7am is 1630652400000
522+ // 3rd Sept 2021 @ 12am is 1630627200000 (start of day)
523+ Timestamp :: set_timestamp ( 1630652400000u64 ) ;
524+ MiningRewardsAllowanceTestModule :: on_initialize ( 8 ) ;
525+
526+ // the below works to unbond each of the accounts
527+
528+ // check that the referendum that we created earlier still exists
529+ assert_eq ! ( Democracy :: referendum_count( ) , 1 , "referenda not created" ) ;
530+
531+ // remove the votes and then unlock for each account
532+ // note: `remove_vote` must be done before `unlock`
533+ assert_ok ! ( Democracy :: remove_vote( Origin :: signed( 1 ) , referendum_index) ) ;
534+ assert_ok ! ( Democracy :: remove_vote( Origin :: signed( 2 ) , referendum_index) ) ;
535+ assert_ok ! ( Democracy :: remove_vote( Origin :: signed( 3 ) , referendum_index) ) ;
536+ // we removed their votes
537+ assert_eq ! ( Democracy :: referendum_status( referendum_index) . unwrap( ) . tally, Tally { ayes: 0 , nays: 0 , turnout: 0 } ) ;
538+ assert_ok ! ( Democracy :: unlock( Origin :: signed( 1 ) , 1 ) ) ;
539+ assert_ok ! ( Democracy :: unlock( Origin :: signed( 2 ) , 2 ) ) ;
540+ assert_ok ! ( Democracy :: unlock( Origin :: signed( 3 ) , 3 ) ) ;
541+
542+ // check that all accounts are unlocked
543+ assert_eq ! ( Balances :: locks( 1 ) , vec![ ] ) ;
544+ assert_eq ! ( Balances :: locks( 2 ) , vec![ ] ) ;
545+ assert_eq ! ( Balances :: locks( 3 ) , vec![ ] ) ;
546+
547+ // now wait for the next day when we iterate through the miner accounts and they should have no locks
548+ // 4th Sept 2021 @ ~7am is 1630738800000
549+ // 4th Sept 2021 @ 12am is 1630713600000 (start of day)
550+ Timestamp :: set_timestamp ( 1630738800000u64 ) ;
551+ MiningRewardsAllowanceTestModule :: on_initialize ( 9 ) ;
552+
553+ // IMPORTANT NOTE: The min. DHX bonded has increased from 10 (10:1) to 20 (20:1) in order to be eligible
554+ // for rewards, however none of the miner's increased their bonded DHX amount proportionally to still remain
555+ // eligible for rewards, so since having insufficient bonded DHX is the same as unbonding, we expect the
556+ // cooling off period days remaining to change so they are now going through the unbonding cool down period,
557+ // (which we also count using `cooling_off_period_days_remaining`)
558+ // where they aren't eligble for rewards until they bond the new min. DHX so cooling off period starts and
559+ // then they'd be eligible for rewards after waiting that period, but also note that if they don't bond the new min.
560+ // DHX and wait until the end of the cool down period then they'll be able to withdraw the amount they had bonded.
561+ //
562+ // but in the tests the initial bonded amounts were much more than the min. DHX bonded, so even after it increases
563+ // from 10 (10:1) to 20 (20:1) they are still eligible for rewards.
564+ // so in the tests we've just decided to remove their vote and `unlock` their bonded DHX so they don't have a lock
565+ // and so don't satisfy the min. DHX bonded
566+
567+ // params: start of date, days remaining, bonding status
568+ // note: since they don't have the min. DHX bonded their bonding status changes to `2`, which is unbonding
569+ assert_eq ! ( MiningRewardsAllowanceTestModule :: cooling_off_period_days_remaining( 1 ) , Some ( ( 1630713600000 , 1 , 2 ) ) ) ;
570+
571+ assert_eq ! ( MiningRewardsAllowanceTestModule :: bonded_dhx_of_account_for_date( ( 1630713600000 , 1 ) ) , Some ( 0u128 ) ) ;
572+ assert_eq ! ( MiningRewardsAllowanceTestModule :: bonded_dhx_of_account_for_date( ( 1630713600000 , 2 ) ) , Some ( 0u128 ) ) ;
573+ assert_eq ! ( MiningRewardsAllowanceTestModule :: bonded_dhx_of_account_for_date( ( 1630713600000 , 3 ) ) , Some ( 0u128 ) ) ;
574+
575+ // check they are not eligible for rewards due to insufficient bonded amount
576+ assert_eq ! ( MiningRewardsAllowanceTestModule :: rewards_aggregated_dhx_for_all_miners_for_date( 1630713600000 ) , None ) ;
577+
578+ assert_eq ! ( MiningRewardsAllowanceTestModule :: rewards_accumulated_dhx_for_miner_for_date( ( 1630713600000 , 1 ) ) , None ) ;
579+ assert_eq ! ( MiningRewardsAllowanceTestModule :: rewards_accumulated_dhx_for_miner_for_date( ( 1630713600000 , 2 ) ) , None ) ;
580+ assert_eq ! ( MiningRewardsAllowanceTestModule :: rewards_accumulated_dhx_for_miner_for_date( ( 1630713600000 , 3 ) ) , None ) ;
581+
582+ assert_eq ! ( MiningRewardsAllowanceTestModule :: rewards_allowance_dhx_for_date_remaining( 1630713600000 ) , Some ( FIVE_THOUSAND_DHX ) ) ;
583+ assert_eq ! ( MiningRewardsAllowanceTestModule :: rewards_allowance_dhx_for_date_remaining_distributed( 1630713600000 ) , Some ( false ) ) ;
584+ }
0 commit comments