Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

API for registering inactive funds #12813

Merged
merged 7 commits into from
Dec 3, 2022
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 32 additions & 1 deletion frame/balances/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@
#[macro_use]
mod tests;
mod benchmarking;
pub mod migration;
mod tests_composite;
mod tests_local;
#[cfg(test)]
Expand Down Expand Up @@ -497,6 +498,13 @@ pub mod pallet {
#[pallet::whitelist_storage]
pub type TotalIssuance<T: Config<I>, I: 'static = ()> = StorageValue<_, T::Balance, ValueQuery>;

/// The total units of outstanding deactivated balance in the system.
#[pallet::storage]
#[pallet::getter(fn inactive_issuance)]
#[pallet::whitelist_storage]
pub type InactiveIssuance<T: Config<I>, I: 'static = ()> =
StorageValue<_, T::Balance, ValueQuery>;

/// The Balances pallet example of storing the balance of an account.
///
/// # Example
Expand Down Expand Up @@ -1067,6 +1075,9 @@ impl<T: Config<I>, I: 'static> fungible::Inspect<T::AccountId> for Pallet<T, I>
fn total_issuance() -> Self::Balance {
TotalIssuance::<T, I>::get()
}
fn active_issuance() -> Self::Balance {
TotalIssuance::<T, I>::get().saturating_sub(InactiveIssuance::<T, I>::get())
}
fn minimum_balance() -> Self::Balance {
T::ExistentialDeposit::get()
}
Expand Down Expand Up @@ -1145,6 +1156,14 @@ impl<T: Config<I>, I: 'static> fungible::Transfer<T::AccountId> for Pallet<T, I>
let er = if keep_alive { KeepAlive } else { AllowDeath };
<Self as Currency<T::AccountId>>::transfer(source, dest, amount, er).map(|_| amount)
}

fn deactivate(amount: Self::Balance) {
InactiveIssuance::<T, I>::mutate(|b| b.saturating_accrue(amount));
}

fn reactivate(amount: Self::Balance) {
InactiveIssuance::<T, I>::mutate(|b| b.saturating_reduce(amount));
}
}

impl<T: Config<I>, I: 'static> fungible::Unbalanced<T::AccountId> for Pallet<T, I> {
Expand Down Expand Up @@ -1418,7 +1437,19 @@ where
}

fn total_issuance() -> Self::Balance {
<TotalIssuance<T, I>>::get()
TotalIssuance::<T, I>::get()
}

fn active_issuance() -> Self::Balance {
<Self as fungible::Inspect<T::AccountId>>::active_issuance()
}

fn deactivate(amount: Self::Balance) {
<Self as fungible::Transfer<T::AccountId>>::deactivate(amount);
}

fn reactivate(amount: Self::Balance) {
<Self as fungible::Transfer<T::AccountId>>::reactivate(amount);
}

fn minimum_balance() -> Self::Balance {
Expand Down
51 changes: 51 additions & 0 deletions frame/balances/src/migration.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// Copyright 2017-2020 Parity Technologies (UK) Ltd.
// This file is part of Polkadot.

// Polkadot is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Polkadot is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.

use super::*;
use frame_support::{pallet_prelude::*, traits::OnRuntimeUpgrade, weights::Weight};

// NOTE: This must be used alongside any accounts whose balances are expected to be inactive.
// Generally this will be used for the XCM teleport checking account.
pub struct MigrateToTrackInactive<T: Config, A: Get<T::AccountId>>(
sp_std::marker::PhantomData<(T, A)>,
);
impl<T: Config, A: Get<T::AccountId>> OnRuntimeUpgrade for MigrateToTrackInactive<T, A> {
fn on_runtime_upgrade() -> Weight {
let current_version = Pallet::<T>::current_storage_version();
let onchain_version = Pallet::<T>::on_chain_storage_version();

if onchain_version == 0 && current_version == 1 {
let b = Pallet::<T>::total_balance(&A::get());
Pallet::<T>::deactivate(b);
current_version.put::<Pallet<T>>();
log::info!(target: "runtime::balances", "Storage to version {:?}", current_version);
T::DbWeight::get().reads_writes(3, 3)
} else {
log::info!(target: "runtime::balances", "Migration did not execute. This probably should be removed");
T::DbWeight::get().reads(1)
gavofyork marked this conversation as resolved.
Show resolved Hide resolved
}
}

#[cfg(feature = "try-runtime")]
fn pre_upgrade() -> Result<Vec<u8>, &'static str> {
Ok(vec![])
}

#[cfg(feature = "try-runtime")]
fn post_upgrade(total: Vec<u8>) -> Result<(), &'static str> {
Ok(())
}
}
21 changes: 21 additions & 0 deletions frame/support/src/traits/tokens/currency.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,18 @@ pub trait Currency<AccountId> {
/// The total amount of issuance in the system.
fn total_issuance() -> Self::Balance;

/// The total amount of issuance in the system excluding those which are controlled by the
/// system.
fn active_issuance() -> Self::Balance {
Self::total_issuance()
}

/// Reduce the active issuance by some amount.
fn deactivate(_: Self::Balance) {}

/// Increase the active issuance by some amount, up to the outstanding amount reduced.
fn reactivate(_: Self::Balance) {}

/// The minimum balance any single account may have. This is equivalent to the `Balances`
/// module's `ExistentialDeposit`.
fn minimum_balance() -> Self::Balance;
Expand Down Expand Up @@ -212,6 +224,15 @@ impl<C: Currency<A>, A> Get<C::Balance> for TotalIssuanceOf<C, A> {
}
}

