diff --git a/pallets/distance/src/lib.rs b/pallets/distance/src/lib.rs
index 17639fa025fda34c8a72f82ede6598050e512539..ab6892b438c3629fb52f341e4ad8c063747d6078 100644
--- a/pallets/distance/src/lib.rs
+++ b/pallets/distance/src/lib.rs
@@ -184,13 +184,10 @@ pub mod pallet {
             idty_index: T::IdtyIndex,
             who: T::AccountId,
         },
-        /// A distance evaluation was updated. // TODO refac
-        EvaluationUpdated { evaluator: T::AccountId },
-        /// A distance status was forced. // TODO check if necessary to differenciate
-        EvaluationStatusForced {
-            idty_index: T::IdtyIndex,
-            status: Option<(<T as frame_system::Config>::AccountId, DistanceStatus)>,
-        },
+        /// Distance rule was found valid
+        EvaluatedValid { idty_index: T::IdtyIndex },
+        /// Distance rule was found invalid
+        EvaluatedInvalid { idty_index: T::IdtyIndex },
     }
 
     // ERRORS //
@@ -329,7 +326,7 @@ pub mod pallet {
         ) -> DispatchResult {
             ensure_root(origin)?;
 
-            Self::do_valid_distance_status(identity);
+            Self::do_valid_distance_status(identity, None);
             Ok(())
         }
     }
@@ -405,15 +402,7 @@ pub mod pallet {
             // caller has an identity
             let idty_index = pallet_identity::IdentityIndexOf::<T>::get(who)
                 .ok_or(Error::<T>::CallerHasNoIdentity)?;
-            // TODO some of the following can be moved to a "check idty call allowed" managed by wot
-            let idty = pallet_identity::Identities::<T>::get(idty_index)
-                .ok_or(Error::<T>::CallerIdentityNotFound)?;
-            // caller is member
-            ensure!(
-                idty.status == pallet_identity::IdtyStatus::NotMember
-                    || idty.status == pallet_identity::IdtyStatus::Member,
-                Error::<T>::CallerNotMember
-            );
+            // TODO "check idty call allowed" managed by wot that checks received cert count
             Self::check_request_distance_evaluation_common(idty_index)?;
             Ok(idty_index)
         }
