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
2 changes: 1 addition & 1 deletion node/runtime/src/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use crate::{Balances, System, Authorship, MaximumBlockWeight, NegativeImbalance}

pub struct Author;
impl OnUnbalanced<NegativeImbalance> for Author {
fn on_unbalanced(amount: NegativeImbalance) {
fn on_nonzero_unbalanced(amount: NegativeImbalance) {
Balances::resolve_creating(&Authorship::author(), amount);
}
}
Expand Down
16 changes: 14 additions & 2 deletions srml/balances/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ use codec::{Codec, Encode, Decode};
use support::{
StorageValue, Parameter, decl_event, decl_storage, decl_module,
traits::{
UpdateBalanceOutcome, Currency, OnFreeBalanceZero, OnUnbalanced,
UpdateBalanceOutcome, Currency, OnFreeBalanceZero, OnUnbalanced, TryDrop,
WithdrawReason, WithdrawReasons, LockIdentifier, LockableCurrency, ExistenceRequirement,
Imbalance, SignedImbalance, ReservableCurrency, Get,
},
Expand Down Expand Up @@ -603,7 +603,7 @@ impl<T: Trait<I>, I: Instance> Module<T, I> {
mod imbalances {
use super::{
result, Subtrait, DefaultInstance, Imbalance, Trait, Zero, Instance, Saturating,
StorageValue,
StorageValue, TryDrop,
};
use rstd::mem;

Expand Down Expand Up @@ -631,6 +631,12 @@ mod imbalances {
}
}

impl<T: Trait<I>, I: Instance> TryDrop for PositiveImbalance<T, I> {
fn try_drop(self) -> result::Result<(), Self> {
self.drop_zero()
}
}

impl<T: Trait<I>, I: Instance> Imbalance<T::Balance> for PositiveImbalance<T, I> {
type Opposite = NegativeImbalance<T, I>;

Expand Down Expand Up @@ -676,6 +682,12 @@ mod imbalances {
}
}

impl<T: Trait<I>, I: Instance> TryDrop for NegativeImbalance<T, I> {
fn try_drop(self) -> result::Result<(), Self> {
self.drop_zero()
}
}

impl<T: Trait<I>, I: Instance> Imbalance<T::Balance> for NegativeImbalance<T, I> {
type Opposite = PositiveImbalance<T, I>;

Expand Down
29 changes: 26 additions & 3 deletions srml/generic-asset/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,8 @@ use codec::{Decode, Encode, HasCompact, Input, Output, Error};

use sr_primitives::RuntimeDebug;
use sr_primitives::traits::{
CheckedAdd, CheckedSub, MaybeSerializeDeserialize, Member, One, Saturating, SimpleArithmetic, Zero, Bounded
CheckedAdd, CheckedSub, MaybeSerializeDeserialize, Member, One, Saturating, SimpleArithmetic,
Zero, Bounded,
};

use rstd::prelude::*;
Expand All @@ -165,7 +166,7 @@ use support::{
decl_event, decl_module, decl_storage, ensure,
traits::{
Currency, ExistenceRequirement, Imbalance, LockIdentifier, LockableCurrency, ReservableCurrency,
SignedImbalance, UpdateBalanceOutcome, WithdrawReason, WithdrawReasons,
SignedImbalance, UpdateBalanceOutcome, WithdrawReason, WithdrawReasons, TryDrop,
},
Parameter, StorageMap,
};
Expand Down Expand Up @@ -862,7 +863,9 @@ pub trait AssetIdProvider {
// wrapping these imbalanes in a private module is necessary to ensure absolute privacy
// of the inner member.
mod imbalances {
use super::{result, AssetIdProvider, Imbalance, Saturating, StorageMap, Subtrait, Zero};
use super::{
result, AssetIdProvider, Imbalance, Saturating, StorageMap, Subtrait, Zero, TryDrop
};
use rstd::mem;

/// Opaque, move-only struct with private fields that serves as a token denoting that
Expand Down Expand Up @@ -899,6 +902,16 @@ mod imbalances {
}
}

impl<T, U> TryDrop for PositiveImbalance<T, U>
where
T: Subtrait,
U: AssetIdProvider<AssetId = T::AssetId>,
{
fn try_drop(self) -> result::Result<(), Self> {
self.drop_zero()
}
}

impl<T, U> Imbalance<T::Balance> for PositiveImbalance<T, U>
where
T: Subtrait,
Expand Down Expand Up @@ -948,6 +961,16 @@ mod imbalances {
}
}

impl<T, U> TryDrop for NegativeImbalance<T, U>
where
T: Subtrait,
U: AssetIdProvider<AssetId = T::AssetId>,
{
fn try_drop(self) -> result::Result<(), Self> {
self.drop_zero()
}
}

impl<T, U> Imbalance<T::Balance> for NegativeImbalance<T, U>
where
T: Subtrait,
Expand Down
26 changes: 19 additions & 7 deletions srml/support/src/traits.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,13 +132,19 @@ pub trait KeyOwnerProofSystem<Key> {
///
/// - Someone got slashed.
/// - Someone paid for a transaction to be included.
pub trait OnUnbalanced<Imbalance> {
pub trait OnUnbalanced<Imbalance: TryDrop> {
/// Handler for some imbalance. Infallible.
fn on_unbalanced(amount: Imbalance);
fn on_unbalanced(amount: Imbalance) {
amount.try_drop().unwrap_or_else(Self::on_nonzero_unbalanced)
}

/// Actually handle a non-zero imbalance. You probably want to implement this rather than
/// `on_unbalanced`.
fn on_nonzero_unbalanced(amount: Imbalance);
}

impl<Imbalance> OnUnbalanced<Imbalance> for () {
fn on_unbalanced(amount: Imbalance) { drop(amount); }
impl<Imbalance: TryDrop> OnUnbalanced<Imbalance> for () {
fn on_nonzero_unbalanced(amount: Imbalance) { drop(amount); }
}

/// Simple boolean for whether an account needs to be kept in existence.
Expand All @@ -153,6 +159,12 @@ pub enum ExistenceRequirement {
AllowDeath,
}

/// A type for which some values make sense to be able to drop without further consideration.
pub trait TryDrop: Sized {
/// Drop an instance cleanly. Only works if its value represents "no-operation".
fn try_drop(self) -> Result<(), Self>;
}

/// A trait for a not-quite Linear Type that tracks an imbalance.
///
/// Functions that alter account balances return an object of this trait to
Expand Down Expand Up @@ -182,14 +194,14 @@ pub enum ExistenceRequirement {
///
/// You can always retrieve the raw balance value using `peek`.
#[must_use]
pub trait Imbalance<Balance>: Sized {
pub trait Imbalance<Balance>: Sized + TryDrop {
/// The oppositely imbalanced type. They come in pairs.
type Opposite: Imbalance<Balance>;

/// The zero imbalance. Can be destroyed with `drop_zero`.
fn zero() -> Self;

/// Drop an instance cleanly. Only works if its `value()` is zero.
/// Drop an instance cleanly. Only works if its `self.value()` is zero.
fn drop_zero(self) -> Result<(), Self>;

/// Consume `self` and return two independent instances; the first
Expand Down Expand Up @@ -297,7 +309,7 @@ impl<
Target2: OnUnbalanced<I>,
> OnUnbalanced<I> for SplitTwoWays<Balance, I, Part1, Target1, Part2, Target2>
{
fn on_unbalanced(amount: I) {
fn on_nonzero_unbalanced(amount: I) {
let total: u32 = Part1::VALUE + Part2::VALUE;
let amount1 = amount.peek().saturating_mul(Part1::VALUE.into()) / total.into();
let (imb1, imb2) = amount.split(amount1);
Expand Down
2 changes: 1 addition & 1 deletion srml/treasury/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ impl<T: Trait> Module<T> {
}

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

// Must resolve into existing but better to be safe.
Expand Down