/// A non-const `Get` implementation parameterised by a `Currency` impl which provides the result
/// of `active_issuance`.
pub struct ActiveIssuanceOf<C: Currency<A>, A>(sp_std::marker::PhantomData<(C, A)>);
impl<C: Currency<A>, A> Get<C::Balance> for ActiveIssuanceOf<C, A> {
fn get() -> C::Balance {
C::active_issuance()
}
}

#[cfg(feature = "std")]
impl<AccountId> Currency<AccountId> for () {
type Balance = u32;
Expand Down
21 changes: 21 additions & 0 deletions frame/support/src/traits/tokens/fungible.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,12 @@ pub trait Inspect<AccountId> {
/// The total amount of issuance in the system.
fn total_issuance() -> Self::Balance;

/// The total amount of issuance in the system excluding those which are controlled by the
/// system.
fn active_issuance() -> Self::Balance {
Self::total_issuance()
}

/// The minimum balance any single account may have.
fn minimum_balance() -> Self::Balance;

Expand Down Expand Up @@ -120,6 +126,12 @@ pub trait Transfer<AccountId>: Inspect<AccountId> {
amount: Self::Balance,
keep_alive: bool,
) -> Result<Self::Balance, DispatchError>;

/// Reduce the active issuance by some amount.
fn deactivate(_: Self::Balance) {}

/// Increase the active issuance by some amount, up to the outstanding amount reduced.
fn reactivate(_: Self::Balance) {}
}

/// Trait for inspecting a fungible asset which can be reserved.
Expand Down Expand Up @@ -213,6 +225,9 @@ impl<
fn total_issuance() -> Self::Balance {
<F as fungibles::Inspect<AccountId>>::total_issuance(A::get())
}
fn active_issuance() -> Self::Balance {
<F as fungibles::Inspect<AccountId>>::active_issuance(A::get())
}
fn minimum_balance() -> Self::Balance {
<F as fungibles::Inspect<AccountId>>::minimum_balance(A::get())
}
Expand Down Expand Up @@ -258,6 +273,12 @@ impl<
) -> Result<Self::Balance, DispatchError> {
<F as fungibles::Transfer<AccountId>>::transfer(A::get(), source, dest, amount, keep_alive)
}
fn deactivate(amount: Self::Balance) {
<F as fungibles::Transfer<AccountId>>::deactivate(A::get(), amount)
}
fn reactivate(amount: Self::Balance) {
<F as fungibles::Transfer<AccountId>>::reactivate(A::get(), amount)
}
}

impl<
Expand Down
12 changes: 12 additions & 0 deletions frame/support/src/traits/tokens/fungibles.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ pub trait Inspect<AccountId> {
/// The total amount of issuance in the system.
fn total_issuance(asset: Self::AssetId) -> Self::Balance;

/// The total amount of issuance in the system excluding those which are controlled by the
/// system.
fn active_issuance(asset: Self::AssetId) -> Self::Balance {
Self::total_issuance(asset)
}

/// The minimum balance any single account may have.
fn minimum_balance(asset: Self::AssetId) -> Self::Balance;

Expand Down Expand Up @@ -177,6 +183,12 @@ pub trait Transfer<AccountId>: Inspect<AccountId> {
amount: Self::Balance,
keep_alive: bool,
) -> Result<Self::Balance, DispatchError>;

/// Reduce the active issuance by some amount.
fn deactivate(_: Self::AssetId, _: Self::Balance) {}

/// Increase the active issuance by some amount, up to the outstanding amount reduced.
fn reactivate(_: Self::AssetId, _: Self::Balance) {}
}

/// Trait for inspecting a set of named fungible assets which can be placed on hold.
Expand Down
15 changes: 15 additions & 0 deletions frame/treasury/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ pub mod pallet {
use super::*;
use frame_support::pallet_prelude::*;
use frame_system::pallet_prelude::*;
use sp_runtime::traits::CheckedSub;

#[pallet::pallet]
#[pallet::generate_store(pub(super) trait Store)]
Expand Down Expand Up @@ -223,6 +224,10 @@ pub mod pallet {
OptionQuery,
>;

/// The amount which has been reported as inactive to Currency.
#[pallet::storage]
pub type Inactive<T: Config<I>, I: 'static = ()> = StorageValue<_, BalanceOf<T, I>, ValueQuery>;

/// Proposal indices that have been approved but not yet awarded.
#[pallet::storage]
#[pallet::getter(fn approvals)]
Expand Down Expand Up @@ -316,6 +321,16 @@ pub mod pallet {
/// - The weight is overestimated if some approvals got missed.
/// # </weight>
fn on_initialize(n: T::BlockNumber) -> Weight {
let pot = Self::pot();
let deactivated = Inactive::<T, I>::get();
match pot.checked_sub(&deactivated) {
Some(x) if !x.is_zero() => T::Currency::deactivate(x),
gavofyork marked this conversation as resolved.
Show resolved Hide resolved
_ => match deactivated.checked_sub(&pot) {
Some(x) if !x.is_zero() => T::Currency::reactivate(x),
_ => {},
},
}

// Check to see if we should spend some funds!
if (n % T::SpendPeriod::get()).is_zero() {
Self::spend_funds()
Expand Down