Browse Source

Merge pull request #2347 from shamil-gadelshin/add_missing_events

Add missing events for working-group pallet.
shamil-gadelshin 3 years ago
parent
commit
f900972767

+ 71 - 15
runtime-modules/working-group/src/lib.rs

@@ -52,7 +52,7 @@ pub use types::{
     Application, ApplicationId, ApplyOnOpeningParameters, BalanceOf, Opening, OpeningId,
     OpeningType, StakeParameters, StakePolicy, Worker, WorkerId,
 };
-use types::{ApplicationInfo, WorkerInfo};
+use types::{ApplicationInfo, RewardPaymentType, WorkerInfo};
 
 pub use checks::{ensure_worker_exists, ensure_worker_signed};
 
@@ -181,11 +181,11 @@ decl_event!(
         /// - Rationale.
         WorkerExited(WorkerId),
 
-        /// Emits when worker is leaving immediatly after extrinsic is called
+        /// Emits when worker started leaving their role.
         /// Params:
         /// - Worker id.
         /// - Rationale.
-        WorkerLeft(WorkerId, Option<Vec<u8>>),
+        WorkerStartedLeaving(WorkerId, Option<Vec<u8>>),
 
         /// Emits on terminating the worker.
         /// Params:
@@ -256,10 +256,28 @@ decl_event!(
 
         /// Emits on budget from the working group being spent
         /// Params:
-        /// - Reciever Account Id.
+        /// - Receiver Account Id.
         /// - Balance spent.
         /// - Rationale.
         BudgetSpending(AccountId, Balance, Option<Vec<u8>>),
+
+        /// Emits on paying the reward.
+        /// Params:
+        /// - Receiver Account Id.
+        /// - Reward
+        RewardPaid(AccountId, Balance),
+
+        /// Emits on paying the missed reward.
+        /// Params:
+        /// - Receiver Account Id.
+        /// - Missed reward
+        MissedRewardPaid(AccountId, Balance),
+
+        /// Emits on reaching new missed reward.
+        /// Params:
+        /// - Worker ID.
+        /// - Missed reward (optional). None means 'no missed reward'.
+        NewMissedRewardLevelReached(WorkerId, Option<Balance>),
     }
 );
 
@@ -653,6 +671,9 @@ decl_module! {
             WorkerById::<T, I>::mutate(worker_id, |worker| {
                 worker.started_leaving_at = Some(Self::current_block())
             });
+
+            // Trigger event
+            Self::deposit_event(RawEvent::WorkerStartedLeaving(worker_id, rationale));
         }
 
         /// Terminate the active worker by the lead.
