diff --git a/node/runtime/src/impls.rs b/node/runtime/src/impls.rs index 69b782e807dfc..f6d31cc22507b 100644 --- a/node/runtime/src/impls.rs +++ b/node/runtime/src/impls.rs @@ -25,7 +25,7 @@ use crate::{Balances, System, Authorship, MaximumBlockWeight, NegativeImbalance} pub struct Author; impl OnUnbalanced for Author { - fn on_unbalanced(amount: NegativeImbalance) { + fn on_nonzero_unbalanced(amount: NegativeImbalance) { Balances::resolve_creating(&Authorship::author(), amount); } } diff --git a/srml/balances/src/lib.rs b/srml/balances/src/lib.rs index e22dba3fee477..cd6c84492276c 100644 --- a/srml/balances/src/lib.rs +++ b/srml/balances/src/lib.rs @@ -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, }, @@ -603,7 +603,7 @@ impl, I: Instance> Module { mod imbalances { use super::{ result, Subtrait, DefaultInstance, Imbalance, Trait, Zero, Instance, Saturating, - StorageValue, + StorageValue, TryDrop, }; use rstd::mem; @@ -631,6 +631,12 @@ mod imbalances { } } + impl, I: Instance> TryDrop for PositiveImbalance { + fn try_drop(self) -> result::Result<(), Self> { + self.drop_zero() + } + } + impl, I: Instance> Imbalance for PositiveImbalance { type Opposite = NegativeImbalance; @@ -676,6 +682,12 @@ mod imbalances { } } + impl, I: Instance> TryDrop for NegativeImbalance { + fn try_drop(self) -> result::Result<(), Self> { + self.drop_zero() + } + } + impl, I: Instance> Imbalance for NegativeImbalance { type Opposite = PositiveImbalance; diff --git a/srml/generic-asset/src/lib.rs b/srml/generic-asset/src/lib.rs index fda3b6ae048f4..a552880a34b62 100644 --- a/srml/generic-asset/src/lib.rs +++ b/srml/generic-asset/src/lib.rs @@ -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::*; @@ -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, }; @@ -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 @@ -899,6 +902,16 @@ mod imbalances { } } + impl TryDrop for PositiveImbalance + where + T: Subtrait, + U: AssetIdProvider, + { + fn try_drop(self) -> result::Result<(), Self> { + self.drop_zero() + } + } + impl Imbalance for PositiveImbalance where T: Subtrait, @@ -948,6 +961,16 @@ mod imbalances { } } + impl TryDrop for NegativeImbalance + where + T: Subtrait, + U: AssetIdProvider, + { + fn try_drop(self) -> result::Result<(), Self> { + self.drop_zero() + } + } + impl Imbalance for NegativeImbalance where T: Subtrait, diff --git a/srml/support/src/traits.rs b/srml/support/src/traits.rs index 297e128ebc2f0..c6572a3f94168 100644 --- a/srml/support/src/traits.rs +++ b/srml/support/src/traits.rs @@ -132,13 +132,19 @@ pub trait KeyOwnerProofSystem { /// /// - Someone got slashed. /// - Someone paid for a transaction to be included. -pub trait OnUnbalanced { +pub trait OnUnbalanced { /// 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 OnUnbalanced for () { - fn on_unbalanced(amount: Imbalance) { drop(amount); } +impl OnUnbalanced for () { + fn on_nonzero_unbalanced(amount: Imbalance) { drop(amount); } } /// Simple boolean for whether an account needs to be kept in existence. @@ -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 @@ -182,14 +194,14 @@ pub enum ExistenceRequirement { /// /// You can always retrieve the raw balance value using `peek`. #[must_use] -pub trait Imbalance: Sized { +pub trait Imbalance: Sized + TryDrop { /// The oppositely imbalanced type. They come in pairs. type Opposite: Imbalance; /// 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 @@ -297,7 +309,7 @@ impl< Target2: OnUnbalanced, > OnUnbalanced for SplitTwoWays { - 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); diff --git a/srml/treasury/src/lib.rs b/srml/treasury/src/lib.rs index e07efc396dda3..4a613dfb7859c 100644 --- a/srml/treasury/src/lib.rs +++ b/srml/treasury/src/lib.rs @@ -337,7 +337,7 @@ impl Module { } impl OnUnbalanced> for Module { - fn on_unbalanced(amount: NegativeImbalanceOf) { + fn on_nonzero_unbalanced(amount: NegativeImbalanceOf) { let numeric_amount = amount.peek(); // Must resolve into existing but better to be safe.