From 72751866f554f597e771ac847c93918b034940bd Mon Sep 17 00:00:00 2001 From: str-mv Date: Mon, 22 Nov 2021 13:30:28 +0000 Subject: [PATCH] Switch to orml fork --- --- a/pallets/orml-vesting/ README.md +++ /dev/null @@ -1,9 +0,0 @@ -# Vesting Module - -## 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 Schedule - -The schedule of a vesting is described by data structure `VestingSchedule`: from the block number of `start`, 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. --- a/pallets/orml-vesting/Cargo.toml +++ /dev/null @@ -1,40 +0,0 @@ -[package] -name = "orml-vesting" -description = "Provides scheduled balance locking mechanism, in a *graded vesting* way." -license = "Apache-2.0" -version = "0.4.1-dev" -authors = ["Laminar Developers "] -edition = "2018" - -[dependencies] -scale-info = { version = "1.0", default-features = false, features = ["derive"] } -serde = { version = "1.0.124", optional = true } -codec = { package = "parity-scale-codec", version = "2.3.1", default-features = false, features = ["max-encoded-len"] } -sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.12", default-features = false } -sp-io = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.12", default-features = false } -sp-std = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.12", default-features = false } - -frame-support = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.12", default-features = false } -frame-system = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.12", default-features = false } - -[dev-dependencies] -sp-core = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.12" } -pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.12" } - -[features] -default = ["std"] -std = [ - "serde", - "codec/std", - "scale-info/std", - "sp-runtime/std", - "sp-std/std", - "sp-io/std", - "frame-support/std", - "frame-system/std", -] -runtime-benchmarks = [ - "frame-support/runtime-benchmarks", - "frame-system/runtime-benchmarks", -] -try-runtime = ["frame-support/try-runtime"] --- a/pallets/orml-vesting/src/default_weight.rs +++ /dev/null @@ -1,27 +0,0 @@ -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 2.0.0 - -#![allow(unused_parens)] -#![allow(unused_imports)] -#![allow(clippy::unnecessary_cast)] - -use frame_support::weights::{constants::RocksDbWeight as DbWeight, Weight}; - -impl crate::WeightInfo for () { - fn vested_transfer() -> Weight { - (310_862_000 as Weight) - .saturating_add(DbWeight::get().reads(4 as Weight)) - .saturating_add(DbWeight::get().writes(4 as Weight)) - } - fn claim(i: u32) -> Weight { - (158_614_000 as Weight) - .saturating_add((958_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(DbWeight::get().reads(3 as Weight)) - .saturating_add(DbWeight::get().writes(3 as Weight)) - } - fn update_vesting_schedules(i: u32) -> Weight { - (119_811_000 as Weight) - .saturating_add((2_320_000 as Weight).saturating_mul(i as Weight)) - .saturating_add(DbWeight::get().reads(2 as Weight)) - .saturating_add(DbWeight::get().writes(3 as Weight)) - } -} --- a/pallets/orml-vesting/src/lib.rs +++ /dev/null @@ -1,380 +0,0 @@ -//! # Vesting Module -//! -//! ## 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 Schedule -//! -//! The schedule of a vesting is described by data structure `VestingSchedule`: -//! from the block number of `start`, 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. -//! -//! ## Interface -//! -//! ### Dispatchable Functions -//! -//! - `vested_transfer` - Add a new vesting schedule for an account. -//! - `claim` - Claim unlocked balances. -//! - `update_vesting_schedules` - Update all vesting schedules under an -//! account, `root` origin required. - -#![cfg_attr(not(feature = "std"), no_std)] -#![allow(clippy::unused_unit)] - -use codec::{HasCompact, MaxEncodedLen}; -use frame_support::{ - ensure, - pallet_prelude::*, - traits::{Currency, EnsureOrigin, ExistenceRequirement, Get, LockIdentifier, LockableCurrency, WithdrawReasons}, - transactional, BoundedVec, -}; -use frame_system::{ensure_root, ensure_signed, pallet_prelude::*}; -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, -}; - -mod mock; -mod tests; -mod weights; - -pub use module::*; -pub use weights::WeightInfo; - -pub const VESTING_LOCK_ID: LockIdentifier = *b"ormlvest"; - -/// 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, TypeInfo)] -pub struct VestingSchedule { - /// Vesting starting block - pub start: BlockNumber, - /// Number of blocks between vest - pub period: BlockNumber, - /// Number of vest - pub period_count: u32, - /// Amount of tokens to release per vest - #[codec(compact)] - pub per_period: Balance, -} - -impl VestingSchedule { - /// Returns the end of all periods, `None` if calculation overflows. - pub fn end(&self) -> Option { - // period * period_count + start - self.period - .checked_mul(&self.period_count.into())? - .checked_add(&self.start) - } - - /// Returns all locked amount, `None` if calculation overflows. - pub fn total_amount(&self) -> Option { - self.per_period.checked_mul(&self.period_count.into()) - } - - /// Returns locked amount for a given `time`. - /// - /// Note this func assumes schedule is a valid one(non-zero period and - /// non-overflow total amount), and it should be guaranteed by callers. - pub fn locked_amount(&self, time: BlockNumber) -> Balance { - // full = (time - start) / period - // unrealized = period_count - full - // per_period * unrealized - let full = time - .saturating_sub(self.start) - .checked_div(&self.period) - .expect("ensured non-zero period; qed"); - let unrealized = self.period_count.saturating_sub(full.unique_saturated_into()); - self.per_period - .checked_mul(&unrealized.into()) - .expect("ensured non-overflow total amount; qed") - } -} - -#[frame_support::pallet] -pub mod module { - use super::*; - - pub(crate) type BalanceOf = - <::Currency as Currency<::AccountId>>::Balance; - pub(crate) type VestingScheduleOf = VestingSchedule<::BlockNumber, BalanceOf>; - pub type ScheduledItem = ( - ::AccountId, - ::BlockNumber, - ::BlockNumber, - u32, - BalanceOf, - ); - - #[pallet::config] - pub trait Config: frame_system::Config { - type Event: From> + IsType<::Event>; - - type Currency: LockableCurrency; - - #[pallet::constant] - /// The minimum amount transferred to call `vested_transfer`. - type MinVestedTransfer: Get>; - - /// Required origin for vested transfer. - type VestedTransferOrigin: EnsureOrigin; - - /// Weight information for extrinsics in this module. - type WeightInfo: WeightInfo; - - /// The maximum vesting schedules - type MaxVestingSchedules: Get; - - // The block number provider - type BlockNumberProvider: BlockNumberProvider; - } - - #[pallet::error] - pub enum Error { - /// Vesting period is zero - ZeroVestingPeriod, - /// Number of vests is zero - ZeroVestingPeriodCount, - /// Insufficient amount of balance to lock - InsufficientBalanceToLock, - /// This account have too many vesting schedules - TooManyVestingSchedules, - /// The vested transfer amount is too low - AmountLow, - /// Failed because the maximum vesting schedules was exceeded - MaxVestingSchedulesExceeded, - } - - #[pallet::event] - #[pallet::generate_deposit(fn deposit_event)] - 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), - } - - /// Vesting schedules of an account. - /// - /// VestingSchedules: map AccountId => Vec - #[pallet::storage] - #[pallet::getter(fn vesting_schedules)] - pub type VestingSchedules = StorageMap< - _, - Blake2_128Concat, - T::AccountId, - BoundedVec, T::MaxVestingSchedules>, - ValueQuery, - >; - - #[pallet::genesis_config] - pub struct GenesisConfig { - pub vesting: Vec>, - } - - #[cfg(feature = "std")] - impl Default for GenesisConfig { - fn default() -> Self { - GenesisConfig { vesting: vec![] } - } - } - - #[pallet::genesis_build] - impl GenesisBuild for GenesisConfig { - fn build(&self) { - self.vesting - .iter() - .for_each(|(who, start, period, period_count, per_period)| { - let mut bounded_schedules = VestingSchedules::::get(who); - bounded_schedules - .try_push(VestingSchedule { - start: *start, - period: *period, - period_count: *period_count, - per_period: *per_period, - }) - .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::(schedule)?; - Ok(acc_amount + amount) - }) - .expect("Invalid vesting schedule"); - - assert!( - T::Currency::free_balance(who) >= total_amount, - "Account do not have enough balance" - ); - - T::Currency::set_lock(VESTING_LOCK_ID, who, total_amount, WithdrawReasons::all()); - VestingSchedules::::insert(who, bounded_schedules); - }); - } - } - - #[pallet::pallet] - pub struct Pallet(_); - - #[pallet::hooks] - impl Hooks for Pallet {} - - #[pallet::call] - impl Pallet { - #[pallet::weight(T::WeightInfo::claim((::MaxVestingSchedules::get() / 2) as u32))] - pub fn claim(origin: OriginFor) -> DispatchResult { - let who = ensure_signed(origin)?; - let locked_amount = Self::do_claim(&who); - - Self::deposit_event(Event::Claimed(who, locked_amount)); - Ok(()) - } - - #[pallet::weight(T::WeightInfo::vested_transfer())] - pub fn vested_transfer( - origin: OriginFor, - dest: ::Source, - 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::deposit_event(Event::VestingScheduleAdded(from, to, schedule)); - Ok(()) - } - - #[pallet::weight(T::WeightInfo::update_vesting_schedules(vesting_schedules.len() as u32))] - pub fn update_vesting_schedules( - origin: OriginFor, - who: ::Source, - vesting_schedules: Vec>, - ) -> DispatchResult { - ensure_root(origin)?; - - let account = T::Lookup::lookup(who)?; - Self::do_update_vesting_schedules(&account, vesting_schedules)?; - - Self::deposit_event(Event::VestingSchedulesUpdated(account)); - Ok(()) - } - - #[pallet::weight(T::WeightInfo::claim((::MaxVestingSchedules::get() / 2) as u32))] - pub fn claim_for(origin: OriginFor, dest: ::Source) -> DispatchResult { - let _ = ensure_signed(origin)?; - let who = T::Lookup::lookup(dest)?; - let locked_amount = Self::do_claim(&who); - - Self::deposit_event(Event::Claimed(who, locked_amount)); - Ok(()) - } - } -} - -impl Pallet { - fn do_claim(who: &T::AccountId) -> BalanceOf { - let locked = Self::locked_balance(who); - if locked.is_zero() { - // cleanup the storage and unlock the fund - >::remove(who); - T::Currency::remove_lock(VESTING_LOCK_ID, who); - } else { - T::Currency::set_lock(VESTING_LOCK_ID, who, locked, WithdrawReasons::all()); - } - locked - } - - /// Returns locked balance based on current block number. - fn locked_balance(who: &T::AccountId) -> BalanceOf { - let now = T::BlockNumberProvider::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 - }) - } - - #[transactional] - fn do_vested_transfer(from: &T::AccountId, to: &T::AccountId, schedule: VestingScheduleOf) -> DispatchResult { - let schedule_amount = ensure_valid_vesting_schedule::(&schedule)?; - - let total_amount = Self::locked_balance(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)?; - 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 = 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); - - Ok(()) - } -} - -/// Returns `Ok(total_total)` 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_total = schedule.total_amount().ok_or(ArithmeticError::Overflow)?; - - ensure!(total_total >= T::MinVestedTransfer::get(), Error::::AmountLow); - - Ok(total_total) -} --- a/pallets/orml-vesting/src/mock.rs +++ /dev/null @@ -1,153 +0,0 @@ -//! Mocks for the vesting module. - -#![cfg(test)] - -use super::*; -use frame_support::{ - construct_runtime, parameter_types, - traits::{EnsureOrigin, Everything}, -}; -use frame_system::RawOrigin; -use sp_core::H256; -use sp_runtime::{testing::Header, traits::IdentityLookup}; - -use crate as vesting; - -parameter_types! { - pub const BlockHashCount: u64 = 250; -} - -pub type AccountId = u128; -impl frame_system::Config for Runtime { - type Origin = Origin; - type Call = Call; - type Index = u64; - type BlockNumber = 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 BlockWeights = (); - type BlockLength = (); - type Version = (); - type PalletInfo = PalletInfo; - type AccountData = pallet_balances::AccountData; - type OnNewAccount = (); - type OnKilledAccount = (); - type DbWeight = (); - type BaseCallFilter = Everything; - type SystemWeightInfo = (); - type SS58Prefix = (); - type OnSetCode = (); -} - -type Balance = u64; - -parameter_types! { - pub const ExistentialDeposit: u64 = 1; -} - -impl pallet_balances::Config for Runtime { - type Balance = Balance; - type DustRemoval = (); - type Event = Event; - type ExistentialDeposit = ExistentialDeposit; - type AccountStore = frame_system::Pallet; - type MaxLocks = (); - type MaxReserves = (); - type ReserveIdentifier = [u8; 8]; - type WeightInfo = (); -} - -pub struct EnsureAliceOrBob; -impl EnsureOrigin for EnsureAliceOrBob { - type Success = AccountId; - - fn try_origin(o: Origin) -> Result { - Into::, Origin>>::into(o).and_then(|o| match o { - RawOrigin::Signed(ALICE) => Ok(ALICE), - RawOrigin::Signed(BOB) => Ok(BOB), - r => Err(Origin::from(r)), - }) - } - - #[cfg(feature = "runtime-benchmarks")] - fn successful_origin() -> Origin { - Origin::from(RawOrigin::Signed(Default::default())) - } -} - -parameter_types! { - pub const MaxVestingSchedule: u32 = 2; - pub const MinVestedTransfer: u64 = 5; - pub static MockBlockNumberProvider: u64 = 0; -} - -impl BlockNumberProvider for MockBlockNumberProvider { - type BlockNumber = u64; - - fn current_block_number() -> Self::BlockNumber { - Self::get() - } -} - -impl Config for Runtime { - type Event = Event; - type Currency = PalletBalances; - type MinVestedTransfer = MinVestedTransfer; - type VestedTransferOrigin = EnsureAliceOrBob; - type WeightInfo = (); - type MaxVestingSchedules = MaxVestingSchedule; - 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}, - } -); - -pub const ALICE: AccountId = 1; -pub const BOB: AccountId = 2; -pub const CHARLIE: AccountId = 3; - -#[derive(Default)] -pub struct ExtBuilder; - -impl ExtBuilder { - pub fn build() -> sp_io::TestExternalities { - let mut t = frame_system::GenesisConfig::default() - .build_storage::() - .unwrap(); - - pallet_balances::GenesisConfig:: { - balances: vec![(ALICE, 100), (CHARLIE, 50)], - } - .assimilate_storage(&mut t) - .unwrap(); - - vesting::GenesisConfig:: { - vesting: vec![ - // who, start, period, period_count, per_period - (CHARLIE, 2, 3, 1, 5), - (CHARLIE, 2 + 3, 3, 3, 5), - ], - } - .assimilate_storage(&mut t) - .unwrap(); - - t.into() - } -} --- a/pallets/orml-vesting/src/test.rs +++ /dev/null @@ -1,411 +0,0 @@ -//! Unit tests for the vesting module. - -#![cfg(test)] - -use super::*; -use frame_support::{assert_noop, assert_ok, error::BadOrigin}; -use mock::{Event, *}; -use pallet_balances::{BalanceLock, Reasons}; - -#[test] -fn vesting_from_chain_spec_works() { - ExtBuilder::build().execute_with(|| { - assert_ok!(PalletBalances::ensure_can_withdraw( - &CHARLIE, - 10, - WithdrawReasons::TRANSFER, - 20 - )); - assert!(PalletBalances::ensure_can_withdraw(&CHARLIE, 11, WithdrawReasons::TRANSFER, 19).is_err()); - - assert_eq!( - Vesting::vesting_schedules(&CHARLIE), - vec![ - VestingSchedule { - start: 2u64, - period: 3u64, - period_count: 1u32, - per_period: 5u64, - }, - VestingSchedule { - start: 2u64 + 3u64, - period: 3u64, - period_count: 3u32, - per_period: 5u64, - } - ] - ); - - MockBlockNumberProvider::set(13); - - assert_ok!(Vesting::claim(Origin::signed(CHARLIE))); - - assert_ok!(PalletBalances::ensure_can_withdraw( - &CHARLIE, - 25, - WithdrawReasons::TRANSFER, - 5 - )); - assert!(PalletBalances::ensure_can_withdraw(&CHARLIE, 26, WithdrawReasons::TRANSFER, 4).is_err()); - - MockBlockNumberProvider::set(14); - - assert_ok!(Vesting::claim(Origin::signed(CHARLIE))); - - assert_ok!(PalletBalances::ensure_can_withdraw( - &CHARLIE, - 30, - WithdrawReasons::TRANSFER, - 0 - )); - }); -} - -#[test] -fn vested_transfer_works() { - ExtBuilder::build().execute_with(|| { - System::set_block_number(1); - - let schedule = VestingSchedule { - start: 0u64, - period: 10u64, - 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))); - }); -} - -#[test] -fn add_new_vesting_schedule_merges_with_current_locked_balance_and_until() { - ExtBuilder::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)); - - MockBlockNumberProvider::set(12); - - let another_schedule = VestingSchedule { - start: 10u64, - period: 13u64, - 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, - }) - ); - }); -} - -#[test] -fn cannot_use_fund_if_not_claimed() { - ExtBuilder::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()); - }); -} - -#[test] -fn vested_transfer_fails_if_zero_period_or_count() { - ExtBuilder::build().execute_with(|| { - let schedule = VestingSchedule { - start: 1u64, - period: 0u64, - period_count: 1u32, - per_period: 100u64, - }; - assert_noop!( - Vesting::vested_transfer(Origin::signed(ALICE), BOB, schedule), - Error::::ZeroVestingPeriod - ); - - let schedule = VestingSchedule { - start: 1u64, - period: 1u64, - period_count: 0u32, - per_period: 100u64, - }; - assert_noop!( - Vesting::vested_transfer(Origin::signed(ALICE), 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(|| { - let schedule = VestingSchedule { - start: 1u64, - period: 1u64, - period_count: 2u32, - per_period: u64::MAX, - }; - assert_noop!( - Vesting::vested_transfer(Origin::signed(ALICE), BOB, schedule), - ArithmeticError::Overflow, - ); - - let another_schedule = VestingSchedule { - start: u64::MAX, - period: 1u64, - period_count: 2u32, - per_period: 1u64, - }; - assert_noop!( - Vesting::vested_transfer(Origin::signed(ALICE), BOB, another_schedule), - ArithmeticError::Overflow, - ); - }); -} - -#[test] -fn vested_transfer_fails_if_bad_origin() { - ExtBuilder::build().execute_with(|| { - let schedule = VestingSchedule { - start: 0u64, - period: 10u64, - period_count: 1u32, - per_period: 100u64, - }; - assert_noop!( - Vesting::vested_transfer(Origin::signed(CHARLIE), BOB, schedule), - BadOrigin - ); - }); -} - -#[test] -fn claim_works() { - ExtBuilder::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)); - - MockBlockNumberProvider::set(11); - // remain locked if not claimed - assert!(PalletBalances::transfer(Origin::signed(BOB), ALICE, 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)); - // more are still locked - assert!(PalletBalances::transfer(Origin::signed(BOB), ALICE, 1).is_err()); - - MockBlockNumberProvider::set(21); - // claim more - assert_ok!(Vesting::claim(Origin::signed(BOB))); - assert!(!VestingSchedules::::contains_key(BOB)); - assert_ok!(PalletBalances::transfer(Origin::signed(BOB), ALICE, 10)); - // all used up - assert_eq!(PalletBalances::free_balance(BOB), 0); - - // no locks anymore - assert_eq!(PalletBalances::locks(&BOB), vec![]); - }); -} - -#[test] -fn claim_for_works() { - ExtBuilder::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::claim_for(Origin::signed(ALICE), BOB)); - - assert_eq!( - PalletBalances::locks(&BOB).get(0), - Some(&BalanceLock { - id: VESTING_LOCK_ID, - amount: 20u64, - reasons: Reasons::All, - }) - ); - assert!(VestingSchedules::::contains_key(&BOB)); - - MockBlockNumberProvider::set(21); - - assert_ok!(Vesting::claim_for(Origin::signed(ALICE), BOB)); - - // no locks anymore - assert_eq!(PalletBalances::locks(&BOB), vec![]); - assert!(!VestingSchedules::::contains_key(&BOB)); - }); -} - -#[test] -fn update_vesting_schedules_works() { - ExtBuilder::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)); - - let updated_schedule = VestingSchedule { - start: 0u64, - period: 20u64, - period_count: 2u32, - per_period: 10u64, - }; - assert_ok!(Vesting::update_vesting_schedules( - Origin::root(), - BOB, - vec![updated_schedule] - )); - - MockBlockNumberProvider::set(11); - assert_ok!(Vesting::claim(Origin::signed(BOB))); - assert!(PalletBalances::transfer(Origin::signed(BOB), ALICE, 1).is_err()); - - MockBlockNumberProvider::set(21); - assert_ok!(Vesting::claim(Origin::signed(BOB))); - assert_ok!(PalletBalances::transfer(Origin::signed(BOB), ALICE, 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_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()); - }); -} - -#[test] -fn vested_transfer_check_for_min() { - ExtBuilder::build().execute_with(|| { - let schedule = VestingSchedule { - start: 1u64, - period: 1u64, - period_count: 1u32, - per_period: 3u64, - }; - assert_noop!( - Vesting::vested_transfer(Origin::signed(BOB), ALICE, schedule), - Error::::AmountLow - ); - }); -} - -#[test] -fn multiple_vesting_schedule_claim_works() { - ExtBuilder::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())); - - let schedule2 = VestingSchedule { - start: 0u64, - period: 10u64, - period_count: 3u32, - per_period: 10u64, - }; - assert_ok!(Vesting::vested_transfer(Origin::signed(ALICE), BOB, schedule2.clone())); - - assert_eq!(Vesting::vesting_schedules(&BOB), vec![schedule, schedule2.clone()]); - - MockBlockNumberProvider::set(21); - - assert_ok!(Vesting::claim(Origin::signed(BOB))); - - assert_eq!(Vesting::vesting_schedules(&BOB), vec![schedule2]); - - MockBlockNumberProvider::set(31); - - assert_ok!(Vesting::claim(Origin::signed(BOB))); - - assert!(!VestingSchedules::::contains_key(&BOB)); - - assert_eq!(PalletBalances::locks(&BOB), vec![]); - }); -} - -#[test] -fn exceeding_maximum_schedules_should_fail() { - ExtBuilder::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_noop!( - Vesting::vested_transfer(Origin::signed(ALICE), BOB, schedule.clone()), - Error::::MaxVestingSchedulesExceeded - ); - - let schedules = vec![schedule.clone(), schedule.clone(), schedule]; - - assert_noop!( - Vesting::update_vesting_schedules(Origin::root(), BOB, schedules), - Error::::MaxVestingSchedulesExceeded - ); - }); -} --- a/pallets/orml-vesting/src/weights.rs +++ /dev/null @@ -1,59 +0,0 @@ -//! Autogenerated weights for orml_vesting -//! -//! THIS FILE WAS AUTO-GENERATED USING THE SUBSTRATE BENCHMARK CLI VERSION 3.0.0 -//! DATE: 2021-05-04, STEPS: [50, ], REPEAT: 20, LOW RANGE: [], HIGH RANGE: [] -//! EXECUTION: Some(Wasm), WASM-EXECUTION: Compiled, CHAIN: Some("dev"), DB CACHE: 128 - -// Executed Command: -// /Users/xiliangchen/projects/acala/target/release/acala -// benchmark -// --chain=dev -// --steps=50 -// --repeat=20 -// --pallet=orml_vesting -// --extrinsic=* -// --execution=wasm -// --wasm-execution=compiled -// --heap-pages=4096 -// --output=./vesting/src/weights.rs -// --template -// ../templates/orml-weight-template.hbs - - -#![cfg_attr(rustfmt, rustfmt_skip)] -#![allow(unused_parens)] -#![allow(unused_imports)] -#![allow(clippy::unnecessary_cast)] - -use frame_support::{traits::Get, weights::{Weight, constants::RocksDbWeight}}; -use sp_std::marker::PhantomData; - -/// Weight functions needed for orml_vesting. -pub trait WeightInfo { - fn vested_transfer() -> Weight; - fn claim(i: u32, ) -> Weight; - fn update_vesting_schedules(i: u32, ) -> Weight; -} - -/// 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)) - } - fn claim(i: u32, ) -> Weight { - (31_747_000 as Weight) - // 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)) - } - fn update_vesting_schedules(i: u32, ) -> Weight { - (29_457_000 as Weight) - // 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)) - } -} --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -362,7 +362,7 @@ default-features = false [dependencies.orml-vesting] -path = '../pallets/orml-vesting' +git = 'https://github.com/UniqueNetwork/open-runtime-module-library' version = "0.4.1-dev" default-features = false -- gitstuff