@@ -1300,7 +1321,11 @@ impl<T: Trait<I>, I: Instance> Module<T, I> {
 
             // Check whether the budget is not zero.
             if actual_reward > Zero::zero() {
-                Self::pay_from_budget(&worker.reward_account_id, actual_reward);
+                Self::pay_reward(
+                    &worker.reward_account_id,
+                    actual_reward,
+                    RewardPaymentType::RegularReward,
+                );
             }
 
             // Check whether the budget is insufficient.
@@ -1323,6 +1348,24 @@ impl<T: Trait<I>, I: Instance> Module<T, I> {
         let _ = <balances::Module<T>>::deposit_creating(account_id, amount);
     }
 
+    // Helper-function joining the reward payment with the event.
+    fn pay_reward(
+        account_id: &T::AccountId,
+        amount: BalanceOf<T>,
+        reward_payment_type: RewardPaymentType,
+    ) {
+        Self::pay_from_budget(account_id, amount);
+
+        let event = match reward_payment_type {
+            RewardPaymentType::MissedReward => {
+                RawEvent::MissedRewardPaid(account_id.clone(), amount)
+            }
+            RewardPaymentType::RegularReward => RawEvent::RewardPaid(account_id.clone(), amount),
+        };
+
+        Self::deposit_event(event);
+    }
+
     // Tries to pay missed reward if the reward is enabled for worker and there is enough of group budget.
     fn try_to_pay_missed_reward(worker_id: &WorkerId<T>, worker: &Worker<T>) {
         if let Some(missed_reward) = worker.missed_reward {
@@ -1331,7 +1374,11 @@ impl<T: Trait<I>, I: Instance> Module<T, I> {
 
             // Checks if the budget allows any payment.
             if could_be_paid_reward > Zero::zero() {
-                Self::pay_from_budget(&worker.reward_account_id, could_be_paid_reward);
+                Self::pay_reward(
+                    &worker.reward_account_id,
+                    could_be_paid_reward,
+                    RewardPaymentType::MissedReward,
+                );
 
                 let new_missed_reward = if insufficient_amount > Zero::zero() {
                     Some(insufficient_amount)
@@ -1339,14 +1386,26 @@ impl<T: Trait<I>, I: Instance> Module<T, I> {
                     None
                 };
 
-                // Update worker missed reward.
-                WorkerById::<T, I>::mutate(worker_id, |worker| {
-                    worker.missed_reward = new_missed_reward;
-                });
+                Self::update_worker_missed_reward(worker_id, new_missed_reward);
             }
         }
     }
 
+    // Update worker missed reward.
+    fn update_worker_missed_reward(
+        worker_id: &WorkerId<T>,
+        new_missed_reward: Option<BalanceOf<T>>,
+    ) {
+        WorkerById::<T, I>::mutate(worker_id, |worker| {
+            worker.missed_reward = new_missed_reward;
+        });
+
+        Self::deposit_event(RawEvent::NewMissedRewardLevelReached(
+            *worker_id,
+            new_missed_reward,
+        ));
+    }
+
     // Saves missed reward for a worker.
     fn save_missed_reward(worker_id: &WorkerId<T>, worker: &Worker<T>, reward: BalanceOf<T>) {
         // Save unpaid reward.
@@ -1354,10 +1413,7 @@ impl<T: Trait<I>, I: Instance> Module<T, I> {
 
         let new_missed_reward = missed_reward_so_far + reward;
 
-        // Update worker missed reward.
-        WorkerById::<T, I>::mutate(worker_id, |worker| {
-            worker.missed_reward = Some(new_missed_reward);
-        });
+        Self::update_worker_missed_reward(worker_id, Some(new_missed_reward));
     }
 
     // Returns allowed payment by the group budget and possible missed payment
@@ -1376,7 +1432,7 @@ impl<T: Trait<I>, I: Instance> Module<T, I> {
         WorkerById::<T, I>::iter()
             .filter_map(|(worker_id, worker)| {
                 if let Some(started_leaving_at) = worker.started_leaving_at {
-                    if started_leaving_at + worker.job_unstaking_period >= Self::current_block() {
+                    if started_leaving_at + worker.job_unstaking_period <= Self::current_block() {
                         return Some((worker_id, worker).into());
                     }
                 }

+ 29 - 0
runtime-modules/working-group/src/tests/fixtures.rs

@@ -44,6 +44,35 @@ impl EventFixture {
 
         assert_eq!(System::events().pop().unwrap(), expected_event);
     }
+
+    pub fn contains_crate_event(
+        expected_raw_event: RawEvent<
+            u64,
+            u64,
+            BTreeMap<u64, u64>,
+            u64,
+            u64,
+            u64,
+            OpeningType,
+            StakePolicy<u64, u64>,
+            ApplyOnOpeningParameters<Test>,
+            DefaultInstance,
+        >,
+    ) {
+        let converted_event = TestEvent::crate_DefaultInstance(expected_raw_event);
+
+        Self::contains_global_event(converted_event)
+    }
+
+    fn contains_global_event(expected_event: TestEvent) {
+        let expected_event = EventRecord {
+            phase: Phase::Initialization,
+            event: expected_event,
+            topics: vec![],
+        };
+
+        assert!(System::events().iter().any(|ev| *ev == expected_event));
+    }
 }
 
 pub struct AddOpeningFixture {

+ 64 - 4
runtime-modules/working-group/src/tests/mod.rs

@@ -592,6 +592,8 @@ fn leave_worker_role_succeeds() {
 
         leave_worker_role_fixture.call_and_assert(Ok(()));
 
+        EventFixture::assert_last_crate_event(RawEvent::WorkerStartedLeaving(worker_id, None));
+
         let worker = TestWorkingGroup::worker_by_id(worker_id);
         run_to_block(1 + worker.job_unstaking_period);
 
@@ -608,9 +610,11 @@ fn leave_worker_role_succeeds_with_paying_missed_reward() {
         let worker_id = HireRegularWorkerFixture::default()
             .with_reward_per_block(Some(reward_per_block))
             .hire();
-        let block_number = 4;
 
-        run_to_block(block_number);
+        let reward_period: u64 = <Test as Trait>::RewardPeriod::get().into();
+        let missed_reward_block_number = reward_period * 2;
+
+        run_to_block(missed_reward_block_number);
 
         assert_eq!(Balances::usable_balance(&account_id), 0);
 
@@ -620,15 +624,65 @@ fn leave_worker_role_succeeds_with_paying_missed_reward() {
         leave_worker_role_fixture.call_and_assert(Ok(()));
 
         let worker = TestWorkingGroup::worker_by_id(worker_id);
-        run_to_block(block_number + worker.job_unstaking_period);
+        let leaving_block = missed_reward_block_number + worker.job_unstaking_period;
+        run_to_block(leaving_block);
 
+        let missed_reward = missed_reward_block_number * reward_per_block;
+        EventFixture::contains_crate_event(RawEvent::NewMissedRewardLevelReached(
+            worker_id,
+            Some(missed_reward),
+        ));
+        EventFixture::contains_crate_event(RawEvent::MissedRewardPaid(account_id, missed_reward));
+
+        // Didn't get the last reward period: leaving earlier than rewarding.
+        let reward_block_count = leaving_block - reward_period;
         assert_eq!(
             Balances::usable_balance(&account_id),
-            block_number * reward_per_block + <Test as Trait>::MinimumApplicationStake::get()
+            reward_block_count * reward_per_block + <Test as Trait>::MinimumApplicationStake::get()
         );
     });
 }
 
+#[test]
+fn leave_worker_role_succeeds_with_correct_unstaking_period() {
+    build_test_externalities().execute_with(|| {
+        let starting_block = 10;
+        run_to_block(starting_block);
+
+        let worker_id = HireRegularWorkerFixture::default().hire();
+
+        // Assert initial worker existence
+        assert!(<crate::WorkerById<Test, DefaultInstance>>::contains_key(
+            worker_id
+        ));
+
+        let default_unstaking_period =
+            TestWorkingGroup::worker_by_id(worker_id).job_unstaking_period;
+
+        let leave_worker_role_fixture = LeaveWorkerRoleFixture::default_for_worker_id(worker_id);
+        leave_worker_role_fixture.call_and_assert(Ok(()));
+
+        // Assert worker existence after leave_role
+        assert!(<crate::WorkerById<Test, DefaultInstance>>::contains_key(
+            worker_id
+        ));
+
+        run_to_block(starting_block + default_unstaking_period - 1);
+
+        // Assert worker existence one block before the end of the unstaking period.
+        assert!(<crate::WorkerById<Test, DefaultInstance>>::contains_key(
+            worker_id
+        ));
+
+        run_to_block(starting_block + default_unstaking_period);
+
+        // Assert worker removal after the unstaking period.
+        assert!(!<crate::WorkerById<Test, DefaultInstance>>::contains_key(
+            worker_id
+        ));
+    });
+}
+
 #[test]
 fn leave_worker_role_succeeds_with_partial_payment_of_missed_reward() {
     build_test_externalities().execute_with(|| {
@@ -1866,6 +1920,12 @@ fn rewards_payments_are_successful() {
             Balances::usable_balance(&account_id),
             block_number * reward_per_block
         );
+
+        let reward_period: u64 = <Test as Trait>::RewardPeriod::get().into();
+        EventFixture::assert_last_crate_event(RawEvent::RewardPaid(
+            account_id,
+            reward_per_block * reward_period,
+        ));
     });
 }
 

+ 9 - 0
runtime-modules/working-group/src/types.rs

@@ -258,3 +258,12 @@ pub type ApplyOnOpeningParameters<T> = ApplyOnOpeningParams<
     <T as frame_system::Trait>::AccountId,
     BalanceOf<T>,
 >;
+
+// Reward payment type enum.
+pub(crate) enum RewardPaymentType {
+    // The reward was missed.
+    MissedReward,
+
+    // The reward was paid in time.
+    RegularReward,
+}