diff --git a/blockchain/modules/vesting/Cargo.toml b/blockchain/modules/vesting/Cargo.toml index b893ef25..29a6539a 100644 --- a/blockchain/modules/vesting/Cargo.toml +++ b/blockchain/modules/vesting/Cargo.toml @@ -1,33 +1,35 @@ [package] name = "module-vesting" description = "Provides scheduled balance locking mechanism, in a *graded vesting* way." -version = "1.0.0" +version = "0.9.81" authors = ["Setheum Labs"] -edition = "2018" +edition = "2021" [dependencies] -serde = { version = "1.0.124", optional = true } -codec = { package = "parity-scale-codec", version = "2.2.0", default-features = false, features = ["max-encoded-len"] } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.10", default-features = false } -sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.10", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.10", default-features = false } -frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.10", default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.10", default-features = false } +scale-info = { workspace = true } +serde = { workspace = true, optional = true } +parity-scale-codec = { version = "3.0.0", default-features = false, features = ["max-encoded-len"] } +sp-runtime = { workspace = true } +sp-io = { workspace = true } +sp-std = { workspace = true } +frame-support = { workspace = true } +frame-system = { workspace = true } primitives = { package = "setheum-primitives", path = "../primitives", default-features = false } support = { package = "module-support", path = "../support", default-features = false } orml-traits = { path = "../submodules/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 = "../submodules/orml/tokens" } +sp-core = { workspace = true, features = ["std"] } +pallet-balances = { workspace = true } +orml-tokens = { workspace = true } [features] default = ["std"] std = [ + "scale-info/std", "serde", - "codec/std", + "parity-scale-codec/std", "sp-runtime/std", "sp-std/std", "sp-io/std", @@ -40,4 +42,10 @@ std = [ runtime-benchmarks = [ "frame-support/runtime-benchmarks", "frame-system/runtime-benchmarks", -] \ No newline at end of file + "sp-runtime/runtime-benchmarks", +] +try-runtime = [ + "frame-support/try-runtime", + "frame-system/try-runtime", + "sp-runtime/try-runtime", +] diff --git a/blockchain/modules/vesting/README.md b/blockchain/modules/vesting/README.md index 425eb1d7..7b9d4407 100644 --- a/blockchain/modules/vesting/README.md +++ b/blockchain/modules/vesting/README.md @@ -2,8 +2,12 @@ ## Overview -Vesting module provides a means of scheduled balance lock on an account. It uses the *graded vesting* way, which unlocks a specific amount of balance every period of time, until all balance unlocked. +Vesting module provides a means of scheduled balance lock on an account. It uses the *graded vesting* way, which unlocks a specific amount of balance every period of time, until all balance unlocked. The `NativeCurrencyId` (SEE) and `EDFCurrencyId` (EDF) are both supported in this module. ### Vesting Schedule The schedule of a vesting is described by data structure `VestingSchedule`: from the block number of `start`, of `currency_id`, for every `period` amount of blocks, `per_period` amount of balance would unlocked, until number of periods `period_count` reached. Note in vesting schedules, *time* is measured by block number. All `VestingSchedule`s under an account could be queried in chain state. + +### Locks + +The implementation uses locks which allow tokens to be locked by other pallets that's also using locks, for example, the conviction-voting pallet. diff --git a/blockchain/modules/vesting/src/lib.rs b/blockchain/modules/vesting/src/lib.rs index 6879df92..1f7342e6 100644 --- a/blockchain/modules/vesting/src/lib.rs +++ b/blockchain/modules/vesting/src/lib.rs @@ -47,23 +47,24 @@ #![cfg_attr(not(feature = "std"), no_std)] #![allow(clippy::unused_unit)] -use codec::{HasCompact, MaxEncodedLen}; use frame_support::{ ensure, pallet_prelude::*, - traits::{EnsureOrigin, Get}, - transactional, BoundedVec, + traits::{Currency, EnsureOrigin, ExistenceRequirement, Get, LockIdentifier, LockableCurrency, WithdrawReasons}, + BoundedVec, }; -use frame_system::{ensure_signed, pallet_prelude::*}; +use frame_system::{ensure_root, ensure_signed, pallet_prelude::*}; +use parity_scale_codec::{HasCompact, MaxEncodedLen}; +use scale_info::TypeInfo; use sp_runtime::{ traits::{AtLeast32Bit, BlockNumberProvider, CheckedAdd, Saturating, StaticLookup, Zero}, ArithmeticError, DispatchResult, RuntimeDebug, }; use sp_std::{ cmp::{Eq, PartialEq}, - convert::TryInto, vec::Vec, -};use orml_traits::{ +}; +use orml_traits::{ LockIdentifier, MultiCurrency, MultiLockableCurrency, }; use primitives::CurrencyId; @@ -75,14 +76,14 @@ mod weights; pub use module::*; pub use weights::WeightInfo; -pub const VESTING_LOCK_ID: LockIdentifier = *b"set/vest"; +pub const VESTING_LOCK_ID: LockIdentifier = *b"setvest"; /// The vesting schedule. /// /// Benefits would be granted gradually, `per_period` amount every `period` /// of blocks after `start`. -#[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug, MaxEncodedLen)] -pub struct VestingSchedule { +#[derive(Clone, Encode, Decode, PartialEq, Eq, RuntimeDebug, MaxEncodedLen, TypeInfo)] +pub struct VestingSchedule { /// Vesting starting block pub start: BlockNumber, /// Number of blocks between vest @@ -94,7 +95,9 @@ pub struct VestingSchedule { pub per_period: Balance, } -impl VestingSchedule { +impl + VestingSchedule +{ /// Returns the end of all periods, `None` if calculation overflows. pub fn end(&self) -> Option { // period * period_count + start @@ -135,61 +138,40 @@ pub mod module { <::MultiCurrency as MultiCurrency<::AccountId>>::Balance; pub(crate) type CurrencyIdOf = <::MultiCurrency as MultiCurrency<::AccountId>>::CurrencyId; - pub(crate) type VestingScheduleOf = VestingSchedule<::BlockNumber, BalanceOf>; + pub(crate) type VestingScheduleOf = VestingSchedule, BalanceOf>; pub type ScheduledItem = ( ::AccountId, CurrencyIdOf, - ::BlockNumber, - ::BlockNumber, + BlockNumberFor, + BlockNumberFor, u32, BalanceOf, ); #[pallet::config] pub trait Config: frame_system::Config { - type Event: From> + IsType<::Event>; - - type MultiCurrency: MultiLockableCurrency; + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + type MultiCurrency: MultiLockableCurrency>; + #[pallet::constant] - /// Native Setheum (SEE) currency id. [P]Pronounced "set M" or "setem" - /// + /// Native Setheum (SEE) currency id. type GetNativeCurrencyId: Get; #[pallet::constant] - /// Serp (SERP) currency id. - /// - type GetSerpCurrencyId: Get; - - #[pallet::constant] - /// The Dinar (DNAR) currency id. - /// - type GetDinarCurrencyId: Get; - - #[pallet::constant] - /// HighEnd LaunchPad (HELP) currency id. (LaunchPad Token) - /// - type GetHelpCurrencyId: Get; - - #[pallet::constant] - /// Setter (SETR) currency id - /// - type SetterCurrencyId: Get; + /// Ethical DeFi (EDF) currency id. + type GetEDFCurrencyId: Get; #[pallet::constant] - /// The SetDollar (SETUSD) currency id - type GetSetUSDId: Get; + /// The minimum amount of SEE transferred to call `vested_transfer`. + type MinNativeVestedTransfer: Get>; #[pallet::constant] - /// The minimum amount transferred to call `vested_transfer`. - type MinVestedTransfer: Get>; + /// The minimum amount of EDF transferred to call `vested_transfer`. + type MinEDFVestedTransfer: Get>; - /// SetheumTreasury account. For Vested Transfer - #[pallet::constant] - type TreasuryAccount: Get; - - /// The origin which may update inflation related params - type UpdateOrigin: EnsureOrigin; + /// Required origin for vested transfer. + type VestedTransferOrigin: EnsureOrigin; /// Weight information for extrinsics in this module. type WeightInfo: WeightInfo; @@ -197,20 +179,11 @@ pub mod module { /// The maximum vesting schedules for SEE 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 HELP - type MaxHelpVestingSchedules: Get; + /// The maximum vesting schedules for EDF + type MaxEDFVestingSchedules: Get; - /// The maximum vesting schedules for SETR - type MaxSetterVestingSchedules: Get; - - /// The maximum vesting schedules for SETUSD - type MaxSetUSDVestingSchedules: Get; + // The block number provider + type BlockNumberProvider: BlockNumberProvider>; } #[pallet::error] @@ -225,23 +198,29 @@ pub mod module { TooManyVestingSchedules, /// The vested transfer amount is too low AmountLow, - /// Failed because the maximum vesting schedules was exceeded - MaxVestingSchedulesExceeded, + /// Failed because the maximum vesting schedules for SEE was exceeded + MaxNativeVestingSchedulesExceeded, + /// Failed because the maximum vesting schedules for EDF was exceeded + MaxEDFVestingSchedulesExceeded, } #[pallet::event] #[pallet::generate_deposit(fn deposit_event)] - #[pallet::metadata(T::AccountId = "AccountId", VestingScheduleOf = "VestingScheduleOf", BalanceOf = "Balance")] pub enum Event { - /// 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), + /// Added new vesting schedule. + VestingScheduleAdded { + currency_id: CurrencyIdOf, + from: T::AccountId, + to: T::AccountId, + vesting_schedule: VestingScheduleOf, + }, + /// Claimed vesting. + Claimed { currency_id: CurrencyIdOf, who: T::AccountId, amount: BalanceOf }, + /// Updated vesting schedules. + VestingSchedulesUpdated {currency_id: CurrencyIdOf, who: T::AccountId }, } - /// Vesting schedules of an account under SEE currency. + /// Vesting schedules of an account under Native Currency (SEE). /// /// NativeVestingSchedules: map AccountId => Vec #[pallet::storage] @@ -253,210 +232,98 @@ pub mod module { 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 HELP currency. - /// - /// HelpVestingSchedules: map AccountId => Vec - #[pallet::storage] - #[pallet::getter(fn help_vesting_schedules)] - pub type HelpVestingSchedules = StorageMap< - _, - Blake2_128Concat, - T::AccountId, - BoundedVec, T::MaxHelpVestingSchedules>, - ValueQuery, - >; - - /// Vesting schedules of an account under SETR currency. - /// - /// SetterVestingSchedules: map AccountId => Vec - #[pallet::storage] - #[pallet::getter(fn setter_vesting_schedules)] - pub type SetterVestingSchedules = StorageMap< - _, - Blake2_128Concat, - T::AccountId, - BoundedVec, T::MaxSetterVestingSchedules>, - ValueQuery, - >; - - /// Vesting schedules of an account under SETUSD currency. + + /// Vesting schedules of an account under EDF Currency. /// - /// SetUSDVestingSchedules: map AccountId => Vec + /// EDFVestingSchedules: map AccountId => Vec #[pallet::storage] - #[pallet::getter(fn setusd_vesting_schedules)] - pub type SetUSDVestingSchedules = StorageMap< + #[pallet::getter(fn edf_vesting_schedules)] + pub type EDFVestingSchedules = StorageMap< _, Blake2_128Concat, T::AccountId, - BoundedVec, T::MaxSetUSDVestingSchedules>, + BoundedVec, T::MaxEDFVestingSchedules>, ValueQuery, >; + #[pallet::genesis_config] pub struct GenesisConfig { pub vesting: Vec>, } - #[cfg(feature = "std")] impl Default for GenesisConfig { fn default() -> Self { - GenesisConfig { vesting: vec![] } + GenesisConfig { + vesting: Default::default(), + } } } #[pallet::genesis_build] - impl GenesisBuild for GenesisConfig { + impl BuildGenesisConfig for GenesisConfig { fn build(&self) { self.vesting .iter() .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 { + let mut bounded_schedules = VestingSchedules::::get(who); + bounded_schedules + .try_push(VestingSchedule { start: *start, period: *period, period_count: *period_count, per_period: *per_period, - }] - .try_into() + }) .expect("Max vesting schedules exceeded"); - + let total_amount = bounded_schedules + .iter() + .try_fold::<_, _, Result, DispatchError>>(Zero::zero(), |acc_amount, schedule| { + let amount = ensure_valid_vesting_schedule::(T::GetNativeCurrencyId::get(), schedule)?; + acc_amount + .checked_add(&amount) + .ok_or_else(|| ArithmeticError::Overflow.into()) + }) + .expect("Invalid vesting schedule"); + + } + assert!( - T::MultiCurrency::free_balance(T::GetNativeCurrencyId::get(), who) >= total, - "Account do not have enough balance" + T::MultiCurrency::free_balance(T::GetNativeCurrencyId::get(), who) >= total_amount, + "Account does not have enough balance" ); - T::MultiCurrency::set_lock(VESTING_LOCK_ID, T::GetNativeCurrencyId::get(), who, total).unwrap(); - 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" - ); - - T::MultiCurrency::set_lock(VESTING_LOCK_ID, T::GetSerpCurrencyId::get(), who, total).unwrap(); - 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 { + T::MultiCurrency::set_lock(VESTING_LOCK_ID, T::GetNativeCurrencyId::get(), who, total_amount); + NativeVestingSchedules::::insert(who, bounded_schedules); + } else if currency_id == &T::GetEDFCurrencyId::get() { + let mut bounded_schedules = VestingSchedules::::get(who); + bounded_schedules + .try_push(VestingSchedule { start: *start, period: *period, period_count: *period_count, per_period: *per_period, - }] - .try_into() + }) .expect("Max vesting schedules exceeded"); - + let total_amount = bounded_schedules + .iter() + .try_fold::<_, _, Result, DispatchError>>(Zero::zero(), |acc_amount, schedule| { + let amount = ensure_valid_vesting_schedule::(T::GetEDFCurrencyId::get(), schedule)?; + acc_amount + .checked_add(&amount) + .ok_or_else(|| ArithmeticError::Overflow.into()) + }) + .expect("Invalid vesting schedule"); + + } + assert!( - T::MultiCurrency::free_balance(T::GetDinarCurrencyId::get(), who) >= total, - "Account do not have enough balance" + T::MultiCurrency::free_balance(T::GetEDFCurrencyId::get(), who) >= total_amount, + "Account does not have enough balance" ); - - T::MultiCurrency::set_lock(VESTING_LOCK_ID, T::GetDinarCurrencyId::get(), who, total).unwrap(); - DinarVestingSchedules::::insert(who, bounded_schedule); - } else if currency_id == &T::GetHelpCurrencyId::get() { - let total = *per_period * Into::>::into(*period_count); - - let bounded_schedule: BoundedVec, T::MaxHelpVestingSchedules> = - 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::GetHelpCurrencyId::get(), who) >= total, - "Account do not have enough balance" - ); - - T::MultiCurrency::set_lock(VESTING_LOCK_ID, T::GetHelpCurrencyId::get(), who, total).unwrap(); - HelpVestingSchedules::::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" - ); - - T::MultiCurrency::set_lock(VESTING_LOCK_ID, T::SetterCurrencyId::get(), who, total).unwrap(); - 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" - ); - - T::MultiCurrency::set_lock(VESTING_LOCK_ID, T::GetSetUSDId::get(), who, total).unwrap(); - SetUSDVestingSchedules::::insert(who, bounded_schedule); + + T::MultiCurrency::set_lock(VESTING_LOCK_ID, T::GetEDFCurrencyId::get(), who, total_amount); + EDFVestingSchedules::::insert(who, bounded_schedules); } }); } @@ -466,35 +333,54 @@ pub mod module { pub struct Pallet(_); #[pallet::hooks] - impl Hooks for Pallet {} + impl Hooks> for Pallet {} #[pallet::call] impl Pallet { - #[pallet::weight(T::WeightInfo::claim((::MaxNativeVestingSchedules::get() / 2) as u32))] + #[pallet::call_index(0)] + #[pallet::weight(T::WeightInfo::claim(::MaxVestingSchedules::get() / 2))] pub fn claim(origin: OriginFor, currency_id: CurrencyIdOf) -> DispatchResult { let who = ensure_signed(origin)?; let locked_amount = Self::do_claim(currency_id, &who); - Self::deposit_event(Event::Claimed(who, currency_id, locked_amount)); + Self::deposit_event(Event::Claimed { + currency_id, + who, + amount: locked_amount, + }); Ok(()) } + #[pallet::call_index(1)] #[pallet::weight(T::WeightInfo::vested_transfer())] pub fn vested_transfer( origin: OriginFor, currency_id: CurrencyIdOf, dest: ::Source, - schedule: VestingScheduleOf + schedule: VestingScheduleOf, ) -> DispatchResult { - T::UpdateOrigin::ensure_origin(origin)?; - let from = T::TreasuryAccount::get(); + let from = T::VestedTransferOrigin::ensure_origin(origin)?; let to = T::Lookup::lookup(dest)?; + + if to == from { + ensure!( + T::MultiCurrency::free_balance(currency_id, &from) >= schedule.total_amount().ok_or(ArithmeticError::Overflow)?, + Error::::InsufficientBalanceToLock, + ); + } + Self::do_vested_transfer(currency_id, &from, &to, schedule.clone())?; - Self::deposit_event(Event::VestingScheduleAdded(currency_id, from, to, schedule)); + Self::deposit_event(Event::VestingScheduleAdded { + currency_id, + from, + to, + vesting_schedule: schedule, + }); Ok(()) } + #[pallet::call_index(2)] #[pallet::weight(T::WeightInfo::update_vesting_schedules(vesting_schedules.len() as u32))] pub fn update_vesting_schedules( origin: OriginFor, @@ -502,16 +388,17 @@ pub mod module { who: ::Source, vesting_schedules: Vec>, ) -> DispatchResult { - T::UpdateOrigin::ensure_origin(origin)?; + ensure_root(origin)?; let account = T::Lookup::lookup(who)?; Self::do_update_vesting_schedules(currency_id, &account, vesting_schedules)?; - Self::deposit_event(Event::VestingSchedulesUpdated(currency_id, account)); + Self::deposit_event(Event::VestingSchedulesUpdated { currency_id, who: account }); Ok(()) } - #[pallet::weight(T::WeightInfo::claim((::MaxNativeVestingSchedules::get() / 2) as u32))] + #[pallet::call_index(3)] + #[pallet::weight(T::WeightInfo::claim(::MaxVestingSchedules::get() / 2))] pub fn claim_for( origin: OriginFor, currency_id: CurrencyIdOf, @@ -521,60 +408,39 @@ pub mod module { let who = T::Lookup::lookup(dest)?; let locked_amount = Self::do_claim(currency_id, &who); - Self::deposit_event(Event::Claimed(who, currency_id, locked_amount)); + Self::deposit_event(Event::Claimed { + currency_id, + who, + amount: locked_amount, + }); Ok(()) } } } -impl BlockNumberProvider for Pallet { - type BlockNumber = ::BlockNumber; - - fn current_block_number() -> Self::BlockNumber { - >::block_number() - } -} - impl Pallet { fn do_claim(currency_id: CurrencyIdOf, who: &T::AccountId) -> BalanceOf { - let locked = Self::locked_balance(currency_id, who); + let locked = Self::locked_balance(who); if locked.is_zero() { 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() { + T::MultiCurrency::remove_lock(VESTING_LOCK_ID, currency_id, who); + } else if currency_id == T::GetEDFCurrencyId::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::GetHelpCurrencyId::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(); + >::remove(who); + T::MultiCurrency::remove_lock(VESTING_LOCK_ID, currency_id, who); } } else { - T::MultiCurrency::set_lock(VESTING_LOCK_ID, currency_id, who, locked).unwrap(); + T::MultiCurrency::set_lock(VESTING_LOCK_ID, currency_id, who, locked); } locked } /// Returns locked balance based on current block number. fn locked_balance(currency_id: CurrencyIdOf, who: &T::AccountId) -> BalanceOf { - let now = ::current_block_number(); + let now = T::BlockNumberProvider::current_block_number(); 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(); @@ -590,87 +456,10 @@ impl Pallet { 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::GetHelpCurrencyId::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 + total }) - } else if currency_id == T::GetSetUSDId::get() { - // cleanup the storage and unlock the fund - >::mutate_exists(who, |maybe_schedules| { + } else if currency_id == T::GetEDFCurrencyId::get() { + >::mutate_exists(who, |maybe_schedules| { let total = if let Some(schedules) = maybe_schedules.as_mut() { let mut total: BalanceOf = Zero::zero(); schedules.retain(|s| { @@ -685,223 +474,121 @@ impl Pallet { if total.is_zero() { *maybe_schedules = None; } - return total + total }) - } else { - Zero::zero() } } - #[transactional] 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)?; + if currency_id == T::GetNativeCurrencyId::get() { + let schedule_amount = ensure_valid_vesting_schedule::(T::GetNativeCurrencyId::get(), &schedule)?; - let total_amount = Self::locked_balance(currency_id, to) - .checked_add(&schedule_amount) - .ok_or(ArithmeticError::Overflow)?; + let total_amount = Self::locked_balance(T::GetNativeCurrencyId::get(), to) + .checked_add(&schedule_amount) + .ok_or(ArithmeticError::Overflow)?; - 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::GetHelpCurrencyId::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(()) + T::MultiCurrency::transfer(T::GetNativeCurrencyId::get(), from, to, schedule_amount)?; + T::MultiCurrency::set_lock(VESTING_LOCK_ID, T::GetNativeCurrencyId::get(), to, total_amount)?; + >::try_append(to, schedule).map_err(|_| Error::::MaxNativeVestingSchedulesExceeded)?; + } else if currency_id == T::GetEDFCurrencyId::get() { + let schedule_amount = ensure_valid_vesting_schedule::(T::GetEDFCurrencyId::get(), &schedule)?; + + let total_amount = Self::locked_balance(T::GetEDFCurrencyId::get(), to) + .checked_add(&schedule_amount) + .ok_or(ArithmeticError::Overflow)?; + + T::MultiCurrency::transfer(T::GetEDFCurrencyId::get(), from, to, schedule_amount)?; + T::MultiCurrency::set_lock(VESTING_LOCK_ID, T::GetEDFCurrencyId::get(), to, total_amount)?; + >::try_append(to, schedule).map_err(|_| Error::::MaxEDFVestingSchedulesExceeded)?; + } + Ok(()) } fn do_update_vesting_schedules( currency_id: CurrencyIdOf, - who: &T::AccountId, + 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)?; - + .map_err(|_| Error::::MaxNativeVestingSchedulesExceeded)?; + // 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(); + T::MultiCurrency::remove_lock(VESTING_LOCK_ID,T::GetNativeCurrencyId::get(), 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) + let amount = ensure_valid_vesting_schedule::(T::GetNativeCurrencyId::get(), schedule)?; + acc_amount + .checked_add(&amount) + .ok_or_else(|| ArithmeticError::Overflow.into()) })?; ensure!( - T::MultiCurrency::free_balance(currency_id, who) >= total_amount, + T::MultiCurrency::free_balance(T::GetNativeCurrencyId::get(), who) >= total_amount, Error::::InsufficientBalanceToLock, ); - - T::MultiCurrency::set_lock(VESTING_LOCK_ID, currency_id, who, total_amount)?; + + T::MultiCurrency::set_lock(VESTING_LOCK_ID, T::GetNativeCurrencyId::get(), who, total_amount); >::insert(who, bounded_schedules); - } else if currency_id == T::GetSerpCurrencyId::get() { - let bounded_schedules: BoundedVec, T::MaxSerpVestingSchedules> = schedules + } else if currency_id == T::GetEDFCurrencyId::get() { + let bounded_schedules: BoundedVec, T::MaxEDFVestingSchedules> = 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::GetHelpCurrencyId::get() { - let bounded_schedules: BoundedVec, T::MaxHelpVestingSchedules> = 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)?; - + .map_err(|_| Error::::MaxEDFVestingSchedulesExceeded)?; + // 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(); + >::remove(who); + T::MultiCurrency::remove_lock(VESTING_LOCK_ID,T::GetEDFCurrencyId::get(), 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) + let amount = ensure_valid_vesting_schedule::(T::GetEDFCurrencyId::get(), schedule)?; + acc_amount + .checked_add(&amount) + .ok_or_else(|| ArithmeticError::Overflow.into()) })?; ensure!( - T::MultiCurrency::free_balance(currency_id, who) >= total_amount, + T::MultiCurrency::free_balance(T::GetEDFCurrencyId::get(), who) >= total_amount, Error::::InsufficientBalanceToLock, ); - - T::MultiCurrency::set_lock(VESTING_LOCK_ID, currency_id, who, total_amount)?; - >::insert(who, bounded_schedules); - }; + + T::MultiCurrency::set_lock(VESTING_LOCK_ID, T::GetEDFCurrencyId::get(), who, total_amount); + >::insert(who, bounded_schedules); + } Ok(()) } +} - /// Returns `Ok(amount)` if valid schedule, or error. - fn ensure_valid_vesting_schedule(schedule: &VestingScheduleOf) -> Result, DispatchError> { - ensure!(!schedule.period.is_zero(), Error::::ZeroVestingPeriod); - ensure!(!schedule.period_count.is_zero(), Error::::ZeroVestingPeriodCount); - ensure!(schedule.end().is_some(), ArithmeticError::Overflow); - - let total = schedule.total_amount().ok_or(ArithmeticError::Overflow)?; - - ensure!(total >= T::MinVestedTransfer::get(), Error::::AmountLow); - - Ok(total) +/// Returns `Ok(total_total)` if valid schedule, or error. +fn ensure_valid_vesting_schedule( + currency_id: CurrencyIdOf, + schedule: &VestingScheduleOf +) -> Result, DispatchError> { + ensure!(!schedule.period.is_zero(), Error::::ZeroVestingPeriod); + ensure!(!schedule.period_count.is_zero(), Error::::ZeroVestingPeriodCount); + ensure!(schedule.end().is_some(), ArithmeticError::Overflow); + + let total_total = schedule.total_amount().ok_or(ArithmeticError::Overflow)?; + + if currency_id == T::GetNativeCurrencyId::get() { + ensure!(total_total >= T::MinNativeVestedTransfer::get(), Error::::AmountLow); + } else if currency_id == T::GetEDFCurrencyId::get() { + ensure!(total_total >= T::MinEDFVestedTransfer::get(), Error::::AmountLow); } -} \ No newline at end of file + + Ok(total_total) +} diff --git a/blockchain/modules/vesting/src/mock.rs b/blockchain/modules/vesting/src/mock.rs index e4744960..924d6d63 100644 --- a/blockchain/modules/vesting/src/mock.rs +++ b/blockchain/modules/vesting/src/mock.rs @@ -5,46 +5,36 @@ use super::*; use frame_support::{ construct_runtime, parameter_types, - traits::{EnsureOrigin, Everything}, + traits::{ConstU32, ConstU64, EnsureOrigin, Everything, Nothing}, }; use frame_system::RawOrigin; use orml_traits::parameter_type_with_key; use primitives::{Amount, TokenSymbol}; use sp_core::H256; -use sp_runtime::{testing::Header, traits::IdentityLookup}; +use sp_runtime::{traits::IdentityLookup, BuildStorage}; -use crate as vesting; - -parameter_types! { - pub const BlockHashCount: u64 = 250; +mod vesting { + pub use super::super::*; } pub type AccountId = u128; -pub const SETR: CurrencyId = CurrencyId::Token(TokenSymbol::SETR); -pub const SETUSD: CurrencyId = CurrencyId::Token(TokenSymbol::SETUSD); -pub const SEE: CurrencyId = CurrencyId::Token(TokenSymbol::SEE); -pub const SERP: CurrencyId = CurrencyId::Token(TokenSymbol::SERP); -pub const DNAR: CurrencyId = CurrencyId::Token(TokenSymbol::DNAR); -pub const HELP: CurrencyId = CurrencyId::Token(TokenSymbol::HELP); - impl frame_system::Config for Runtime { - type Origin = Origin; - type Call = Call; - type Index = u64; - type BlockNumber = u64; + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type Nonce = u64; type Hash = H256; type Hashing = ::sp_runtime::traits::BlakeTwo256; type AccountId = AccountId; type Lookup = IdentityLookup; - type Header = Header; - type Event = Event; - type BlockHashCount = BlockHashCount; + type Block = Block; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = ConstU64<250>; type BlockWeights = (); type BlockLength = (); type Version = (); type PalletInfo = PalletInfo; - type AccountData = pallet_balances::AccountData; + type AccountData = (); type OnNewAccount = (); type OnKilledAccount = (); type DbWeight = (); @@ -52,138 +42,106 @@ impl frame_system::Config for Runtime { type SystemWeightInfo = (); type SS58Prefix = (); type OnSetCode = (); + type MaxConsumers = ConstU32<16>; } type Balance = u64; -parameter_types! { - pub const ExistentialDeposit: u64 = 1; - pub const MaxLocks: u32 = 100; +parameter_type_with_key! { + pub ExistentialDeposits: |_currency_id: CurrencyId| -> Balance { + Default::default() + }; } -impl pallet_balances::Config for Runtime { +impl orml_tokens::Config for Runtime { + type RuntimeEvent = RuntimeEvent; type Balance = Balance; - type DustRemoval = (); - type Event = Event; - type ExistentialDeposit = ExistentialDeposit; - type AccountStore = frame_system::Pallet; - type MaxLocks = MaxLocks; + type Amount = Amount; + type CurrencyId = CurrencyId; + type WeightInfo = (); + type ExistentialDeposits = ExistentialDeposits; + type CurrencyHooks = (); + type MaxLocks = (); type MaxReserves = (); type ReserveIdentifier = [u8; 8]; - type WeightInfo = (); + type DustRemovalWhitelist = Nothing; +} + +impl BlockNumberProvider for MockBlockNumberProvider { + type BlockNumber = BlockNumber; + + fn current_block_number() -> Self::BlockNumber { + Self::get() + } } + pub struct EnsureAliceOrBob; -impl EnsureOrigin for EnsureAliceOrBob { +impl EnsureOrigin for EnsureAliceOrBob { type Success = AccountId; - fn try_origin(o: Origin) -> Result { - Into::, Origin>>::into(o).and_then(|o| match o { + fn try_origin(o: RuntimeOrigin) -> Result { + Into::, RuntimeOrigin>>::into(o).and_then(|o| match o { RawOrigin::Signed(ALICE) => Ok(ALICE), RawOrigin::Signed(BOB) => Ok(BOB), - r => Err(Origin::from(r)), + r => Err(RuntimeOrigin::from(r)), }) } #[cfg(feature = "runtime-benchmarks")] - fn successful_origin() -> Origin { - Origin::from(RawOrigin::Signed(Default::default())) + fn try_successful_origin() -> Result { + let zero_account_id = AccountId::decode(&mut sp_runtime::traits::TrailingZeroInput::zeroes()) + .expect("infinite length input; no invalid inputs for type; qed"); + Ok(RuntimeOrigin::from(RawOrigin::Signed(zero_account_id))) } } -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 = (); -} +pub const SEE: CurrencyId = CurrencyId::Token(TokenSymbol::SEE); +pub const EDF: CurrencyId = CurrencyId::Token(TokenSymbol::edf); parameter_types! { - 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 = SEE; // Setheum native currency ticker is SEE/ - pub const GetSerpCurrencyId: CurrencyId = SERP; // Serp currency ticker is SERP/ - pub const GetDinarCurrencyId: CurrencyId = DNAR; // The Dinar currency ticker is DNAR/ - pub const GetHelpCurrencyId: CurrencyId = HELP; // HighEnd LaunchPad currency ticker is HELP/ + pub const GetNativeCurrencyId: CurrencyId = SEE; + pub const GetDEFCurrencyId: CurrencyId = EDF; pub static MockBlockNumberProvider: u64 = 0; - pub const TreasuryAccount: AccountId = TREASURY; } impl BlockNumberProvider for MockBlockNumberProvider { type BlockNumber = u64; - fn current_block_number() -> Self::BlockNumber { + fn current_block_number() -> BlockNumberFor { Self::get() } } -parameter_types! { - pub const MaxNativeVestingSchedules: u32 = 2; - pub const MaxSerpVestingSchedules: u32 = 2; - pub const MaxDinarVestingSchedules: u32 = 2; - pub const MaxHelpVestingSchedules: 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 RuntimeEvent = RuntimeEvent; type MultiCurrency = Tokens; type GetNativeCurrencyId = GetNativeCurrencyId; - type GetSerpCurrencyId = GetSerpCurrencyId; - type GetDinarCurrencyId = GetDinarCurrencyId; - type GetHelpCurrencyId = GetHelpCurrencyId; - type SetterCurrencyId = SetterCurrencyId; - type GetSetUSDId = GetSetUSDId; - type MinVestedTransfer = MinVestedTransfer; - type TreasuryAccount = TreasuryAccount; - type UpdateOrigin = EnsureAliceOrBob; + type GetEDFCurrencyId = GetEDFCurrencyId; + type MinNativeVestedTransfer = ConstU64<5>; + type MinEDFVestedTransfer = ConstU64<5>; + type VestedTransferOrigin = EnsureAliceOrBob; type WeightInfo = (); - type MaxNativeVestingSchedules = MaxNativeVestingSchedules; - type MaxSerpVestingSchedules = MaxSerpVestingSchedules; - type MaxDinarVestingSchedules = MaxDinarVestingSchedules; - type MaxHelpVestingSchedules = MaxHelpVestingSchedules; - type MaxSetterVestingSchedules = MaxSetterVestingSchedules; - type MaxSetUSDVestingSchedules = MaxSetUSDVestingSchedules; + type MaxNativeVestingSchedules = ConstU32<2>; + type MaxEDFVestingSchedules = ConstU32<2>; + type BlockNumberProvider = MockBlockNumberProvider; } -type UncheckedExtrinsic = frame_system::mocking::MockUncheckedExtrinsic; type Block = frame_system::mocking::MockBlock; construct_runtime!( - pub enum Runtime where - Block = Block, - NodeBlock = Block, - UncheckedExtrinsic = UncheckedExtrinsic, - { - 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} + pub enum Runtime { + System: frame_system, + Vesting: vesting, + Tokens: orml_tokens, } ); pub const ALICE: AccountId = 1; pub const BOB: AccountId = 2; pub const CHARLIE: AccountId = 3; -pub const TREASURY: AccountId = 4; +#[derive(Default)] pub struct ExtBuilder { balances: Vec<(AccountId, CurrencyId, Balance)>, } @@ -192,33 +150,19 @@ impl Default for ExtBuilder { fn default() -> Self { Self { balances: vec![ - (ALICE, SEE, 10000), - (ALICE, SERP, 1000), - (ALICE, DNAR, 1000), - (ALICE, HELP, 1000), - (ALICE, SETR, 1000), - (ALICE, SETUSD, 1000), - (CHARLIE, SEE, 10000), - (CHARLIE, SERP, 1000), - (CHARLIE, DNAR, 1000), - (CHARLIE, HELP, 1000), - (CHARLIE, SETR, 1000), - (CHARLIE, SETUSD, 1000), - (TREASURY, SEE, 10000), - (TREASURY, SERP, 1000), - (TREASURY, DNAR, 1000), - (TREASURY, HELP, 1000), - (TREASURY, SETR, 1000), - (TREASURY, SETUSD, 1000) + (ALICE, SEE, 100), + (ALICE, EDF, 100), + (CHARLIE, SEE, 50) + (CHARLIE, EDF, 50) ], } } } impl ExtBuilder { - pub fn build(self) -> sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::default() - .build_storage::() + pub fn build() -> sp_io::TestExternalities { + let mut t = frame_system::GenesisConfig::::default() + .build_storage() .unwrap(); orml_tokens::GenesisConfig:: { @@ -228,12 +172,17 @@ impl ExtBuilder { .unwrap(); vesting::GenesisConfig:: { - // who, start, period, period_count, per_period - vesting: vec![(CHARLIE, SEE, 2, 3, 4, 5)], + vesting: vec![ + // who, start, period, period_count, per_period + (CHARLIE, SEE, 2, 3, 1, 5), + (CHARLIE, SEE, 2 + 3, 3, 3, 5), + (CHARLIE, EDF, 2, 3, 1, 5), + (CHARLIE, EDF, 2 + 3, 3, 3, 5), + ], } .assimilate_storage(&mut t) .unwrap(); t.into() } -} \ No newline at end of file +} diff --git a/blockchain/modules/vesting/src/tests.rs b/blockchain/modules/vesting/src/tests.rs index fa0e2d89..df4ce576 100644 --- a/blockchain/modules/vesting/src/tests.rs +++ b/blockchain/modules/vesting/src/tests.rs @@ -4,7 +4,9 @@ use super::*; use frame_support::{assert_noop, assert_ok, error::BadOrigin}; -use mock::{Event, SEE, *}; +use mock::*; +use sp_runtime::traits::Dispatchable; +use sp_runtime::TokenError; #[test] fn vesting_from_chain_spec_works() { @@ -14,30 +16,40 @@ fn vesting_from_chain_spec_works() { &CHARLIE, 10 )); + assert!(Tokens::ensure_can_withdraw(SEE, &CHARLIE, 11).is_err()); assert_eq!( Vesting::native_vesting_schedules(&CHARLIE), - vec![VestingSchedule { - start: 2u64, - period: 3u64, - period_count: 4u32, - per_period: 5u64, - }] + vec![ + VestingSchedule { + start: 2u64, + period: 3u64, + period_count: 1u32, + per_period: 5u64, + }, + VestingSchedule { + start: 2u64 + 3u64, + period: 3u64, + period_count: 3u32, + per_period: 5u64, + } + ] ); - System::set_block_number(13); + MockBlockNumberProvider::set(13); - assert_ok!(Vesting::claim(Origin::signed(CHARLIE), SEE)); + assert_ok!(Vesting::claim(RuntimeOrigin::signed(CHARLIE), SEE)); assert_ok!(Tokens::ensure_can_withdraw( SEE, &CHARLIE, 25 )); + assert!(Tokens::ensure_can_withdraw(SEE, &CHARLIE, 26).is_err()); - System::set_block_number(14); + MockBlockNumberProvider::set(14); - assert_ok!(Vesting::claim(Origin::signed(CHARLIE), SEE)); + assert_ok!(Vesting::claim(RuntimeOrigin::signed(CHARLIE), SEE)); assert_ok!(Tokens::ensure_can_withdraw( SEE, @@ -58,8 +70,58 @@ fn vested_transfer_works() { period_count: 1u32, per_period: 100u64, }; - assert_ok!(Vesting::vested_transfer(Origin::signed(ALICE), SEE, BOB, schedule.clone())); + assert_ok!(Vesting::vested_transfer( + RuntimeOrigin::signed(ALICE), + SEE, + BOB, + schedule.clone() + )); assert_eq!(Vesting::native_vesting_schedules(&BOB), vec![schedule.clone()]); + System::assert_last_event(RuntimeEvent::Vesting(crate::Event::VestingScheduleAdded { + from: ALICE, + to: BOB, + vesting_schedule: schedule, + })); + }); +} + +#[test] +fn self_vesting() { + ExtBuilder::default().build().execute_with(|| { + System::set_block_number(1); + + let schedule = VestingSchedule { + start: 0u64, + period: 10u64, + period_count: 1u32, + per_period: ALICE_BALANCE, + }; + + let bad_schedule = VestingSchedule { + start: 0u64, + period: 10u64, + period_count: 1u32, + per_period: 10 * ALICE_BALANCE, + }; + + assert_noop!( + Vesting::vested_transfer(RuntimeOrigin::signed(ALICE), SEE, ALICE, bad_schedule), + crate::Error::::InsufficientBalanceToLock + ); + + assert_ok!(Vesting::vested_transfer( + RuntimeOrigin::signed(ALICE), + SEE, + ALICE, + schedule.clone() + )); + + assert_eq!(Vesting::native_vesting_schedules(&ALICE), vec![schedule.clone()]); + System::assert_last_event(RuntimeEvent::Vesting(crate::Event::VestingScheduleAdded { + from: ALICE, + to: ALICE, + vesting_schedule: schedule, + })); }); } @@ -72,9 +134,9 @@ fn add_new_vesting_schedule_merges_with_current_locked_balance_and_until() { period_count: 2u32, per_period: 10u64, }; - assert_ok!(Vesting::vested_transfer(Origin::signed(ALICE), SEE, BOB, schedule)); + assert_ok!(Vesting::vested_transfer(RuntimeOrigin::signed(ALICE), SEE, BOB, schedule)); - System::set_block_number(12); + MockBlockNumberProvider::set(12); let another_schedule = VestingSchedule { start: 10u64, @@ -82,7 +144,20 @@ 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), SEE, BOB, another_schedule)); + assert_ok!(Vesting::vested_transfer( + RuntimeOrigin::signed(ALICE), + SEE, + BOB, + another_schedule + )); + + assert_eq!( + Tokens::locks(&BOB, SEE).get(0), + Some(&BalanceLock { + id: VESTING_LOCK_ID, + amount: 17u64, + }) + ); }); } @@ -95,7 +170,7 @@ fn cannot_use_fund_if_not_claimed() { period_count: 1u32, per_period: 50u64, }; - assert_ok!(Vesting::vested_transfer(Origin::signed(ALICE), SEE, BOB, schedule)); + assert_ok!(Vesting::vested_transfer(RuntimeOrigin::signed(ALICE), SEE, BOB, schedule)); assert!(Tokens::ensure_can_withdraw(SEE, &BOB, 1).is_err()); }); } @@ -110,7 +185,7 @@ fn vested_transfer_fails_if_zero_period_or_count() { per_period: 100u64, }; assert_noop!( - Vesting::vested_transfer(Origin::signed(ALICE), SEE, BOB, schedule), + Vesting::vested_transfer(RuntimeOrigin::signed(ALICE), SEE, BOB, schedule), Error::::ZeroVestingPeriod ); @@ -121,12 +196,28 @@ fn vested_transfer_fails_if_zero_period_or_count() { per_period: 100u64, }; assert_noop!( - Vesting::vested_transfer(Origin::signed(ALICE), SEE, BOB, schedule), + Vesting::vested_transfer(RuntimeOrigin::signed(ALICE), SEE, BOB, schedule), Error::::ZeroVestingPeriodCount ); }); } +#[test] +fn vested_transfer_fails_if_transfer_err() { + ExtBuilder::default().build().execute_with(|| { + let schedule = VestingSchedule { + start: 1u64, + period: 1u64, + period_count: 1u32, + per_period: 100u64, + }; + assert_noop!( + Vesting::vested_transfer(RuntimeOrigin::signed(BOB), SEE, ALICE, schedule), + TokenError::FundsUnavailable, + ); + }); +} + #[test] fn vested_transfer_fails_if_overflow() { ExtBuilder::default().build().execute_with(|| { @@ -137,7 +228,7 @@ fn vested_transfer_fails_if_overflow() { per_period: u64::MAX, }; assert_noop!( - Vesting::vested_transfer(Origin::signed(ALICE), SEE, BOB, schedule), + Vesting::vested_transfer(RuntimeOrigin::signed(ALICE), SEE, BOB, schedule), ArithmeticError::Overflow, ); @@ -148,7 +239,7 @@ fn vested_transfer_fails_if_overflow() { per_period: 1u64, }; assert_noop!( - Vesting::vested_transfer(Origin::signed(ALICE), SEE, BOB, another_schedule), + Vesting::vested_transfer(RuntimeOrigin::signed(ALICE), SEE, BOB, another_schedule), ArithmeticError::Overflow, ); }); @@ -164,7 +255,7 @@ fn vested_transfer_fails_if_bad_origin() { per_period: 100u64, }; assert_noop!( - Vesting::vested_transfer(Origin::signed(CHARLIE), SEE, BOB, schedule), + Vesting::vested_transfer(RuntimeOrigin::signed(CHARLIE), SEE, BOB, schedule), BadOrigin ); }); @@ -179,29 +270,28 @@ fn claim_works() { period_count: 2u32, per_period: 10u64, }; - assert_ok!(Vesting::vested_transfer(Origin::signed(ALICE), SEE, BOB, schedule)); + assert_ok!(Vesting::vested_transfer(RuntimeOrigin::signed(ALICE), SEE, BOB, schedule)); - System::set_block_number(11); + MockBlockNumberProvider::set(11); // remain locked if not claimed - assert!(Tokens::transfer(Origin::signed(BOB), ALICE, SEE, 10).is_err()); + assert!(Tokens::transfer(&BOB, &ALICE, SEE, 10).is_err()); // unlocked after claiming - assert_ok!(Vesting::claim(Origin::signed(BOB), SEE)); + assert_ok!(Vesting::claim(RuntimeOrigin::signed(BOB), SEE)); assert!(NativeVestingSchedules::::contains_key(BOB)); - assert_ok!(Tokens::transfer(Origin::signed(BOB), ALICE, SEE, 10)); + assert_ok!(Tokens::transfer(&BOB, &ALICE, SEE, 10)); // more are still locked - assert!(Tokens::transfer(Origin::signed(BOB), ALICE, SEE, 1).is_err()); + assert!(Tokens::transfer(&BOB, &ALICE, SEE, 1).is_err()); - System::set_block_number(21); + MockBlockNumberProvider::set(21); // claim more - assert_ok!(Vesting::claim(Origin::signed(BOB), SEE)); + assert_ok!(Vesting::claim(RuntimeOrigin::signed(BOB), SEE)); assert!(!NativeVestingSchedules::::contains_key(BOB)); - assert_ok!(Tokens::transfer(Origin::signed(BOB), ALICE, SEE, 10)); + assert_ok!(Tokens::transfer(&BOB, &ALICE, SEE, 10)); // all used up assert_eq!(Tokens::free_balance(SEE, &BOB), 0); - assert_eq!(PalletBalances::free_balance(BOB), 0); // no locks anymore - assert_eq!(PalletBalances::locks(&BOB), vec![]); + assert_eq!(Tokens::locks(&BOB, SEE), vec![]); }); } @@ -214,18 +304,25 @@ fn claim_for_works() { period_count: 2u32, per_period: 10u64, }; - assert_ok!(Vesting::vested_transfer(Origin::signed(ALICE), SEE, BOB, schedule)); + assert_ok!(Vesting::vested_transfer(RuntimeOrigin::signed(ALICE), SEE, BOB, schedule)); - assert_ok!(Vesting::claim_for(Origin::signed(ALICE), SEE, BOB)); + assert_ok!(Vesting::claim_for(RuntimeOrigin::signed(ALICE), SEE, BOB)); + assert_eq!( + Tokens::locks(&BOB, SEE).get(0), + Some(&BalanceLock { + id: VESTING_LOCK_ID, + amount: 20u64, + }) + ); assert!(NativeVestingSchedules::::contains_key(&BOB)); - System::set_block_number(21); + MockBlockNumberProvider::set(21); - assert_ok!(Vesting::claim_for(Origin::signed(ALICE), SEE, BOB)); + assert_ok!(Vesting::claim_for(RuntimeOrigin::signed(ALICE), SEE, BOB)); // no locks anymore - assert_eq!(PalletBalances::locks(&BOB), vec![]); + assert_eq!(Tokens::locks(&BOB, SEE), vec![]); assert!(!NativeVestingSchedules::::contains_key(&BOB)); }); } @@ -239,7 +336,7 @@ fn update_vesting_schedules_works() { period_count: 2u32, per_period: 10u64, }; - assert_ok!(Vesting::vested_transfer(Origin::signed(ALICE), SEE, BOB, schedule)); + assert_ok!(Vesting::vested_transfer(RuntimeOrigin::signed(ALICE), SEE, BOB, schedule)); let updated_schedule = VestingSchedule { start: 0u64, @@ -248,33 +345,39 @@ fn update_vesting_schedules_works() { per_period: 10u64, }; assert_ok!(Vesting::update_vesting_schedules( - Origin::signed(ALICE), + RuntimeOrigin::root(), SEE, BOB, vec![updated_schedule] )); - System::set_block_number(11); - assert_ok!(Vesting::claim(Origin::signed(BOB), SEE)); - assert!(Tokens::transfer(Origin::signed(BOB), ALICE, SEE, 1).is_err()); + MockBlockNumberProvider::set(11); + assert_ok!(Vesting::claim(RuntimeOrigin::signed(BOB), SEE)); + assert!(Tokens::transfer(&BOB, &ALICE, SEE, 1).is_err()); - System::set_block_number(21); - assert_ok!(Vesting::claim(Origin::signed(BOB), SEE)); - assert_ok!(Tokens::transfer(Origin::signed(BOB), ALICE, SEE, 10)); + MockBlockNumberProvider::set(21); + assert_ok!(Vesting::claim(RuntimeOrigin::signed(BOB), SEE)); + assert_ok!(Tokens::transfer(&BOB, &ALICE, SEE, 10)); // empty vesting schedules cleanup the storage and unlock the fund assert!(NativeVestingSchedules::::contains_key(BOB)); - - assert_ok!(Vesting::update_vesting_schedules(Origin::signed(ALICE), SEE, BOB, vec![])); + assert_eq!( + Tokens::locks(&BOB, SEE).get(0), + Some(&BalanceLock { + id: VESTING_LOCK_ID, + amount: 10u64, + }) + ); + assert_ok!(Vesting::update_vesting_schedules(RuntimeOrigin::root(), SEE, BOB, vec![])); assert!(!NativeVestingSchedules::::contains_key(BOB)); - assert_eq!(PalletBalances::locks(&BOB), vec![]); + assert_eq!(Tokens::locks(&BOB, SEE), vec![]); }); } #[test] fn update_vesting_schedules_fails_if_unexpected_existing_locks() { ExtBuilder::default().build().execute_with(|| { - assert_ok!(Tokens::transfer(Origin::signed(ALICE), BOB, SEE, 1)); + assert_ok!(Tokens::transfer(&ALICE, &BOB, SEE, 1)); Tokens::set_lock(*b"prelocks", SEE, &BOB, 0u64); }); } @@ -289,7 +392,7 @@ fn vested_transfer_check_for_min() { per_period: 3u64, }; assert_noop!( - Vesting::vested_transfer(Origin::signed(BOB), SEE, ALICE, schedule), + Vesting::vested_transfer(RuntimeOrigin::signed(BOB), SEE, ALICE, schedule), Error::::AmountLow ); }); @@ -304,7 +407,7 @@ fn multiple_vesting_schedule_claim_works() { period_count: 2u32, per_period: 10u64, }; - assert_ok!(Vesting::vested_transfer(Origin::signed(ALICE), SEE, BOB, schedule.clone())); + assert_ok!(Vesting::vested_transfer(RuntimeOrigin::signed(ALICE), SEE, BOB, schedule.clone())); let schedule2 = VestingSchedule { start: 0u64, @@ -312,23 +415,23 @@ fn multiple_vesting_schedule_claim_works() { period_count: 3u32, per_period: 10u64, }; - assert_ok!(Vesting::vested_transfer(Origin::signed(ALICE), SEE, BOB, schedule2.clone())); + assert_ok!(Vesting::vested_transfer(RuntimeOrigin::signed(ALICE), SEE, BOB, schedule2.clone())); assert_eq!(Vesting::native_vesting_schedules(&BOB), vec![schedule, schedule2.clone()]); - System::set_block_number(21); + MockBlockNumberProvider::set(21); - assert_ok!(Vesting::claim(Origin::signed(BOB), SEE)); + assert_ok!(Vesting::claim(RuntimeOrigin::signed(BOB, SEE))); assert_eq!(Vesting::native_vesting_schedules(&BOB), vec![schedule2]); - System::set_block_number(31); + MockBlockNumberProvider::set(31); - assert_ok!(Vesting::claim(Origin::signed(BOB), SEE)); + assert_ok!(Vesting::claim(RuntimeOrigin::signed(BOB, SEE))); assert!(!NativeVestingSchedules::::contains_key(&BOB)); - assert_eq!(PalletBalances::locks(&BOB), vec![]); + assert_eq!(Tokens::locks(&BOB, SEE), vec![]); }); } @@ -341,18 +444,75 @@ fn exceeding_maximum_schedules_should_fail() { period_count: 2u32, per_period: 10u64, }; - assert_ok!(Vesting::vested_transfer(Origin::signed(ALICE), SEE, BOB, schedule.clone())); - assert_ok!(Vesting::vested_transfer(Origin::signed(ALICE), SEE, BOB, schedule.clone())); + assert_ok!(Vesting::vested_transfer(RuntimeOrigin::signed(ALICE), SEE, BOB, schedule.clone())); + assert_ok!(Vesting::vested_transfer(RuntimeOrigin::signed(ALICE), SEE, BOB, schedule.clone())); + + let create = RuntimeCall::Vesting(crate::Call::::vested_transfer { + currency_id: SEE, + dest: BOB, + schedule: schedule.clone(), + }); assert_noop!( - Vesting::vested_transfer(Origin::signed(ALICE), SEE, BOB, schedule.clone()), - Error::::MaxVestingSchedulesExceeded + create.dispatch(RuntimeOrigin::signed(ALICE)), + Error::::MaxNativeVestingSchedulesExceeded ); let schedules = vec![schedule.clone(), schedule.clone(), schedule]; assert_noop!( - Vesting::update_vesting_schedules(Origin::signed(ALICE), SEE, BOB, schedules), - Error::::MaxVestingSchedulesExceeded + Vesting::update_vesting_schedules(RuntimeOrigin::root(), SEE, BOB, schedules), + Error::::MaxNativeVestingSchedulesExceeded ); }); -} \ No newline at end of file +} + +#[test] +fn cliff_vesting_works() { + const VESTING_AMOUNT: Balance = 12; + const VESTING_PERIOD: Balance = 20; + + ExtBuilder::default().build().execute_with(|| { + let cliff_schedule = VestingSchedule { + start: VESTING_PERIOD - 1, + period: 1, + period_count: 1, + per_period: VESTING_AMOUNT, + }; + + let balance_lock = BalanceLock { + id: VESTING_LOCK_ID, + amount: VESTING_AMOUNT, + }; + + assert_eq!(Tokens::free_balance(SEE, BOB), 0); + assert_ok!(Vesting::vested_transfer( + RuntimeOrigin::signed(ALICE), + SEE, + BOB, + cliff_schedule + )); + assert_eq!(Tokens::free_balance(SEE, BOB), VESTING_AMOUNT); + assert_eq!(Tokens::locks(&BOB, SEE), vec![balance_lock.clone()]); + + for i in 1..VESTING_PERIOD { + MockBlockNumberProvider::set(i); + assert_ok!(Vesting::claim(RuntimeOrigin::signed(BOB), SEE)); + assert_eq!(Tokens::free_balance(SEE, BOB), VESTING_AMOUNT); + assert_eq!(Tokens::locks(&BOB, SEE), vec![balance_lock.clone()]); + assert_noop!( + Tokens::transfer(&BOB, &CHARLIE, SEE, VESTING_AMOUNT), + TokenError::Frozen, + ); + } + + MockBlockNumberProvider::set(VESTING_PERIOD); + assert_ok!(Vesting::claim(RuntimeOrigin::signed(BOB), SEE)); + assert!(Tokens::locks(&BOB, SEE).is_empty()); + assert_ok!(Tokens::transfer( + &BOB, + &CHARLIE, + SEE, + VESTING_AMOUNT + )); + }); +} diff --git a/blockchain/modules/vesting/src/weights.rs b/blockchain/modules/vesting/src/weights.rs index db35b4f8..251132c6 100644 --- a/blockchain/modules/vesting/src/weights.rs +++ b/blockchain/modules/vesting/src/weights.rs @@ -10,7 +10,7 @@ // --chain=dev // --steps=50 // --repeat=20 -// --pallet=orlm_vesting +// --pallet=module_vesting // --extrinsic=* // --execution=wasm // --wasm-execution=compiled @@ -20,6 +20,7 @@ // ..maintain/orml-weight-template.hbs + #![cfg_attr(rustfmt, rustfmt_skip)] #![allow(unused_parens)] #![allow(unused_imports)] @@ -28,7 +29,7 @@ use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; use sp_std::marker::PhantomData; -/// Weight functions needed for module_vesting. +/// Weight functions needed for orml_vesting. pub trait WeightInfo { fn vested_transfer() -> Weight; fn claim(i: u32, ) -> Weight; @@ -38,22 +39,22 @@ pub trait WeightInfo { /// Default weights. impl WeightInfo for () { fn vested_transfer() -> Weight { - (69_000_000 as Weight) - .saturating_add(RocksDbWeight::get().reads(4 as Weight)) - .saturating_add(RocksDbWeight::get().writes(4 as Weight)) + Weight::from_parts(69_000_000, 0) + .saturating_add(RocksDbWeight::get().reads(4 as u64)) + .saturating_add(RocksDbWeight::get().writes(4 as u64)) } fn claim(i: u32, ) -> Weight { - (31_747_000 as Weight) + Weight::from_parts(31_747_000, 0) // Standard Error: 4_000 - .saturating_add((63_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(RocksDbWeight::get().reads(2 as Weight)) - .saturating_add(RocksDbWeight::get().writes(2 as Weight)) + .saturating_add(Weight::from_parts(63_000, 0).saturating_mul(i as u64)) + .saturating_add(RocksDbWeight::get().reads(2 as u64)) + .saturating_add(RocksDbWeight::get().writes(2 as u64)) } fn update_vesting_schedules(i: u32, ) -> Weight { - (29_457_000 as Weight) + Weight::from_parts(29_457_000, 0) // Standard Error: 4_000 - .saturating_add((117_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(RocksDbWeight::get().reads(2 as Weight)) - .saturating_add(RocksDbWeight::get().writes(3 as Weight)) + .saturating_add(Weight::from_parts(117_000, 0).saturating_mul(i as u64)) + .saturating_add(RocksDbWeight::get().reads(2 as u64)) + .saturating_add(RocksDbWeight::get().writes(3 as u64)) } }