diff --git a/pallets/universal-dividend/Cargo.toml b/pallets/universal-dividend/Cargo.toml index 15b44662466637b12c7078fc98a538ddadd0b4e9..d30d51095fe467b5089f354f971cd1111e82acef 100644 --- a/pallets/universal-dividend/Cargo.toml +++ b/pallets/universal-dividend/Cargo.toml @@ -64,6 +64,11 @@ default-features = false git = 'https://github.com/librelois/substrate.git' branch = 'duniter-monthly-2022-01' +[dependencies.sp-runtime] +default-features = false +git = 'https://github.com/librelois/substrate.git' +branch = 'duniter-monthly-2022-01' + ### DOC ### [package.metadata.docs.rs] diff --git a/pallets/universal-dividend/src/lib.rs b/pallets/universal-dividend/src/lib.rs index 8fe5b9d82cb7a471a9c2bce3d0b0f1c957eb7596..d1ab546cd71524307d998518f83d3800576bbc20 100644 --- a/pallets/universal-dividend/src/lib.rs +++ b/pallets/universal-dividend/src/lib.rs @@ -27,11 +27,12 @@ mod tests; #[cfg(feature = "runtime-benchmarks")] mod benchmarking; -use frame_support::traits::Currency; +use frame_support::traits::{tokens::ExistenceRequirement, Currency}; use sp_arithmetic::{ per_things::Permill, - traits::{One, Zero}, + traits::{CheckedSub, One, Saturating, Zero}, }; +use sp_runtime::traits::StaticLookup; use sp_std::prelude::*; const OFFCHAIN_PREFIX_UD_HISTORY: &[u8] = b"ud::history::"; @@ -48,17 +49,6 @@ pub mod pallet { #[pallet::config] pub trait Config: frame_system::Config { - #[pallet::constant] - /// Universal dividend creation period - type UdCreationPeriod: Get<Self::BlockNumber>; - #[pallet::constant] - /// Universal dividend reevaluation period (in number of creation period) - type UdReevalPeriod: Get<BalanceOf<Self>>; - #[pallet::constant] - /// Universal dividend reevaluation period in number of blocks - /// Must be equal to UdReevalPeriod * UdCreationPeriod - type UdReevalPeriodInBlocks: Get<Self::BlockNumber>; - // The currency type Currency: Currency<Self::AccountId>; /// Because this pallet emits events, it depends on the runtime's definition of an event. @@ -70,6 +60,25 @@ pub mod pallet { #[pallet::constant] /// Square of the money growth rate per ud reevaluation period type SquareMoneyGrowthRate: Get<Permill>; + #[pallet::constant] + /// Universal dividend creation period + type UdCreationPeriod: Get<Self::BlockNumber>; + #[pallet::constant] + /// Universal dividend first reevaluation (in block number) + /// Must be leess than UdReevalPeriodInBlocks + type UdFirstReeval: Get<Self::BlockNumber>; + #[pallet::constant] + /// Universal dividend reevaluation period (in number of creation period) + type UdReevalPeriod: Get<BalanceOf<Self>>; + #[pallet::constant] + /// Universal dividend reevaluation period in number of blocks + /// Must be equal to UdReevalPeriod * UdCreationPeriod + type UdReevalPeriodInBlocks: Get<Self::BlockNumber>; + #[pallet::constant] + /// The number of units to divide the amounts expressed in number of UDs + /// Example: If you wish to express the UD amounts with a maximum precision of the order + /// of the milliUD, choose 1000 + type UnitsPerUd: Get<BalanceOf<Self>>; } // STORAGE // @@ -158,7 +167,9 @@ pub mod pallet { fn on_initialize(n: T::BlockNumber) -> Weight { if (n % T::UdCreationPeriod::get()).is_zero() { let current_members_count = T::MembersCount::get(); - if (n % T::UdReevalPeriodInBlocks::get()).is_zero() { + if (n % T::UdReevalPeriodInBlocks::get()).checked_sub(&T::UdFirstReeval::get()) + == Some(Zero::zero()) + { Self::reeval_ud(current_members_count) + Self::create_ud(current_members_count, n) } else { @@ -204,6 +215,24 @@ pub mod pallet { total_weight } + fn do_transfer_ud( + origin: OriginFor<T>, + dest: <T::Lookup as StaticLookup>::Source, + value: BalanceOf<T>, + existence_requirement: ExistenceRequirement, + ) -> DispatchResultWithPostInfo { + let who = ensure_signed(origin)?; + let dest = T::Lookup::lookup(dest)?; + let ud_amount = <CurrentUdStorage<T>>::try_get() + .map_err(|_| DispatchError::Other("corrupted storage"))?; + T::Currency::transfer( + &who, + &dest, + value.saturating_mul(ud_amount) / T::UnitsPerUd::get(), + existence_requirement, + )?; + Ok(().into()) + } fn reeval_ud(members_count: BalanceOf<T>) -> Weight { let total_weight: Weight = 0; @@ -252,4 +281,29 @@ pub mod pallet { sp_io::offchain_index::set(key.as_ref(), ud_amount.encode().as_ref()); } } + + // CALLS // + + #[pallet::call] + impl<T: Config> Pallet<T> { + /// Transfer some liquid free balance to another account, in milliUD. + #[pallet::weight(0)] + pub fn transfer_ud( + origin: OriginFor<T>, + dest: <T::Lookup as StaticLookup>::Source, + #[pallet::compact] value: BalanceOf<T>, + ) -> DispatchResultWithPostInfo { + Self::do_transfer_ud(origin, dest, value, ExistenceRequirement::AllowDeath) + } + + /// Transfer some liquid free balance to another account, in milliUD. + #[pallet::weight(0)] + pub fn transfer_ud_keep_alive( + origin: OriginFor<T>, + dest: <T::Lookup as StaticLookup>::Source, + #[pallet::compact] value: BalanceOf<T>, + ) -> DispatchResultWithPostInfo { + Self::do_transfer_ud(origin, dest, value, ExistenceRequirement::KeepAlive) + } + } } diff --git a/runtime/common/src/pallets_config.rs b/runtime/common/src/pallets_config.rs index bbd1ac537b1a20203bdd2220b9c192fa5f555058..a9bd788e6d18dec6bbe96f73789e15a4c285ba25 100644 --- a/runtime/common/src/pallets_config.rs +++ b/runtime/common/src/pallets_config.rs @@ -155,8 +155,10 @@ macro_rules! pallets_config { type MembersIds = common_runtime::providers::UdAccountsProvider<Runtime>; type SquareMoneyGrowthRate = SquareMoneyGrowthRate; type UdCreationPeriod = UdCreationPeriod; + type UdFirstReeval = UdFirstReeval; type UdReevalPeriod = UdReevalPeriod; type UdReevalPeriodInBlocks = UdReevalPeriodInBlocks; + type UnitsPerUd = frame_support::traits::ConstU64<1_000>; } impl pallet_ud_accounts_storage::Config for Runtime {} diff --git a/runtime/g1/src/parameters.rs b/runtime/g1/src/parameters.rs index a3fa2e65615247322cdb50d2d41b2b46f9257d73..952f1b2766f79f8bfcb48adc6eba0f3b442542d7 100644 --- a/runtime/g1/src/parameters.rs +++ b/runtime/g1/src/parameters.rs @@ -64,6 +64,8 @@ parameter_types! { parameter_types! { pub const SquareMoneyGrowthRate: Permill = Permill::from_parts(2_381_440); // 0.002_381_440 = 0.0488^2 pub const UdCreationPeriod: BlockNumber = DAYS; + // TODO: this value will depend on the date of the migration + pub const UdFirstReeval: BlockNumber = 45 * DAYS; pub const UdReevalPeriod: Balance = 182; pub const UdReevalPeriodInBlocks: BlockNumber = 2_620_800; // 86400 * 182 / 6 } diff --git a/runtime/gdev/src/parameters.rs b/runtime/gdev/src/parameters.rs index 870995e9d3ccced3adbe00a90037ba59cbda27c6..13fd4e842d738a6569bb52781c6709639323d097 100644 --- a/runtime/gdev/src/parameters.rs +++ b/runtime/gdev/src/parameters.rs @@ -66,6 +66,7 @@ parameter_types! { parameter_types! { pub const SquareMoneyGrowthRate: Permill = Permill::one(); pub const UdCreationPeriod: BlockNumber = 10; + pub const UdFirstReeval: BlockNumber = 100; pub const UdReevalPeriod: Balance = 10; pub const UdReevalPeriodInBlocks: BlockNumber = 20 * 10; } diff --git a/runtime/gtest/src/parameters.rs b/runtime/gtest/src/parameters.rs index 3247e21bb536c918ab7af3a4b7cc1d51c045ff7e..1c6f300eb2fd1d0ebbf165dbf2cbcc8604b9b01c 100644 --- a/runtime/gtest/src/parameters.rs +++ b/runtime/gtest/src/parameters.rs @@ -64,6 +64,7 @@ parameter_types! { parameter_types! { pub const SquareMoneyGrowthRate: Permill = Permill::from_parts(2_381_440); // 0.002_381_440 = 0.0488^2 pub const UdCreationPeriod: BlockNumber = DAYS; + pub const UdFirstReeval: BlockNumber = 2 * DAYS; pub const UdReevalPeriod: Balance = 7; pub const UdReevalPeriodInBlocks: BlockNumber = 100800; // 86400 *7 / 6 }