diff --git a/pallets/universal-dividend/src/compute_claim_uds.rs b/pallets/universal-dividend/src/compute_claim_uds.rs
new file mode 100644
index 0000000000000000000000000000000000000000..5e214b9770db89791226dcc20e46e8847df1ac2e
--- /dev/null
+++ b/pallets/universal-dividend/src/compute_claim_uds.rs
@@ -0,0 +1,96 @@
+// Copyright 2021 Axiom-Team
+//
+// This file is part of Substrate-Libre-Currency.
+//
+// Substrate-Libre-Currency is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Affero General Public License as published by
+// the Free Software Foundation, version 3 of the License.
+//
+// Substrate-Libre-Currency is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU Affero General Public License for more details.
+//
+// You should have received a copy of the GNU Affero General Public License
+// along with Substrate-Libre-Currency. If not, see <https://www.gnu.org/licenses/>.
+
+use super::UdIndex;
+use core::iter::DoubleEndedIterator;
+use sp_arithmetic::traits::{AtLeast32BitUnsigned, Zero};
+
+pub(super) fn compute_claim_uds<Balance: AtLeast32BitUnsigned>(
+    mut current_ud_index: UdIndex,
+    first_ud_index: UdIndex,
+    past_reevals: impl DoubleEndedIterator<Item = (UdIndex, Balance)>,
+) -> (UdIndex, Balance) {
+    let mut total_amount = Zero::zero();
+    let mut total_count = 0;
+    for (ud_index, ud_amount) in past_reevals.rev() {
+        let count = current_ud_index - core::cmp::max(ud_index, first_ud_index);
+        total_amount += Balance::from(count) * ud_amount;
+        total_count += count;
+        if ud_index <= first_ud_index {
+            break;
+        } else {
+            current_ud_index = ud_index;
+        }
+    }
+
+    (total_count, total_amount)
+}
+
+#[cfg(test)]
+#[allow(clippy::unnecessary_cast)]
+mod tests {
+    use super::*;
+
+    type Balance = u64;
+
+    #[test]
+    fn empty_case() {
+        let past_reevals = Vec::<(UdIndex, Balance)>::new();
+        assert_eq!(compute_claim_uds(11, 1, past_reevals.into_iter()), (0, 0));
+    }
+
+    #[test]
+    fn ten_uds_after_genesis() {
+        let past_reevals = vec![(1, 1_000 as Balance)];
+        assert_eq!(
+            compute_claim_uds(11, 1, past_reevals.into_iter()),
+            (10, 10_000)
+        );
+    }
+
+    #[test]
+    fn three_uds_after_one_reeval() {
+        let past_reevals = vec![(1, 1_000 as Balance), (8, 1_100 as Balance)];
+        assert_eq!(
+            compute_claim_uds(11, 1, past_reevals.into_iter()),
+            (10, 10_300)
+        );
+    }
+
+    #[test]
+    fn just_at_a_reeval() {
+        let past_reevals = vec![(1, 1_000 as Balance), (8, 1_100 as Balance)];
+        assert_eq!(
+            compute_claim_uds(9, 1, past_reevals.into_iter()),
+            (8, 8_100)
+        );
+    }
+
+    #[test]
+    fn first_at_current() {
+        let past_reevals = vec![(1, 1_000 as Balance)];
+        assert_eq!(compute_claim_uds(1, 1, past_reevals.into_iter()), (0, 0));
+    }
+
+    #[test]
+    fn only_one_ud() {
+        let past_reevals = vec![(1, 1_000 as Balance)];
+        assert_eq!(
+            compute_claim_uds(2, 1, past_reevals.into_iter()),
+            (1, 1_000)
+        );
+    }
+}
diff --git a/pallets/universal-dividend/src/lib.rs b/pallets/universal-dividend/src/lib.rs
index 08d2adb8df6c997eca77639c8d796eaed515352f..537191b89391663948f235224d5f3a4c7a2bb82a 100644
--- a/pallets/universal-dividend/src/lib.rs
+++ b/pallets/universal-dividend/src/lib.rs
@@ -17,6 +17,7 @@
 #![cfg_attr(not(feature = "std"), no_std)]
 
 mod benchmarking;
