Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all 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
1 change: 1 addition & 0 deletions bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -601,6 +601,7 @@ impl pallet_treasury::Trait for Runtime {
type ProposalBondMinimum = ProposalBondMinimum;
type SpendPeriod = SpendPeriod;
type Burn = Burn;
type BurnDestination = ();
type WeightInfo = ();
}

Expand Down
16 changes: 15 additions & 1 deletion frame/society/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -264,11 +264,12 @@ use frame_support::{decl_error, decl_module, decl_storage, decl_event, ensure, d
use frame_support::weights::Weight;
use frame_support::traits::{
Currency, ReservableCurrency, Randomness, Get, ChangeMembers, BalanceStatus,
ExistenceRequirement::AllowDeath, EnsureOrigin
ExistenceRequirement::AllowDeath, EnsureOrigin, OnUnbalanced, Imbalance
};
use frame_system::{self as system, ensure_signed, ensure_root};

type BalanceOf<T, I> = <<T as Trait<I>>::Currency as Currency<<T as system::Trait>::AccountId>>::Balance;
type NegativeImbalanceOf<T> = <<T as Trait>::Currency as Currency<<T as frame_system::Trait>::AccountId>>::NegativeImbalance;

/// The module's configuration trait.
pub trait Trait<I=DefaultInstance>: system::Trait {
Expand Down Expand Up @@ -1143,6 +1144,8 @@ decl_event! {
NewMaxMembers(u32),
/// Society is unfounded.
Unfounded(AccountId),
/// Some funds were deposited into the society account.
Deposit(Balance),
}
}

Expand Down Expand Up @@ -1665,3 +1668,14 @@ impl<T: Trait<I>, I: Instance> Module<T, I> {
}
}
}

impl<T: Trait> OnUnbalanced<NegativeImbalanceOf<T>> for Module<T> {
fn on_nonzero_unbalanced(amount: NegativeImbalanceOf<T>) {
let numeric_amount = amount.peek();

// Must resolve into existing but better to be safe.
let _ = T::Currency::resolve_creating(&Self::account_id(), amount);

Self::deposit_event(RawEvent::Deposit(numeric_amount));
}
}
8 changes: 8 additions & 0 deletions frame/support/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -897,6 +897,14 @@ pub trait Currency<AccountId> {
/// in the case of overflow.
fn issue(amount: Self::Balance) -> Self::NegativeImbalance;

/// Produce a pair of imbalances that cancel each other out exactly.
///
/// This is just the same as burning and issuing the same amount and has no effect on the
/// total issuance.
fn pair(amount: Self::Balance) -> (Self::PositiveImbalance, Self::NegativeImbalance) {
(Self::burn(amount.clone()), Self::issue(amount))
}

/// The 'free' balance of a given account.
///
/// This is the only balance that matters in terms of most operations on tokens. It alone
Expand Down
8 changes: 7 additions & 1 deletion frame/treasury/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@ pub trait Trait: frame_system::Trait {
/// Percentage of spare funds (if any) that are burnt per spend period.
type Burn: Get<Permill>;

/// Handler for the unbalanced decrease when treasury funds are burned.
type BurnDestination: OnUnbalanced<NegativeImbalanceOf<Self>>;

/// Weight information for extrinsics in this pallet.
type WeightInfo: WeightInfo;
}
Expand Down Expand Up @@ -771,7 +774,10 @@ impl<T: Trait> Module<T> {
// burn some proportion of the remaining budget if we run a surplus.
let burn = (T::Burn::get() * budget_remaining).min(budget_remaining);
budget_remaining -= burn;
imbalance.subsume(T::Currency::burn(burn));

let (debit, credit) = T::Currency::pair(burn);
imbalance.subsume(debit);
T::BurnDestination::on_unbalanced(credit);
Self::deposit_event(RawEvent::Burnt(burn))
}

Expand Down
1 change: 1 addition & 0 deletions frame/treasury/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ impl Trait for Test {
type ProposalBondMinimum = ProposalBondMinimum;
type SpendPeriod = SpendPeriod;
type Burn = Burn;
type BurnDestination = (); // Just gets burned.
type WeightInfo = ();
}
type System = frame_system::Module<Test>;
Expand Down
57 changes: 53 additions & 4 deletions primitives/arithmetic/src/per_things.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1170,6 +1170,51 @@ macro_rules! implement_per_thing {
};
}

macro_rules! implement_per_thing_with_perthousand {
(
$name:ident,
$test_mod:ident,
$pt_test_mod:ident,
[$($test_units:tt),+],
$max:tt,
$type:ty,
$upper_type:ty,
$title:expr $(,)?
) => {
implement_per_thing! {
$name, $test_mod, [ $( $test_units ),+ ], $max, $type, $upper_type, $title,
}
impl $name {
/// Converts a percent into `Self`. Equal to `x / 1000`.
///
/// This can be created at compile time.
pub const fn from_perthousand(x: $type) -> Self {
Self(([x, 1000][(x > 1000) as usize] as $upper_type * $max as $upper_type / 1000) as $type)
}
}
#[cfg(test)]
mod $pt_test_mod {
use super::$name;
use crate::traits::Zero;

#[test]
fn from_perthousand_works() {
// some really basic stuff
assert_eq!($name::from_perthousand(00), $name::from_parts(Zero::zero()));
assert_eq!($name::from_perthousand(100), $name::from_parts($max / 10));
assert_eq!($name::from_perthousand(1000), $name::from_parts($max));
assert_eq!($name::from_perthousand(2000), $name::from_parts($max));
}

#[test]
#[allow(unused)]
fn const_fns_work() {
const C1: $name = $name::from_perthousand(500);
}
}
}
}

implement_per_thing!(
Percent,
test_per_cent,
Expand All @@ -1179,36 +1224,40 @@ implement_per_thing!(
u16,
"_Percent_",
);
implement_per_thing!(
implement_per_thing_with_perthousand!(
PerU16,
test_peru16,
test_peru16_extra,
[u32, u64, u128],
65535_u16,
u16,
u32,
"_Parts per 65535_",
);
implement_per_thing!(
implement_per_thing_with_perthousand!(
Permill,
test_permill,
test_permill_extra,
[u32, u64, u128],
1_000_000u32,
u32,
u64,
"_Parts per Million_",
);
implement_per_thing!(
implement_per_thing_with_perthousand!(
Perbill,
test_perbill,
test_perbill_extra,
[u32, u64, u128],
1_000_000_000u32,
u32,
u64,
"_Parts per Billion_",
);
implement_per_thing!(
implement_per_thing_with_perthousand!(
Perquintill,
test_perquintill,
test_perquintill_extra,
[u64, u128],
1_000_000_000_000_000_000u64,
u64,
Expand Down