Introduce VestingCurrency trait (#4257)

* Introduce `VestingCurrency` trait

* Return error if account already has vesting schedule
This commit is contained in:
Shawn Tabrizi
2019-12-01 20:52:00 +01:00
committed by Gavin Wood
parent bd4f1fc54b
commit 40f6d05a4c
2 changed files with 68 additions and 14 deletions
+45 -14
View File
@@ -167,7 +167,7 @@ use support::{
traits::{
UpdateBalanceOutcome, Currency, OnFreeBalanceZero, OnUnbalanced, TryDrop,
WithdrawReason, WithdrawReasons, LockIdentifier, LockableCurrency, ExistenceRequirement,
Imbalance, SignedImbalance, ReservableCurrency, Get,
Imbalance, SignedImbalance, ReservableCurrency, Get, VestingCurrency,
},
weights::SimpleDispatchInfo,
dispatch::Result,
@@ -510,19 +510,6 @@ decl_module! {
}
impl<T: Trait<I>, I: Instance> Module<T, I> {
// PUBLIC IMMUTABLES
/// Get the amount that is currently being vested and cannot be transferred out of this account.
pub fn vesting_balance(who: &T::AccountId) -> T::Balance {
if let Some(v) = Self::vesting(who) {
Self::free_balance(who)
.min(v.locked_at(<system::Module<T>>::block_number()))
} else {
Zero::zero()
}
}
// PRIVATE MUTABLES
/// Set the reserved balance of an account to some new value. Will enforce `ExistentialDeposit`
@@ -1209,6 +1196,50 @@ where
}
}
impl<T: Trait<I>, I: Instance> VestingCurrency<T::AccountId> for Module<T, I>
where
T::Balance: MaybeSerializeDeserialize + Debug
{
type Moment = T::BlockNumber;
/// Get the amount that is currently being vested and cannot be transferred out of this account.
fn vesting_balance(who: &T::AccountId) -> T::Balance {
if let Some(v) = Self::vesting(who) {
Self::free_balance(who)
.min(v.locked_at(<system::Module<T>>::block_number()))
} else {
Zero::zero()
}
}
/// Adds a vesting schedule to a given account.
///
/// If there already exists a vesting schedule for the given account, an `Err` is returned
/// and nothing is updated.
fn add_vesting_schedule(
who: &T::AccountId,
locked: T::Balance,
per_block: T::Balance,
starting_block: T::BlockNumber
) -> Result {
if <Vesting<T, I>>::exists(who) {
return Err("A vesting schedule already exists for this account.");
}
let vesting_schedule = VestingSchedule {
locked,
per_block,
starting_block
};
<Vesting<T, I>>::insert(who, vesting_schedule);
Ok(())
}
/// Remove a vesting schedule for a given account.
fn remove_vesting_schedule(who: &T::AccountId) {
<Vesting<T, I>>::remove(who);
}
}
impl<T: Trait<I>, I: Instance> IsDeadAccount<T::AccountId> for Module<T, I>
where
T::Balance: MaybeSerializeDeserialize + Debug
+23
View File
@@ -602,6 +602,29 @@ pub trait LockableCurrency<AccountId>: Currency<AccountId> {
);
}
/// A currency whose accounts can have balances which vest over time.
pub trait VestingCurrency<AccountId>: Currency<AccountId> {
/// The quantity used to denote time; usually just a `BlockNumber`.
type Moment;
/// Get the amount that is currently being vested and cannot be transferred out of this account.
fn vesting_balance(who: &AccountId) -> Self::Balance;
/// Adds a vesting schedule to a given account.
///
/// If there already exists a vesting schedule for the given account, an `Err` is returned
/// and nothing is updated.
fn add_vesting_schedule(
who: &AccountId,
locked: Self::Balance,
per_block: Self::Balance,
starting_block: Self::Moment,
) -> result::Result<(), &'static str>;
/// Remove a vesting schedule for a given account.
fn remove_vesting_schedule(who: &AccountId);
}
bitmask! {
/// Reasons for moving funds out of an account.
#[derive(Encode, Decode)]