@@ -424,9 +413,10 @@ pub mod pallet {
             target: <T as pallet_identity::Config>::IdtyIndex,
         ) -> Result<(), DispatchError> {
             // caller has an identity
-            let caller_idty_index = pallet_identity::IdentityIndexOf::<T>::get(&who)
+            let caller_idty_index = pallet_identity::IdentityIndexOf::<T>::get(who)
                 .ok_or(Error::<T>::CallerHasNoIdentity)?;
             // TODO some of the following can be moved to a "check idty call allowed" managed by wot
+            // which also checks certification count
             let caller_idty = pallet_identity::Identities::<T>::get(caller_idty_index)
                 .ok_or(Error::<T>::CallerIdentityNotFound)?;
             // caller is member
@@ -520,8 +510,6 @@ pub mod pallet {
                     {
                         median_acc.push(distance_value);
                     }
-
-                    Self::deposit_event(Event::EvaluationUpdated { evaluator });
                     Ok(())
                 } else {
                     // one author can only submit one evaluation
@@ -531,24 +519,40 @@ pub mod pallet {
         }
 
         /// Set the distance status using IdtyIndex and AccountId
-        pub fn do_valid_distance_status(idty: <T as pallet_identity::Config>::IdtyIndex) {
-            // expiration session index
-            let expire_on =
-                pallet_session::Pallet::<T>::current_index() + T::ResultExpiration::get();
+        pub fn do_valid_distance_status(
+            idty: <T as pallet_identity::Config>::IdtyIndex,
+            expire_on: Option<u32>,
+        ) {
+            // expiration session index if not given
+            let expire_on = expire_on.unwrap_or_else(|| {
+                pallet_session::Pallet::<T>::current_index() + T::ResultExpiration::get()
+            });
             // index valid result
             ValidEvaluationResult::<T>::set(idty, Some(()));
             // schedule expiry
             ValidEvaluationExpireOn::<T>::append(expire_on, idty);
             // callback
             T::OnValidDistanceStatus::on_valid_distance_status(idty);
-            // TODO event
+            // deposit event
+            Self::deposit_event(Event::EvaluatedValid { idty_index: idty });
         }
     }
 
     impl<T: Config> pallet_authority_members::OnNewSession for Pallet<T> {
         fn on_new_session(index: SessionIndex) {
+            // set evaluation block
             EvaluationBlock::<T>::set(frame_system::Pallet::<T>::parent_hash());
 
+            // expire old valid results
+            if let Some(idties) = ValidEvaluationExpireOn::<T>::take(index) {
+                idties.into_iter().for_each(|i| {
+                    ValidEvaluationResult::<T>::take(i);
+                });
+            }
+
+            // new expiration session number
+            let expire_on = index + T::ResultExpiration::get();
+
             // Apply the results from the current pool (which was previous session's result pool)
             // We take the results so the pool is left empty for the new session.
             #[allow(clippy::type_complexity)]
@@ -557,46 +561,48 @@ pub mod pallet {
                 <T as pallet_identity::Config>::IdtyIndex,
             > = Pallet::<T>::take_current_pool(index);
             for (idty, median_acc) in current_pool.evaluations.into_iter() {
+                // distance result
+                let mut distance_result: Option<bool> = None;
+
+                // get result of the computation
                 if let Some(median_result) = median_acc.get_median() {
-                    // get result of the comutation
                     let median = match median_result {
                         MedianResult::One(m) => m,
                         MedianResult::Two(m1, m2) => m1 + (m2 - m1) / 2, // Avoid overflow (since max is 1)
                     };
-                    // distance status criterion
-                    let is_distance_status_valid = median >= T::MinAccessibleReferees::get();
+                    // update distance result
+                    distance_result = Some(median >= T::MinAccessibleReferees::get());
+                }
 
-                    // take requester and perform unreserve or slash
-                    if let Some(requester) = PendingEvaluationRequest::<T>::take(idty) {
-                        if is_distance_status_valid {
+                // take requester and perform unreserve or slash
+                if let Some(requester) = PendingEvaluationRequest::<T>::take(idty) {
+                    match distance_result {
+                        None => {
+                            // no result, unreserve
                             T::Currency::unreserve(
                                 &requester,
                                 <T as Config>::EvaluationPrice::get(),
                             );
-                        } else {
+                        }
+                        Some(true) => {
+                            // positive result, unreserve and apply
+                            T::Currency::unreserve(
+                                &requester,
+                                <T as Config>::EvaluationPrice::get(),
+                            );
+                            Self::do_valid_distance_status(idty, Some(expire_on));
+                        }
+                        Some(false) => {
+                            // negative result, slash and deposit event
                             T::Currency::slash_reserved(
                                 &requester,
                                 <T as Config>::EvaluationPrice::get(),
                             );
+                            Self::deposit_event(Event::EvaluatedInvalid { idty_index: idty });
                         }
                     }
-                    // if evaluation happened without request, it's ok to do nothing
-
-                    // if evaluation is positive, remember it for antispam
-                    // and perform callbacks
-                    if is_distance_status_valid {
-                        Self::do_valid_distance_status(idty);
-                    } else {
-                        // TODO event
-                    }
-                }
-                // when no result is published, all funds are unreserved
-                else if let Some(requester) = PendingEvaluationRequest::<T>::take(idty) {
-                    <T as Config>::Currency::unreserve(
-                        &requester,
-                        <T as Config>::EvaluationPrice::get(),
-                    );
                 }
+                // if evaluation happened without request, it's ok to do nothing
             }
         }
     }
diff --git a/runtime/common/src/providers.rs b/runtime/common/src/providers.rs
index 3f8bc76b81f142b3a015ecf72835e2f83ababfac..df5b31e9ecfa13183eb09c2e3bb5776075590c10 100644
--- a/runtime/common/src/providers.rs
+++ b/runtime/common/src/providers.rs
@@ -109,7 +109,7 @@ macro_rules! impl_benchmark_setup_handler {
                 account: &<T as frame_system::Config>::AccountId,
             ) -> () {
                 let _ = pallet_distance::Pallet::<T>::do_valid_distance_status(
-                    *idty_id
+                    *idty_id, None
                 );
             }
             fn add_cert(issuer: &IdtyIndex, receiver: &IdtyIndex) {
diff --git a/runtime/gdev/tests/integration_tests.rs b/runtime/gdev/tests/integration_tests.rs
index d03a902097cb9b06c6dc5aa0c21eea50f4ffd12d..177efe07df6516a3e63fd68d4747af4ddf55dfaa 100644
--- a/runtime/gdev/tests/integration_tests.rs
+++ b/runtime/gdev/tests/integration_tests.rs
@@ -440,11 +440,8 @@ fn test_identity_creation_workflow() {
                 5
             ));
             assert_eq!(
-                Distance::identity_distance_status(5),
-                Some((
-                    AccountKeyring::Charlie.to_account_id(),
-                    pallet_distance::DistanceStatus::Pending
-                ))
+                Distance::pending_evaluation_request(5),
+                Some(AccountKeyring::Charlie.to_account_id(),)
             );
 
             run_to_block(51); // Pass 2 sessions
@@ -681,13 +678,9 @@ fn test_ud_claimed_membership_on_and_off() {
         ));
 
         // alice claims back her membership
-        assert_ok!(Distance::force_set_distance_status(
+        assert_ok!(Distance::force_valid_distance_status(
             frame_system::RawOrigin::Root.into(),
             1,
-            Some((
-                AccountKeyring::Alice.to_account_id(),
-                pallet_distance::DistanceStatus::Valid
-            ))
         ));
         assert_ok!(Membership::claim_membership(
             frame_system::RawOrigin::Signed(AccountKeyring::Alice.to_account_id()).into()
@@ -1133,13 +1126,9 @@ fn test_validate_new_idty_after_few_uds() {
                 2,
                 5,
             ));
-            assert_ok!(Distance::force_set_distance_status(
+            assert_ok!(Distance::force_valid_distance_status(
                 frame_system::RawOrigin::Root.into(),
                 5,
-                Some((
-                    AccountKeyring::Bob.to_account_id(),
-                    pallet_distance::DistanceStatus::Valid
-                ))
             ));
             assert_ok!(Membership::claim_membership(
                 frame_system::RawOrigin::Signed(AccountKeyring::Eve.to_account_id()).into(),
@@ -1193,13 +1182,9 @@ fn test_claim_memberhsip_after_few_uds() {
             ));
 
             // eve should be able to claim her membership
-            assert_ok!(Distance::force_set_distance_status(
+            assert_ok!(Distance::force_valid_distance_status(
                 frame_system::RawOrigin::Root.into(),
                 5,
-                Some((
-                    AccountKeyring::Eve.to_account_id(),
-                    pallet_distance::DistanceStatus::Valid
-                ))
             ));
             assert_ok!(Membership::claim_membership(
                 frame_system::RawOrigin::Signed(AccountKeyring::Eve.to_account_id()).into(),