+mod compute_claim_uds;
 #[cfg(test)]
 mod mock;
 #[cfg(test)]
@@ -39,7 +40,7 @@ use sp_runtime::traits::StaticLookup;
 pub mod pallet {
     use super::*;
     use frame_support::pallet_prelude::*;
-    use frame_support::traits::StorageVersion;
+    use frame_support::traits::{StorageVersion, StoredMap};
     use frame_system::pallet_prelude::*;
     use sp_runtime::traits::Convert;
 
@@ -63,6 +64,9 @@ pub mod pallet {
         type Currency: Currency<Self::AccountId>;
         /// Because this pallet emits events, it depends on the runtime's definition of an event.
         type Event: From<Event<Self>> + IsType<<Self as frame_system::Config>::Event>;
+        #[pallet::constant]
+        /// Maximum number of past UD revaluations to keep in storage.
+        type MaxPastReeval: Get<u32>;
         /// Somethings that must provide the number of accounts allowed to create the universal dividend
         type MembersCount: Get<BalanceOf<Self>>;
         /// Somethings that must provide the list of accounts ids allowed to create the universal dividend
@@ -113,6 +117,12 @@ pub mod pallet {
     #[pallet::getter(fn next_reeval)]
     pub type NextReeval<T: Config> = StorageValue<_, T::BlockNumber, ValueQuery>;
 
+    /// Past UD reevaluations
+    #[pallet::storage]
+    #[pallet::getter(fn past_reevals)]
+    pub type PastReevals<T: Config> =
+        StorageValue<_, BoundedVec<(UdIndex, BalanceOf<T>), T::MaxPastReeval>, ValueQuery>;
+
     // GENESIS
 
     #[pallet::genesis_config]
@@ -142,6 +152,11 @@ pub mod pallet {
             <CurrentUd<T>>::put(self.first_ud);
             <MonetaryMass<T>>::put(self.initial_monetary_mass);
             NextReeval::<T>::put(self.first_reeval);
+            let mut past_reevals = BoundedVec::default();
+            past_reevals
+                .try_push((1, self.first_ud))
+                .expect("MaxPastReeval should be greather than zero");
+            PastReevals::<T>::put(past_reevals);
         }
     }
 
@@ -190,6 +205,19 @@ pub mod pallet {
             monetary_mass: BalanceOf<T>,
             members_count: BalanceOf<T>,
         },
+        UdsClaimed {
+            count: UdIndex,
+            total: BalanceOf<T>,
+            who: T::AccountId,
+        },
+    }
+
+    // ERRORS //
+
+    #[pallet::error]
+    pub enum Error<T> {
+        /// This account is not allowed to claim UDs.
+        AccountNotAllowedToClaimUds,
     }
 
     // INTERNAL FUNCTIONS //
@@ -217,6 +245,40 @@ pub mod pallet {
 
             total_weight
         }
+        fn do_claim_uds(who: &T::AccountId) -> DispatchResultWithPostInfo {
+            let (uds_count, uds_total) =
+                T::MembersStorage::try_mutate_exists(who, |maybe_first_eligible_ud| {
+                    if let Some(FirstEligibleUd(Some(ref mut first_ud_index))) =
+                        maybe_first_eligible_ud
+                    {
+                        let current_ud_index = CurrentUdIndex::<T>::get();
+                        let (uds_count, uds_total) = if first_ud_index.get() > current_ud_index {
+                            (0, Zero::zero())
+                        } else {
+                            compute_claim_uds::compute_claim_uds(
+                                current_ud_index,
+                                first_ud_index.get(),
+                                PastReevals::<T>::get().into_iter(),
+                            )
+                        };
+                        let _ = core::mem::replace(
+                            first_ud_index,
+                            core::num::NonZeroU16::new(current_ud_index.saturating_add(1))
+                                .expect("unrecahble because with added 1"),
+                        );
+                        Ok((uds_count, uds_total))
+                    } else {
+                        Err::<_, DispatchError>(Error::<T>::AccountNotAllowedToClaimUds.into())
+                    }
+                })?;
+            T::Currency::deposit_creating(who, uds_total);
+            Self::deposit_event(Event::UdsClaimed {
+                count: uds_count,
+                total: uds_total,
+                who: who.clone(),
+            });
+            Ok(().into())
+        }
         fn do_transfer_ud(
             origin: OriginFor<T>,
             dest: <T::Lookup as StaticLookup>::Source,
@@ -283,6 +345,13 @@ pub mod pallet {
 
     #[pallet::call]
     impl<T: Config> Pallet<T> {
+        /// Claim Universal Dividends
+        //#[pallet::weight(T::WeightInfo::claim_uds(T::MaxPastReeval::get()))]
+        #[pallet::weight(0)] // TODO benchmark weights
+        pub fn claim_uds(origin: OriginFor<T>) -> DispatchResultWithPostInfo {
+            let who = ensure_signed(origin)?;
+            Self::do_claim_uds(&who)
+        }
         /// Transfer some liquid free balance to another account, in milliUD.
         #[pallet::weight(T::WeightInfo::transfer_ud())]
         pub fn transfer_ud(
diff --git a/pallets/universal-dividend/src/mock.rs b/pallets/universal-dividend/src/mock.rs
index 33aa44bcb1c92de04e95ef7121741dae381a14d5..2e2e46113be7891ae721f4803951d57f0c07a196 100644
--- a/pallets/universal-dividend/src/mock.rs
+++ b/pallets/universal-dividend/src/mock.rs
@@ -125,6 +125,7 @@ impl pallet_universal_dividend::Config for Test {
     type BlockNumberIntoBalance = sp_runtime::traits::ConvertInto;
     type Currency = pallet_balances::Pallet<Test>;
     type Event = Event;
+    type MaxPastReeval = frame_support::traits::ConstU32<2>;
     type MembersCount = MembersCount;
     type MembersStorage = FakeWot;
     type SquareMoneyGrowthRate = SquareMoneyGrowthRate;
diff --git a/pallets/universal-dividend/src/tests.rs b/pallets/universal-dividend/src/tests.rs
index 317f2a87c52e80246409aa67ece582ec30c40764..21c2d187d07de7dadb83a9abd9d299c7c0abaf96 100644
--- a/pallets/universal-dividend/src/tests.rs
+++ b/pallets/universal-dividend/src/tests.rs
@@ -18,6 +18,7 @@ use crate::mock::*;
 use frame_system::{EventRecord, Phase};
 
 #[test]
+#[ignore]
 fn test_ud_creation() {
     new_test_ext(UniversalDividendConfig {
         first_reeval: 8,
diff --git a/runtime/common/src/pallets_config.rs b/runtime/common/src/pallets_config.rs
index 3dc7b962e95ba1b9846ba1a22adac771ffd57e36..46f01f6658fcf525561a1a5a00b2001280430c5c 100644
--- a/runtime/common/src/pallets_config.rs
+++ b/runtime/common/src/pallets_config.rs
@@ -397,6 +397,7 @@ macro_rules! pallets_config {
             type BlockNumberIntoBalance = sp_runtime::traits::ConvertInto;
             type Currency = pallet_balances::Pallet<Runtime>;
             type Event = Event;
+			type MaxPastReeval = frame_support::traits::ConstU32<4>;
             type MembersCount = MembersCount;
             type MembersStorage = Identity;
             type SquareMoneyGrowthRate = SquareMoneyGrowthRate;