From a485bbde6d77e66608887fad6122afb61a3ce294 Mon Sep 17 00:00:00 2001 From: "Muhammad-Jibril B.A" Date: Wed, 22 Dec 2021 10:35:04 +0800 Subject: [PATCH] Fees and vesting ERevert to MultiCurrency Vesting #682 Update OnPayment of TransactionFees to 50% to Treasury 50% Burn #677 --- Cargo.lock | 1 + lib-serml/vesting/Cargo.toml | 3 +- lib-serml/vesting/src/lib.rs | 624 +++++++++++++++++++++++++++------ lib-serml/vesting/src/mock.rs | 100 +++++- lib-serml/vesting/src/tests.rs | 202 +++++------ resources/types.json | 7 + runtime/src/lib.rs | 34 +- 7 files changed, 721 insertions(+), 250 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 525bb135e..ef353b594 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4177,6 +4177,7 @@ dependencies = [ "frame-support", "frame-system", "module-support", + "orml-tokens", "orml-traits", "pallet-balances", "parity-scale-codec", diff --git a/lib-serml/vesting/Cargo.toml b/lib-serml/vesting/Cargo.toml index 62229d78d..794d6bd8a 100644 --- a/lib-serml/vesting/Cargo.toml +++ b/lib-serml/vesting/Cargo.toml @@ -20,6 +20,7 @@ orml-traits = { path = "../../lib-orml/traits", default-features = false } [dev-dependencies] sp-core = { git = "https://github.com/paritytech/substrate" , branch = "polkadot-v0.9.10" } pallet-balances = { git = "https://github.com/paritytech/substrate" , branch = "polkadot-v0.9.10" } +orml-tokens = { path = "../../lib-orml/tokens" } [features] default = ["std"] @@ -38,4 +39,4 @@ std = [ runtime-benchmarks = [ "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", -] +] \ No newline at end of file diff --git a/lib-serml/vesting/src/lib.rs b/lib-serml/vesting/src/lib.rs index b7248da86..8d39a7d4d 100644 --- a/lib-serml/vesting/src/lib.rs +++ b/lib-serml/vesting/src/lib.rs @@ -52,7 +52,7 @@ use codec::{HasCompact, MaxEncodedLen}; use frame_support::{ ensure, pallet_prelude::*, - traits::{Currency, EnsureOrigin, ExistenceRequirement, Get, LockIdentifier, LockableCurrency, WithdrawReasons}, + traits::{EnsureOrigin, Get}, transactional, BoundedVec, }; use frame_system::{ensure_root, ensure_signed, pallet_prelude::*}; @@ -64,7 +64,10 @@ use sp_std::{ cmp::{Eq, PartialEq}, convert::TryInto, vec::Vec, +};use orml_traits::{ + LockIdentifier, MultiCurrency, MultiLockableCurrency, }; +use primitives::CurrencyId; mod mock; mod tests; @@ -130,10 +133,13 @@ pub mod module { use super::*; pub(crate) type BalanceOf = - <::Currency as Currency<::AccountId>>::Balance; + <::MultiCurrency as MultiCurrency<::AccountId>>::Balance; + pub(crate) type CurrencyIdOf = + <::MultiCurrency as MultiCurrency<::AccountId>>::CurrencyId; pub(crate) type VestingScheduleOf = VestingSchedule<::BlockNumber, BalanceOf>; pub type ScheduledItem = ( ::AccountId, + CurrencyIdOf, ::BlockNumber, ::BlockNumber, u32, @@ -144,7 +150,31 @@ pub mod module { pub trait Config: frame_system::Config { type Event: From> + IsType<::Event>; - type Currency: LockableCurrency; + type MultiCurrency: MultiLockableCurrency; + + #[pallet::constant] + /// Native Setheum (SETM) currency id. [P]Pronounced "set M" or "setem" + /// + type GetNativeCurrencyId: Get; + + #[pallet::constant] + /// Serp (SERP) currency id. + /// + type GetSerpCurrencyId: Get; + + #[pallet::constant] + /// The Dinar (DNAR) currency id. + /// + type GetDinarCurrencyId: Get; + + #[pallet::constant] + /// Setter (SETR) currency id + /// + type SetterCurrencyId: Get; + + #[pallet::constant] + /// The SetDollar (SETUSD) currency id + type GetSetUSDId: Get; #[pallet::constant] /// The minimum amount transferred to call `vested_transfer`. @@ -156,8 +186,20 @@ pub mod module { /// Weight information for extrinsics in this module. type WeightInfo: WeightInfo; - /// The maximum vesting schedules - type MaxVestingSchedules: Get; + /// The maximum vesting schedules for SETM + type MaxNativeVestingSchedules: Get; + + /// The maximum vesting schedules for SERP + type MaxSerpVestingSchedules: Get; + + /// The maximum vesting schedules for DNAR + type MaxDinarVestingSchedules: Get; + + /// The maximum vesting schedules for SETR + type MaxSetterVestingSchedules: Get; + + /// The maximum vesting schedules for SETUSD + type MaxSetUSDVestingSchedules: Get; } #[pallet::error] @@ -180,24 +222,76 @@ pub mod module { #[pallet::generate_deposit(fn deposit_event)] #[pallet::metadata(T::AccountId = "AccountId", VestingScheduleOf = "VestingScheduleOf", BalanceOf = "Balance")] pub enum Event { - /// Added new vesting schedule. \[from, to, vesting_schedule\] - VestingScheduleAdded(T::AccountId, T::AccountId, VestingScheduleOf), - /// Claimed vesting. \[who, locked_amount\] - Claimed(T::AccountId, BalanceOf), - /// Updated vesting schedules. \[who\] - VestingSchedulesUpdated(T::AccountId), + /// Added new vesting schedule. \[currency_id, from, to, vesting_schedule\] + VestingScheduleAdded(CurrencyIdOf, T::AccountId, T::AccountId, VestingScheduleOf), + /// Claimed vesting. \[who, currency_id, locked_amount\] + Claimed(T::AccountId, CurrencyIdOf, BalanceOf), + /// Updated vesting schedules. \[currency_id, who\] + VestingSchedulesUpdated(CurrencyIdOf, T::AccountId), } - /// Vesting schedules of an account. + /// Vesting schedules of an account under SETM currency. + /// + /// NativeVestingSchedules: map AccountId => Vec + #[pallet::storage] + #[pallet::getter(fn native_vesting_schedules)] + pub type NativeVestingSchedules = StorageMap< + _, + Blake2_128Concat, + T::AccountId, + BoundedVec, T::MaxNativeVestingSchedules>, + ValueQuery, + >; + + /// Vesting schedules of an account under SERP currency. + /// + /// SerpVestingSchedules: map AccountId => Vec + #[pallet::storage] + #[pallet::getter(fn serp_vesting_schedules)] + pub type SerpVestingSchedules = StorageMap< + _, + Blake2_128Concat, + T::AccountId, + BoundedVec, T::MaxSerpVestingSchedules>, + ValueQuery, + >; + + /// Vesting schedules of an account under DNAR currency. + /// + /// DinarVestingSchedules: map AccountId => Vec + #[pallet::storage] + #[pallet::getter(fn dinar_vesting_schedules)] + pub type DinarVestingSchedules = StorageMap< + _, + Blake2_128Concat, + T::AccountId, + BoundedVec, T::MaxDinarVestingSchedules>, + ValueQuery, + >; + + /// Vesting schedules of an account under SETR currency. /// - /// VestingSchedules: map AccountId => Vec + /// SetterVestingSchedules: map AccountId => Vec #[pallet::storage] - #[pallet::getter(fn vesting_schedules)] - pub type VestingSchedules = StorageMap< + #[pallet::getter(fn setter_vesting_schedules)] + pub type SetterVestingSchedules = StorageMap< _, Blake2_128Concat, T::AccountId, - BoundedVec, T::MaxVestingSchedules>, + BoundedVec, T::MaxSetterVestingSchedules>, + ValueQuery, + >; + + /// Vesting schedules of an account under SETUSD currency. + /// + /// SetUSDVestingSchedules: map AccountId => Vec + #[pallet::storage] + #[pallet::getter(fn setusd_vesting_schedules)] + pub type SetUSDVestingSchedules = StorageMap< + _, + Blake2_128Concat, + T::AccountId, + BoundedVec, T::MaxSetUSDVestingSchedules>, ValueQuery, >; @@ -218,26 +312,113 @@ pub mod module { fn build(&self) { self.vesting .iter() - .for_each(|(who, start, period, period_count, per_period)| { - let total = *per_period * Into::>::into(*period_count); - - let bounded_schedule: BoundedVec, T::MaxVestingSchedules> = - vec![VestingSchedule { - start: *start, - period: *period, - period_count: *period_count, - per_period: *per_period, - }] - .try_into() - .expect("Max vesting schedules exceeded"); - - assert!( - T::Currency::free_balance(who) >= total, - "Account do not have enough balance" - ); - - T::Currency::set_lock(VESTING_LOCK_ID, who, total, WithdrawReasons::all()); - VestingSchedules::::insert(who, bounded_schedule); + .for_each(|(who, currency_id, start, period, period_count, per_period)| { + if currency_id == &T::GetNativeCurrencyId::get() { + let total = *per_period * Into::>::into(*period_count); + + let bounded_schedule: BoundedVec, T::MaxNativeVestingSchedules> = + vec![VestingSchedule { + start: *start, + period: *period, + period_count: *period_count, + per_period: *per_period, + }] + .try_into() + .expect("Max vesting schedules exceeded"); + + assert!( + T::MultiCurrency::free_balance(T::GetNativeCurrencyId::get(), who) >= total, + "Account do not have enough balance" + ); + + if T::MultiCurrency::set_lock(VESTING_LOCK_ID, T::GetNativeCurrencyId::get(), who, total).is_ok() { + NativeVestingSchedules::::insert(who, bounded_schedule) + } + } else if currency_id == &T::GetSerpCurrencyId::get() { + let total = *per_period * Into::>::into(*period_count); + + let bounded_schedule: BoundedVec, T::MaxSerpVestingSchedules> = + vec![VestingSchedule { + start: *start, + period: *period, + period_count: *period_count, + per_period: *per_period, + }] + .try_into() + .expect("Max vesting schedules exceeded"); + + assert!( + T::MultiCurrency::free_balance(T::GetSerpCurrencyId::get(), who) >= total, + "Account do not have enough balance" + ); + + if T::MultiCurrency::set_lock(VESTING_LOCK_ID, T::GetSerpCurrencyId::get(), who, total).is_ok() { + SerpVestingSchedules::::insert(who, bounded_schedule) + } + } else if currency_id == &T::GetDinarCurrencyId::get() { + let total = *per_period * Into::>::into(*period_count); + + let bounded_schedule: BoundedVec, T::MaxDinarVestingSchedules> = + vec![VestingSchedule { + start: *start, + period: *period, + period_count: *period_count, + per_period: *per_period, + }] + .try_into() + .expect("Max vesting schedules exceeded"); + + assert!( + T::MultiCurrency::free_balance(T::GetDinarCurrencyId::get(), who) >= total, + "Account do not have enough balance" + ); + + if T::MultiCurrency::set_lock(VESTING_LOCK_ID, T::GetDinarCurrencyId::get(), who, total).is_ok() { + DinarVestingSchedules::::insert(who, bounded_schedule) + } + } else if currency_id == &T::SetterCurrencyId::get() { + let total = *per_period * Into::>::into(*period_count); + + let bounded_schedule: BoundedVec, T::MaxSetterVestingSchedules> = + vec![VestingSchedule { + start: *start, + period: *period, + period_count: *period_count, + per_period: *per_period, + }] + .try_into() + .expect("Max vesting schedules exceeded"); + + assert!( + T::MultiCurrency::free_balance(T::SetterCurrencyId::get(), who) >= total, + "Account do not have enough balance" + ); + + if T::MultiCurrency::set_lock(VESTING_LOCK_ID, T::SetterCurrencyId::get(), who, total).is_ok() { + SetterVestingSchedules::::insert(who, bounded_schedule) + } + } else if currency_id == &T::GetSetUSDId::get() { + let total = *per_period * Into::>::into(*period_count); + + let bounded_schedule: BoundedVec, T::MaxSetUSDVestingSchedules> = + vec![VestingSchedule { + start: *start, + period: *period, + period_count: *period_count, + per_period: *per_period, + }] + .try_into() + .expect("Max vesting schedules exceeded"); + + assert!( + T::MultiCurrency::free_balance(T::GetSetUSDId::get(), who) >= total, + "Account do not have enough balance" + ); + + if T::MultiCurrency::set_lock(VESTING_LOCK_ID, T::GetSetUSDId::get(), who, total).is_ok() { + SetUSDVestingSchedules::::insert(who, bounded_schedule) + } + } }); } } @@ -250,51 +431,57 @@ pub mod module { #[pallet::call] impl Pallet { - #[pallet::weight(T::WeightInfo::claim((::MaxVestingSchedules::get() / 2) as u32))] - pub fn claim(origin: OriginFor) -> DispatchResult { + #[pallet::weight(T::WeightInfo::claim((::MaxNativeVestingSchedules::get() / 2) as u32))] + pub fn claim(origin: OriginFor, currency_id: CurrencyIdOf) -> DispatchResult { let who = ensure_signed(origin)?; - let locked_amount = Self::do_claim(&who); + let locked_amount = Self::do_claim(currency_id, &who); - Self::deposit_event(Event::Claimed(who, locked_amount)); + Self::deposit_event(Event::Claimed(who, currency_id, locked_amount)); Ok(()) } #[pallet::weight(T::WeightInfo::vested_transfer())] pub fn vested_transfer( origin: OriginFor, + currency_id: CurrencyIdOf, dest: ::Source, - schedule: VestingScheduleOf, + schedule: VestingScheduleOf ) -> DispatchResult { let from = T::VestedTransferOrigin::ensure_origin(origin)?; let to = T::Lookup::lookup(dest)?; - Self::do_vested_transfer(&from, &to, schedule.clone())?; + Self::do_vested_transfer(currency_id, &from, &to, schedule.clone())?; - Self::deposit_event(Event::VestingScheduleAdded(from, to, schedule)); + Self::deposit_event(Event::VestingScheduleAdded(currency_id, from, to, schedule)); Ok(()) } #[pallet::weight(T::WeightInfo::update_vesting_schedules(vesting_schedules.len() as u32))] pub fn update_vesting_schedules( origin: OriginFor, + currency_id: CurrencyIdOf, who: ::Source, vesting_schedules: Vec>, ) -> DispatchResult { ensure_root(origin)?; let account = T::Lookup::lookup(who)?; - Self::do_update_vesting_schedules(&account, vesting_schedules)?; + Self::do_update_vesting_schedules(currency_id, &account, vesting_schedules)?; - Self::deposit_event(Event::VestingSchedulesUpdated(account)); + Self::deposit_event(Event::VestingSchedulesUpdated(currency_id, account)); Ok(()) } - #[pallet::weight(T::WeightInfo::claim((::MaxVestingSchedules::get() / 2) as u32))] - pub fn claim_for(origin: OriginFor, dest: ::Source) -> DispatchResult { + #[pallet::weight(T::WeightInfo::claim((::MaxNativeVestingSchedules::get() / 2) as u32))] + pub fn claim_for( + origin: OriginFor, + currency_id: CurrencyIdOf, + dest: ::Source + ) -> DispatchResult { let _ = ensure_signed(origin)?; let who = T::Lookup::lookup(dest)?; - let locked_amount = Self::do_claim(&who); + let locked_amount = Self::do_claim(currency_id, &who); - Self::deposit_event(Event::Claimed(who, locked_amount)); + Self::deposit_event(Event::Claimed(who, currency_id, locked_amount)); Ok(()) } } @@ -309,80 +496,307 @@ impl BlockNumberProvider for Pallet { } impl Pallet { - fn do_claim(who: &T::AccountId) -> BalanceOf { - let locked = Self::locked_balance(who); + fn do_claim(currency_id: CurrencyIdOf, who: &T::AccountId) -> BalanceOf { + let locked = Self::locked_balance(currency_id, who); if locked.is_zero() { - // cleanup the storage and unlock the fund - >::remove(who); - T::Currency::remove_lock(VESTING_LOCK_ID, who); + if currency_id == T::GetNativeCurrencyId::get() { + // cleanup the storage and unlock the fund + >::remove(who); + T::MultiCurrency::remove_lock(VESTING_LOCK_ID, currency_id, who).unwrap(); + } else if currency_id == T::GetSerpCurrencyId::get() { + // cleanup the storage and unlock the fund + >::remove(who); + T::MultiCurrency::remove_lock(VESTING_LOCK_ID, currency_id, who).unwrap(); + } else if currency_id == T::GetDinarCurrencyId::get() { + // cleanup the storage and unlock the fund + >::remove(who); + T::MultiCurrency::remove_lock(VESTING_LOCK_ID, currency_id, who).unwrap(); + } else if currency_id == T::SetterCurrencyId::get() { + // cleanup the storage and unlock the fund + >::remove(who); + T::MultiCurrency::remove_lock(VESTING_LOCK_ID, currency_id, who).unwrap(); + } else if currency_id == T::GetSetUSDId::get() { + // cleanup the storage and unlock the fund + >::remove(who); + T::MultiCurrency::remove_lock(VESTING_LOCK_ID, currency_id, who).unwrap(); + } } else { - T::Currency::set_lock(VESTING_LOCK_ID, who, locked, WithdrawReasons::all()); + T::MultiCurrency::set_lock(VESTING_LOCK_ID, currency_id, who, locked).unwrap(); } locked } /// Returns locked balance based on current block number. - fn locked_balance(who: &T::AccountId) -> BalanceOf { + fn locked_balance(currency_id: CurrencyIdOf, who: &T::AccountId) -> BalanceOf { let now = ::current_block_number(); - >::mutate_exists(who, |maybe_schedules| { - let total = if let Some(schedules) = maybe_schedules.as_mut() { - let mut total: BalanceOf = Zero::zero(); - schedules.retain(|s| { - let amount = s.locked_amount(now); - total = total.saturating_add(amount); - !amount.is_zero() - }); - total - } else { - Zero::zero() - }; - if total.is_zero() { - *maybe_schedules = None; - } - total - }) + if currency_id == T::GetNativeCurrencyId::get() { + // cleanup the storage and unlock the fund + >::mutate_exists(who, |maybe_schedules| { + let total = if let Some(schedules) = maybe_schedules.as_mut() { + let mut total: BalanceOf = Zero::zero(); + schedules.retain(|s| { + let amount = s.locked_amount(now); + total = total.saturating_add(amount); + !amount.is_zero() + }); + total + } else { + Zero::zero() + }; + if total.is_zero() { + *maybe_schedules = None; + } + return total + }) + } else if currency_id == T::GetSerpCurrencyId::get() { + // cleanup the storage and unlock the fund + >::mutate_exists(who, |maybe_schedules| { + let total = if let Some(schedules) = maybe_schedules.as_mut() { + let mut total: BalanceOf = Zero::zero(); + schedules.retain(|s| { + let amount = s.locked_amount(now); + total = total.saturating_add(amount); + !amount.is_zero() + }); + total + } else { + Zero::zero() + }; + if total.is_zero() { + *maybe_schedules = None; + } + return total + }) + } else if currency_id == T::GetDinarCurrencyId::get() { + // cleanup the storage and unlock the fund + >::mutate_exists(who, |maybe_schedules| { + let total = if let Some(schedules) = maybe_schedules.as_mut() { + let mut total: BalanceOf = Zero::zero(); + schedules.retain(|s| { + let amount = s.locked_amount(now); + total = total.saturating_add(amount); + !amount.is_zero() + }); + total + } else { + Zero::zero() + }; + if total.is_zero() { + *maybe_schedules = None; + } + return total + }) + } else if currency_id == T::SetterCurrencyId::get() { + // cleanup the storage and unlock the fund + >::mutate_exists(who, |maybe_schedules| { + let total = if let Some(schedules) = maybe_schedules.as_mut() { + let mut total: BalanceOf = Zero::zero(); + schedules.retain(|s| { + let amount = s.locked_amount(now); + total = total.saturating_add(amount); + !amount.is_zero() + }); + total + } else { + Zero::zero() + }; + if total.is_zero() { + *maybe_schedules = None; + } + return total + }) + } else if currency_id == T::GetSetUSDId::get() { + // cleanup the storage and unlock the fund + >::mutate_exists(who, |maybe_schedules| { + let total = if let Some(schedules) = maybe_schedules.as_mut() { + let mut total: BalanceOf = Zero::zero(); + schedules.retain(|s| { + let amount = s.locked_amount(now); + total = total.saturating_add(amount); + !amount.is_zero() + }); + total + } else { + Zero::zero() + }; + if total.is_zero() { + *maybe_schedules = None; + } + return total + }) + } else { + Zero::zero() + } } #[transactional] - fn do_vested_transfer(from: &T::AccountId, to: &T::AccountId, schedule: VestingScheduleOf) -> DispatchResult { + fn do_vested_transfer( + currency_id: CurrencyIdOf, + from: &T::AccountId, + to: &T::AccountId, + schedule: VestingScheduleOf + ) -> DispatchResult { let schedule_amount = Self::ensure_valid_vesting_schedule(&schedule)?; - let total_amount = Self::locked_balance(to) + let total_amount = Self::locked_balance(currency_id, to) .checked_add(&schedule_amount) .ok_or(ArithmeticError::Overflow)?; - T::Currency::transfer(from, to, schedule_amount, ExistenceRequirement::AllowDeath)?; - T::Currency::set_lock(VESTING_LOCK_ID, to, total_amount, WithdrawReasons::all()); - >::try_append(to, schedule).map_err(|_| Error::::MaxVestingSchedulesExceeded)?; + if currency_id == T::GetNativeCurrencyId::get() { + T::MultiCurrency::transfer(currency_id, from, to, schedule_amount)?; + T::MultiCurrency::set_lock(VESTING_LOCK_ID, currency_id, to, total_amount)?; + >::try_append(to, schedule).map_err(|_| Error::::MaxVestingSchedulesExceeded)?; + } else if currency_id == T::GetSerpCurrencyId::get() { + T::MultiCurrency::transfer(currency_id, from, to, schedule_amount)?; + T::MultiCurrency::set_lock(VESTING_LOCK_ID, currency_id, to, total_amount)?; + >::try_append(to, schedule).map_err(|_| Error::::MaxVestingSchedulesExceeded)?; + } else if currency_id == T::GetDinarCurrencyId::get() { + T::MultiCurrency::transfer(currency_id, from, to, schedule_amount)?; + T::MultiCurrency::set_lock(VESTING_LOCK_ID, currency_id, to, total_amount)?; + >::try_append(to, schedule).map_err(|_| Error::::MaxVestingSchedulesExceeded)?; + } else if currency_id == T::SetterCurrencyId::get() { + T::MultiCurrency::transfer(currency_id, from, to, schedule_amount)?; + T::MultiCurrency::set_lock(VESTING_LOCK_ID, currency_id, to, total_amount)?; + >::try_append(to, schedule).map_err(|_| Error::::MaxVestingSchedulesExceeded)?; + } else if currency_id == T::GetSetUSDId::get() { + T::MultiCurrency::transfer(currency_id, from, to, schedule_amount)?; + T::MultiCurrency::set_lock(VESTING_LOCK_ID, currency_id, to, total_amount)?; + >::try_append(to, schedule).map_err(|_| Error::::MaxVestingSchedulesExceeded)?; + }; Ok(()) } - fn do_update_vesting_schedules(who: &T::AccountId, schedules: Vec>) -> DispatchResult { - let bounded_schedules: BoundedVec, T::MaxVestingSchedules> = schedules - .try_into() - .map_err(|_| Error::::MaxVestingSchedulesExceeded)?; - - // empty vesting schedules cleanup the storage and unlock the fund - if bounded_schedules.len().is_zero() { - >::remove(who); - T::Currency::remove_lock(VESTING_LOCK_ID, who); - return Ok(()); - } - - let total_amount = bounded_schedules - .iter() - .try_fold::<_, _, Result, DispatchError>>(Zero::zero(), |acc_amount, schedule| { - let amount = Self::ensure_valid_vesting_schedule(schedule)?; - Ok(acc_amount + amount) - })?; - ensure!( - T::Currency::free_balance(who) >= total_amount, - Error::::InsufficientBalanceToLock, - ); - - T::Currency::set_lock(VESTING_LOCK_ID, who, total_amount, WithdrawReasons::all()); - >::insert(who, bounded_schedules); - + fn do_update_vesting_schedules( + currency_id: CurrencyIdOf, + who: &T::AccountId, + schedules: Vec> + ) -> DispatchResult { + if currency_id == T::GetNativeCurrencyId::get() { + let bounded_schedules: BoundedVec, T::MaxNativeVestingSchedules> = schedules + .try_into() + .map_err(|_| Error::::MaxVestingSchedulesExceeded)?; + + // empty vesting schedules cleanup the storage and unlock the fund + if bounded_schedules.len().is_zero() { + >::remove(who); + T::MultiCurrency::remove_lock(VESTING_LOCK_ID, currency_id, who).unwrap(); + return Ok(()); + } + + let total_amount = bounded_schedules + .iter() + .try_fold::<_, _, Result, DispatchError>>(Zero::zero(), |acc_amount, schedule| { + let amount = Self::ensure_valid_vesting_schedule(schedule)?; + Ok(acc_amount + amount) + })?; + ensure!( + T::MultiCurrency::free_balance(currency_id, who) >= total_amount, + Error::::InsufficientBalanceToLock, + ); + + T::MultiCurrency::set_lock(VESTING_LOCK_ID, currency_id, who, total_amount)?; + >::insert(who, bounded_schedules); + } else if currency_id == T::GetSerpCurrencyId::get() { + let bounded_schedules: BoundedVec, T::MaxSerpVestingSchedules> = schedules + .try_into() + .map_err(|_| Error::::MaxVestingSchedulesExceeded)?; + + // empty vesting schedules cleanup the storage and unlock the fund + if bounded_schedules.len().is_zero() { + >::remove(who); + T::MultiCurrency::remove_lock(VESTING_LOCK_ID, currency_id, who).unwrap(); + return Ok(()); + } + + let total_amount = bounded_schedules + .iter() + .try_fold::<_, _, Result, DispatchError>>(Zero::zero(), |acc_amount, schedule| { + let amount = Self::ensure_valid_vesting_schedule(schedule)?; + Ok(acc_amount + amount) + })?; + ensure!( + T::MultiCurrency::free_balance(currency_id, who) >= total_amount, + Error::::InsufficientBalanceToLock, + ); + + T::MultiCurrency::set_lock(VESTING_LOCK_ID, currency_id, who, total_amount)?; + >::insert(who, bounded_schedules); + } else if currency_id == T::GetDinarCurrencyId::get() { + let bounded_schedules: BoundedVec, T::MaxDinarVestingSchedules> = schedules + .try_into() + .map_err(|_| Error::::MaxVestingSchedulesExceeded)?; + + // empty vesting schedules cleanup the storage and unlock the fund + if bounded_schedules.len().is_zero() { + >::remove(who); + T::MultiCurrency::remove_lock(VESTING_LOCK_ID, currency_id, who).unwrap(); + return Ok(()); + } + + let total_amount = bounded_schedules + .iter() + .try_fold::<_, _, Result, DispatchError>>(Zero::zero(), |acc_amount, schedule| { + let amount = Self::ensure_valid_vesting_schedule(schedule)?; + Ok(acc_amount + amount) + })?; + ensure!( + T::MultiCurrency::free_balance(currency_id, who) >= total_amount, + Error::::InsufficientBalanceToLock, + ); + + T::MultiCurrency::set_lock(VESTING_LOCK_ID, currency_id, who, total_amount)?; + >::insert(who, bounded_schedules); + } else if currency_id == T::SetterCurrencyId::get() { + let bounded_schedules: BoundedVec, T::MaxSetterVestingSchedules> = schedules + .try_into() + .map_err(|_| Error::::MaxVestingSchedulesExceeded)?; + + // empty vesting schedules cleanup the storage and unlock the fund + if bounded_schedules.len().is_zero() { + >::remove(who); + T::MultiCurrency::remove_lock(VESTING_LOCK_ID, currency_id, who).unwrap(); + return Ok(()); + } + + let total_amount = bounded_schedules + .iter() + .try_fold::<_, _, Result, DispatchError>>(Zero::zero(), |acc_amount, schedule| { + let amount = Self::ensure_valid_vesting_schedule(schedule)?; + Ok(acc_amount + amount) + })?; + ensure!( + T::MultiCurrency::free_balance(currency_id, who) >= total_amount, + Error::::InsufficientBalanceToLock, + ); + + T::MultiCurrency::set_lock(VESTING_LOCK_ID, currency_id, who, total_amount)?; + >::insert(who, bounded_schedules); + } else if currency_id == T::GetSetUSDId::get() { + let bounded_schedules: BoundedVec, T::MaxSetUSDVestingSchedules> = schedules + .try_into() + .map_err(|_| Error::::MaxVestingSchedulesExceeded)?; + + // empty vesting schedules cleanup the storage and unlock the fund + if bounded_schedules.len().is_zero() { + >::remove(who); + T::MultiCurrency::remove_lock(VESTING_LOCK_ID, currency_id, who).unwrap(); + return Ok(()); + } + + let total_amount = bounded_schedules + .iter() + .try_fold::<_, _, Result, DispatchError>>(Zero::zero(), |acc_amount, schedule| { + let amount = Self::ensure_valid_vesting_schedule(schedule)?; + Ok(acc_amount + amount) + })?; + ensure!( + T::MultiCurrency::free_balance(currency_id, who) >= total_amount, + Error::::InsufficientBalanceToLock, + ); + + T::MultiCurrency::set_lock(VESTING_LOCK_ID, currency_id, who, total_amount)?; + >::insert(who, bounded_schedules); + }; Ok(()) } @@ -398,4 +812,4 @@ impl Pallet { Ok(total) } -} +} \ No newline at end of file diff --git a/lib-serml/vesting/src/mock.rs b/lib-serml/vesting/src/mock.rs index 385c15b0b..557d3c44f 100644 --- a/lib-serml/vesting/src/mock.rs +++ b/lib-serml/vesting/src/mock.rs @@ -21,6 +21,12 @@ parameter_types! { pub type AccountId = u128; +pub const SETR: CurrencyId = CurrencyId::Token(TokenSymbol::SETR); +pub const SETUSD: CurrencyId = CurrencyId::Token(TokenSymbol::SETUSD); +pub const SETM: CurrencyId = CurrencyId::Token(TokenSymbol::SETM); +pub const SERP: CurrencyId = CurrencyId::Token(TokenSymbol::SERP); +pub const DNAR: CurrencyId = CurrencyId::Token(TokenSymbol::DNAR); + impl frame_system::Config for Runtime { type Origin = Origin; type Call = Call; @@ -84,18 +90,70 @@ impl EnsureOrigin for EnsureAliceOrBob { } } +parameter_type_with_key! { + pub ExistentialDeposits: |_currency_id: CurrencyId| -> Balance { + Default::default() + }; +} + +impl orml_tokens::Config for Runtime { + type Event = Event; + type Balance = Balance; + type Amount = Amount; + type CurrencyId = CurrencyId; + type WeightInfo = (); + type ExistentialDeposits = ExistentialDeposits; + type OnDust = (); + type MaxLocks = MaxLocks; + type DustRemovalWhitelist = (); +} + parameter_types! { - pub const MaxVestingSchedule: u32 = 2; + pub StableCurrencyIds: Vec = vec![ + SETR, + SETUSD, + ]; + pub const SetterCurrencyId: CurrencyId = SETR; // Setter currency ticker is SETR/ + pub const GetSetUSDId: CurrencyId = SETUSD; // SetDollar currency ticker is SETUSD/ + pub const GetNativeCurrencyId: CurrencyId = SETM; // Setheum native currency ticker is SETM/ + pub const GetSerpCurrencyId: CurrencyId = SERP; // Setheum native currency ticker is SETM/ + pub const GetDinarCurrencyId: CurrencyId = DNAR; // Setheum native currency ticker is SETM/ + pub static MockBlockNumberProvider: u64 = 0; +} + +impl BlockNumberProvider for MockBlockNumberProvider { + type BlockNumber = u64; + + fn current_block_number() -> Self::BlockNumber { + Self::get() + } +} + +parameter_types! { + pub const MaxNativeVestingSchedules: u32 = 2; + pub const MaxSerpVestingSchedules: u32 = 2; + pub const MaxDinarVestingSchedules: u32 = 2; + pub const MaxSetterVestingSchedules: u32 = 2; + pub const MaxSetUSDVestingSchedules: u32 = 2; pub const MinVestedTransfer: u64 = 5; } impl Config for Runtime { type Event = Event; - type Currency = PalletBalances; + type MultiCurrency = Tokens; + type GetNativeCurrencyId = GetNativeCurrencyId; + type GetSerpCurrencyId = GetSerpCurrencyId; + type GetDinarCurrencyId = GetDinarCurrencyId; + type SetterCurrencyId = SetterCurrencyId; + type GetSetUSDId = GetSetUSDId; type MinVestedTransfer = MinVestedTransfer; type VestedTransferOrigin = EnsureAliceOrBob; type WeightInfo = (); - type MaxVestingSchedules = MaxVestingSchedule; + type MaxNativeVestingSchedules = MaxNativeVestingSchedules; + type MaxSerpVestingSchedules = MaxSerpVestingSchedules; + type MaxDinarVestingSchedules = MaxDinarVestingSchedules; + type MaxSetterVestingSchedules = MaxSetterVestingSchedules; + type MaxSetUSDVestingSchedules = MaxSetUSDVestingSchedules; } type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; @@ -110,6 +168,7 @@ construct_runtime!( System: frame_system::{Pallet, Call, Storage, Config, Event}, Vesting: vesting::{Pallet, Storage, Call, Event, Config}, PalletBalances: pallet_balances::{Pallet, Call, Storage, Config, Event}, + Tokens: orml_tokens::{Pallet, Storage, Event, Config} } ); @@ -117,27 +176,48 @@ pub const ALICE: AccountId = 1; pub const BOB: AccountId = 2; pub const CHARLIE: AccountId = 3; -#[derive(Default)] -pub struct ExtBuilder; +pub struct ExtBuilder { + balances: Vec<(AccountId, CurrencyId, Balance)>, +} + +impl Default for ExtBuilder { + fn default() -> Self { + Self { + balances: vec![ + (ALICE, SETM, 10000), + (ALICE, SERP, 1000), + (ALICE, DNAR, 1000), + (ALICE, SETR, 1000), + (ALICE, SETUSD, 1000), + (CHARLIE, SETM, 10000), + (CHARLIE, SERP, 1000), + (CHARLIE, DNAR, 1000), + (CHARLIE, SETR, 1000), + (CHARLIE, SETUSD, 1000) + ], + } + } +} impl ExtBuilder { - pub fn build() -> sp_io::TestExternalities { + pub fn build(self) -> sp_io::TestExternalities { let mut t = frame_system::GenesisConfig::default() .build_storage::() .unwrap(); - pallet_balances::GenesisConfig:: { - balances: vec![(ALICE, 100), (CHARLIE, 30)], + orml_tokens::GenesisConfig:: { + balances: self.balances, } .assimilate_storage(&mut t) .unwrap(); vesting::GenesisConfig:: { - vesting: vec![(CHARLIE, 2, 3, 4, 5)], // who, start, period, period_count, per_period + // who, start, period, period_count, per_period + vesting: vec![(CHARLIE, SETM, 2, 3, 4, 5)], } .assimilate_storage(&mut t) .unwrap(); t.into() } -} +} \ No newline at end of file diff --git a/lib-serml/vesting/src/tests.rs b/lib-serml/vesting/src/tests.rs index 070176eb4..d73178c32 100644 --- a/lib-serml/vesting/src/tests.rs +++ b/lib-serml/vesting/src/tests.rs @@ -4,22 +4,19 @@ use super::*; use frame_support::{assert_noop, assert_ok, error::BadOrigin}; -use mock::{Event, *}; -use pallet_balances::{BalanceLock, Reasons}; +use mock::{Event, SETM, *}; #[test] fn vesting_from_chain_spec_works() { - ExtBuilder::build().execute_with(|| { - assert_ok!(PalletBalances::ensure_can_withdraw( + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Tokens::ensure_can_withdraw( + SETM, &CHARLIE, - 10, - WithdrawReasons::TRANSFER, - 20 + 10 )); - assert!(PalletBalances::ensure_can_withdraw(&CHARLIE, 11, WithdrawReasons::TRANSFER, 19).is_err()); assert_eq!( - Vesting::vesting_schedules(&CHARLIE), + Vesting::native_vesting_schedules(&CHARLIE), vec![VestingSchedule { start: 2u64, period: 3u64, @@ -30,32 +27,29 @@ fn vesting_from_chain_spec_works() { System::set_block_number(13); - assert_ok!(Vesting::claim(Origin::signed(CHARLIE))); + assert_ok!(Vesting::claim(Origin::signed(CHARLIE), SETM)); - assert_ok!(PalletBalances::ensure_can_withdraw( + assert_ok!(Tokens::ensure_can_withdraw( + SETM, &CHARLIE, - 25, - WithdrawReasons::TRANSFER, - 5 + 25 )); - assert!(PalletBalances::ensure_can_withdraw(&CHARLIE, 26, WithdrawReasons::TRANSFER, 4).is_err()); System::set_block_number(14); - assert_ok!(Vesting::claim(Origin::signed(CHARLIE))); + assert_ok!(Vesting::claim(Origin::signed(CHARLIE), SETM)); - assert_ok!(PalletBalances::ensure_can_withdraw( + assert_ok!(Tokens::ensure_can_withdraw( + SETM, &CHARLIE, - 30, - WithdrawReasons::TRANSFER, - 0 + 30 )); }); } #[test] fn vested_transfer_works() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build().execute_with(|| { System::set_block_number(1); let schedule = VestingSchedule { @@ -64,22 +58,22 @@ fn vested_transfer_works() { period_count: 1u32, per_period: 100u64, }; - assert_ok!(Vesting::vested_transfer(Origin::signed(ALICE), BOB, schedule.clone())); - assert_eq!(Vesting::vesting_schedules(&BOB), vec![schedule.clone()]); - System::assert_last_event(Event::Vesting(crate::Event::VestingScheduleAdded(ALICE, BOB, schedule))); + assert_ok!(Vesting::vested_transfer(Origin::signed(ALICE), SETM, BOB, schedule.clone())); + assert_eq!(Vesting::native_vesting_schedules(&BOB), vec![schedule.clone()]); + System::assert_last_event(Event::Vesting(crate::Event::VestingScheduleAdded(SETM, ALICE, BOB, schedule))); }); } #[test] fn add_new_vesting_schedule_merges_with_current_locked_balance_and_until() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build().execute_with(|| { let schedule = VestingSchedule { start: 0u64, period: 10u64, period_count: 2u32, per_period: 10u64, }; - assert_ok!(Vesting::vested_transfer(Origin::signed(ALICE), BOB, schedule)); + assert_ok!(Vesting::vested_transfer(Origin::signed(ALICE), SETM, BOB, schedule)); System::set_block_number(12); @@ -89,36 +83,27 @@ fn add_new_vesting_schedule_merges_with_current_locked_balance_and_until() { period_count: 1u32, per_period: 7u64, }; - assert_ok!(Vesting::vested_transfer(Origin::signed(ALICE), BOB, another_schedule)); - - assert_eq!( - PalletBalances::locks(&BOB).get(0), - Some(&BalanceLock { - id: VESTING_LOCK_ID, - amount: 17u64, - reasons: Reasons::All, - }) - ); + assert_ok!(Vesting::vested_transfer(Origin::signed(ALICE), SETM, BOB, another_schedule)); }); } #[test] fn cannot_use_fund_if_not_claimed() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build().execute_with(|| { let schedule = VestingSchedule { start: 10u64, period: 10u64, period_count: 1u32, per_period: 50u64, }; - assert_ok!(Vesting::vested_transfer(Origin::signed(ALICE), BOB, schedule)); - assert!(PalletBalances::ensure_can_withdraw(&BOB, 1, WithdrawReasons::TRANSFER, 49).is_err()); + assert_ok!(Vesting::vested_transfer(Origin::signed(ALICE), SETM, BOB, schedule)); + assert!(Tokens::ensure_can_withdraw(SETM, &BOB, 1).is_err()); }); } #[test] fn vested_transfer_fails_if_zero_period_or_count() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build().execute_with(|| { let schedule = VestingSchedule { start: 1u64, period: 0u64, @@ -126,7 +111,7 @@ fn vested_transfer_fails_if_zero_period_or_count() { per_period: 100u64, }; assert_noop!( - Vesting::vested_transfer(Origin::signed(ALICE), BOB, schedule), + Vesting::vested_transfer(Origin::signed(ALICE), SETM, BOB, schedule), Error::::ZeroVestingPeriod ); @@ -137,31 +122,15 @@ fn vested_transfer_fails_if_zero_period_or_count() { per_period: 100u64, }; assert_noop!( - Vesting::vested_transfer(Origin::signed(ALICE), BOB, schedule), + Vesting::vested_transfer(Origin::signed(ALICE), SETM, BOB, schedule), Error::::ZeroVestingPeriodCount ); }); } -#[test] -fn vested_transfer_fails_if_transfer_err() { - ExtBuilder::build().execute_with(|| { - let schedule = VestingSchedule { - start: 1u64, - period: 1u64, - period_count: 1u32, - per_period: 100u64, - }; - assert_noop!( - Vesting::vested_transfer(Origin::signed(BOB), ALICE, schedule), - pallet_balances::Error::::InsufficientBalance, - ); - }); -} - #[test] fn vested_transfer_fails_if_overflow() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build().execute_with(|| { let schedule = VestingSchedule { start: 1u64, period: 1u64, @@ -169,7 +138,7 @@ fn vested_transfer_fails_if_overflow() { per_period: u64::MAX, }; assert_noop!( - Vesting::vested_transfer(Origin::signed(ALICE), BOB, schedule), + Vesting::vested_transfer(Origin::signed(ALICE), SETM, BOB, schedule), ArithmeticError::Overflow, ); @@ -180,7 +149,7 @@ fn vested_transfer_fails_if_overflow() { per_period: 1u64, }; assert_noop!( - Vesting::vested_transfer(Origin::signed(ALICE), BOB, another_schedule), + Vesting::vested_transfer(Origin::signed(ALICE), SETM, BOB, another_schedule), ArithmeticError::Overflow, ); }); @@ -188,7 +157,7 @@ fn vested_transfer_fails_if_overflow() { #[test] fn vested_transfer_fails_if_bad_origin() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build().execute_with(|| { let schedule = VestingSchedule { start: 0u64, period: 10u64, @@ -196,7 +165,7 @@ fn vested_transfer_fails_if_bad_origin() { per_period: 100u64, }; assert_noop!( - Vesting::vested_transfer(Origin::signed(CHARLIE), BOB, schedule), + Vesting::vested_transfer(Origin::signed(CHARLIE), SETM, BOB, schedule), BadOrigin ); }); @@ -204,31 +173,32 @@ fn vested_transfer_fails_if_bad_origin() { #[test] fn claim_works() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build().execute_with(|| { let schedule = VestingSchedule { start: 0u64, period: 10u64, period_count: 2u32, per_period: 10u64, }; - assert_ok!(Vesting::vested_transfer(Origin::signed(ALICE), BOB, schedule)); + assert_ok!(Vesting::vested_transfer(Origin::signed(ALICE), SETM, BOB, schedule)); System::set_block_number(11); // remain locked if not claimed - assert!(PalletBalances::transfer(Origin::signed(BOB), ALICE, 10).is_err()); + assert!(Tokens::transfer(Origin::signed(BOB), ALICE, SETM, 10).is_err()); // unlocked after claiming - assert_ok!(Vesting::claim(Origin::signed(BOB))); - assert!(VestingSchedules::::contains_key(BOB)); - assert_ok!(PalletBalances::transfer(Origin::signed(BOB), ALICE, 10)); + assert_ok!(Vesting::claim(Origin::signed(BOB), SETM)); + assert!(NativeVestingSchedules::::contains_key(BOB)); + assert_ok!(Tokens::transfer(Origin::signed(BOB), ALICE, SETM, 10)); // more are still locked - assert!(PalletBalances::transfer(Origin::signed(BOB), ALICE, 1).is_err()); + assert!(Tokens::transfer(Origin::signed(BOB), ALICE, SETM, 1).is_err()); System::set_block_number(21); // claim more - assert_ok!(Vesting::claim(Origin::signed(BOB))); - assert!(!VestingSchedules::::contains_key(BOB)); - assert_ok!(PalletBalances::transfer(Origin::signed(BOB), ALICE, 10)); + assert_ok!(Vesting::claim(Origin::signed(BOB), SETM)); + assert!(!NativeVestingSchedules::::contains_key(BOB)); + assert_ok!(Tokens::transfer(Origin::signed(BOB), ALICE, SETM, 10)); // all used up + assert_eq!(Tokens::free_balance(SETM, &BOB), 0); assert_eq!(PalletBalances::free_balance(BOB), 0); // no locks anymore @@ -238,47 +208,39 @@ fn claim_works() { #[test] fn claim_for_works() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build().execute_with(|| { let schedule = VestingSchedule { start: 0u64, period: 10u64, period_count: 2u32, per_period: 10u64, }; - assert_ok!(Vesting::vested_transfer(Origin::signed(ALICE), BOB, schedule)); + assert_ok!(Vesting::vested_transfer(Origin::signed(ALICE), SETM, BOB, schedule)); - assert_ok!(Vesting::claim_for(Origin::signed(ALICE), BOB)); + assert_ok!(Vesting::claim_for(Origin::signed(ALICE), SETM, BOB)); - assert_eq!( - PalletBalances::locks(&BOB).get(0), - Some(&BalanceLock { - id: VESTING_LOCK_ID, - amount: 20u64, - reasons: Reasons::All, - }) - ); - assert!(VestingSchedules::::contains_key(&BOB)); + assert!(NativeVestingSchedules::::contains_key(&BOB)); System::set_block_number(21); - assert_ok!(Vesting::claim_for(Origin::signed(ALICE), BOB)); + assert_ok!(Vesting::claim_for(Origin::signed(ALICE), SETM, BOB)); // no locks anymore assert_eq!(PalletBalances::locks(&BOB), vec![]); - assert!(!VestingSchedules::::contains_key(&BOB)); + assert!(!NativeVestingSchedules::::contains_key(&BOB)); }); } #[test] fn update_vesting_schedules_works() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build().execute_with(|| { let schedule = VestingSchedule { start: 0u64, period: 10u64, period_count: 2u32, per_period: 10u64, }; - assert_ok!(Vesting::vested_transfer(Origin::signed(ALICE), BOB, schedule)); + assert_ok!(Vesting::vested_transfer(Origin::signed(ALICE), SETM, BOB, schedule)); let updated_schedule = VestingSchedule { start: 0u64, @@ -288,45 +250,39 @@ fn update_vesting_schedules_works() { }; assert_ok!(Vesting::update_vesting_schedules( Origin::root(), + SETM, BOB, vec![updated_schedule] )); System::set_block_number(11); - assert_ok!(Vesting::claim(Origin::signed(BOB))); - assert!(PalletBalances::transfer(Origin::signed(BOB), ALICE, 1).is_err()); + assert_ok!(Vesting::claim(Origin::signed(BOB), SETM)); + assert!(Tokens::transfer(Origin::signed(BOB), ALICE, SETM, 1).is_err()); System::set_block_number(21); - assert_ok!(Vesting::claim(Origin::signed(BOB))); - assert_ok!(PalletBalances::transfer(Origin::signed(BOB), ALICE, 10)); + assert_ok!(Vesting::claim(Origin::signed(BOB), SETM)); + assert_ok!(Tokens::transfer(Origin::signed(BOB), ALICE, SETM, 10)); // empty vesting schedules cleanup the storage and unlock the fund - assert!(VestingSchedules::::contains_key(BOB)); - assert_eq!( - PalletBalances::locks(&BOB).get(0), - Some(&BalanceLock { - id: VESTING_LOCK_ID, - amount: 10u64, - reasons: Reasons::All, - }) - ); - assert_ok!(Vesting::update_vesting_schedules(Origin::root(), BOB, vec![])); - assert!(!VestingSchedules::::contains_key(BOB)); + assert!(NativeVestingSchedules::::contains_key(BOB)); + + assert_ok!(Vesting::update_vesting_schedules(Origin::root(), SETM, BOB, vec![])); + assert!(!NativeVestingSchedules::::contains_key(BOB)); assert_eq!(PalletBalances::locks(&BOB), vec![]); }); } #[test] fn update_vesting_schedules_fails_if_unexpected_existing_locks() { - ExtBuilder::build().execute_with(|| { - assert_ok!(PalletBalances::transfer(Origin::signed(ALICE), BOB, 1)); - PalletBalances::set_lock(*b"prelocks", &BOB, 0u64, WithdrawReasons::all()); + ExtBuilder::default().build().execute_with(|| { + assert_ok!(Tokens::transfer(Origin::signed(ALICE), BOB, SETM, 1)); + Tokens::set_lock(*b"prelocks", SETM, &BOB, 0u64); }); } #[test] fn vested_transfer_check_for_min() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build().execute_with(|| { let schedule = VestingSchedule { start: 1u64, period: 1u64, @@ -334,7 +290,7 @@ fn vested_transfer_check_for_min() { per_period: 3u64, }; assert_noop!( - Vesting::vested_transfer(Origin::signed(BOB), ALICE, schedule), + Vesting::vested_transfer(Origin::signed(BOB), SETM, ALICE, schedule), Error::::AmountLow ); }); @@ -342,14 +298,14 @@ fn vested_transfer_check_for_min() { #[test] fn multiple_vesting_schedule_claim_works() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build().execute_with(|| { let schedule = VestingSchedule { start: 0u64, period: 10u64, period_count: 2u32, per_period: 10u64, }; - assert_ok!(Vesting::vested_transfer(Origin::signed(ALICE), BOB, schedule.clone())); + assert_ok!(Vesting::vested_transfer(Origin::signed(ALICE), SETM, BOB, schedule.clone())); let schedule2 = VestingSchedule { start: 0u64, @@ -357,21 +313,21 @@ fn multiple_vesting_schedule_claim_works() { period_count: 3u32, per_period: 10u64, }; - assert_ok!(Vesting::vested_transfer(Origin::signed(ALICE), BOB, schedule2.clone())); + assert_ok!(Vesting::vested_transfer(Origin::signed(ALICE), SETM, BOB, schedule2.clone())); - assert_eq!(Vesting::vesting_schedules(&BOB), vec![schedule, schedule2.clone()]); + assert_eq!(Vesting::native_vesting_schedules(&BOB), vec![schedule, schedule2.clone()]); System::set_block_number(21); - assert_ok!(Vesting::claim(Origin::signed(BOB))); + assert_ok!(Vesting::claim(Origin::signed(BOB), SETM)); - assert_eq!(Vesting::vesting_schedules(&BOB), vec![schedule2]); + assert_eq!(Vesting::native_vesting_schedules(&BOB), vec![schedule2]); System::set_block_number(31); - assert_ok!(Vesting::claim(Origin::signed(BOB))); + assert_ok!(Vesting::claim(Origin::signed(BOB), SETM)); - assert!(!VestingSchedules::::contains_key(&BOB)); + assert!(!NativeVestingSchedules::::contains_key(&BOB)); assert_eq!(PalletBalances::locks(&BOB), vec![]); }); @@ -379,25 +335,25 @@ fn multiple_vesting_schedule_claim_works() { #[test] fn exceeding_maximum_schedules_should_fail() { - ExtBuilder::build().execute_with(|| { + ExtBuilder::default().build().execute_with(|| { let schedule = VestingSchedule { start: 0u64, period: 10u64, period_count: 2u32, per_period: 10u64, }; - assert_ok!(Vesting::vested_transfer(Origin::signed(ALICE), BOB, schedule.clone())); - assert_ok!(Vesting::vested_transfer(Origin::signed(ALICE), BOB, schedule.clone())); + assert_ok!(Vesting::vested_transfer(Origin::signed(ALICE), SETM, BOB, schedule.clone())); + assert_ok!(Vesting::vested_transfer(Origin::signed(ALICE), SETM, BOB, schedule.clone())); assert_noop!( - Vesting::vested_transfer(Origin::signed(ALICE), BOB, schedule.clone()), + Vesting::vested_transfer(Origin::signed(ALICE), SETM, BOB, schedule.clone()), Error::::MaxVestingSchedulesExceeded ); let schedules = vec![schedule.clone(), schedule.clone(), schedule]; assert_noop!( - Vesting::update_vesting_schedules(Origin::root(), BOB, schedules), + Vesting::update_vesting_schedules(Origin::root(), SETM, BOB, schedules), Error::::MaxVestingSchedulesExceeded ); }); -} +} \ No newline at end of file diff --git a/resources/types.json b/resources/types.json index d7b2e6e75..45b22f2de 100644 --- a/resources/types.json +++ b/resources/types.json @@ -56,6 +56,13 @@ "AmountOf": "Amount", "AuctionId": "u32", "AuctionIdOf": "AuctionId", + "VestingSchedule": { + "start": "BlockNumber", + "period": "BlockNumber", + "periodCount": "u32", + "perPeriod": "Compact" + }, + "VestingScheduleOf": "VestingSchedule", "TokenSymbol": { "_enum": { "SETM": 0, diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index e89a02542..5bd190158 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -938,14 +938,13 @@ pub struct DealWithFees; impl OnUnbalanced for DealWithFees { fn on_unbalanceds(mut fees_then_tips: impl Iterator) { if let Some(fees) = fees_then_tips.next() { - // for fees, 80% to treasury, 20% to author - let mut split = fees.ration(80, 20); + // for fees, 50% to treasury, 50% burn + let mut split = fees.ration(50, 50); if let Some(tips) = fees_then_tips.next() { - // for tips, if any, 70% to treasury, 30% to author (though this can be anything) - tips.ration_merge_into(70, 30, &mut split); + // for tips, if any, 50% to treasury, 50% burn (though this can be anything) + tips.ration_merge_into(50, 50, &mut split); } Treasury::on_unbalanced(split.0); - Balances::resolve_creating(&Authorship::author(), split.1); } } } @@ -1202,14 +1201,27 @@ impl pallet_balances::Config for Runtime { parameter_types! { pub MinVestedTransfer: Balance = 0; - pub const MaxVestingSchedules: u32 = 500; + pub const MaxNativeVestingSchedules: u32 = 70; + pub const MaxSerpVestingSchedules: u32 = 70; + pub const MaxDinarVestingSchedules: u32 = 70; + pub const MaxSetterVestingSchedules: u32 = 70; + pub const MaxSetUSDVestingSchedules: u32 = 70; } impl module_vesting::Config for Runtime { type Event = Event; - type Currency = pallet_balances::Pallet; + type MultiCurrency = Currencies; + type GetNativeCurrencyId = GetNativeCurrencyId; + type GetSerpCurrencyId = GetSerpCurrencyId; + type GetDinarCurrencyId = GetDinarCurrencyId; + type SetterCurrencyId = SetterCurrencyId; + type GetSetUSDId = GetSetUSDId; type MinVestedTransfer = MinVestedTransfer; - type MaxVestingSchedules = MaxVestingSchedules; + type MaxNativeVestingSchedules = MaxNativeVestingSchedules; + type MaxSerpVestingSchedules = MaxSerpVestingSchedules; + type MaxDinarVestingSchedules = MaxDinarVestingSchedules; + type MaxSetterVestingSchedules = MaxSetterVestingSchedules; + type MaxSetUSDVestingSchedules = MaxSetUSDVestingSchedules; type VestedTransferOrigin = EnsureWeb3SettersClub; type WeightInfo = weights::module_vesting::WeightInfo; } @@ -2037,7 +2049,7 @@ impl_runtime_apis! { orml_list_benchmark!(list, extra, module_prices, benchmarking::prices); // orml_list_benchmark!(list, extra, module_evm_accounts, benchmarking::evm_accounts); orml_list_benchmark!(list, extra, module_currencies, benchmarking::currencies); - orml_list_benchmark!(list, extra, module_vesting, benchmarking::vesting); + // orml_list_benchmark!(list, extra, module_vesting, benchmarking::vesting); orml_list_benchmark!(list, extra, orml_tokens, benchmarking::tokens); orml_list_benchmark!(list, extra, orml_auction, benchmarking::auction); @@ -2097,7 +2109,7 @@ impl_runtime_apis! { orml_add_benchmark!(params, batches, orml_tokens, benchmarking::tokens); orml_add_benchmark!(params, batches, orml_auction, benchmarking::auction); - orml_add_benchmark!(params, batches, module_vesting, benchmarking::vesting); + // orml_add_benchmark!(params, batches, module_vesting, benchmarking::vesting); orml_add_benchmark!(params, batches, orml_authority, benchmarking::authority); orml_add_benchmark!(params, batches, orml_oracle, benchmarking::oracle); @@ -2106,4 +2118,4 @@ impl_runtime_apis! { Ok(batches) } } -} +} \ No newline at end of file