referrerpolicy=no-referrer-when-downgrade

frame_support/traits/tokens/imbalance/
on_unbalanced.rs

1// This file is part of Substrate.
2
3// Copyright (C) Parity Technologies (UK) Ltd.
4// SPDX-License-Identifier: Apache-2.0
5
6// Licensed under the Apache License, Version 2.0 (the "License");
7// you may not use this file except in compliance with the License.
8// You may obtain a copy of the License at
9//
10// 	http://www.apache.org/licenses/LICENSE-2.0
11//
12// Unless required by applicable law or agreed to in writing, software
13// distributed under the License is distributed on an "AS IS" BASIS,
14// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15// See the License for the specific language governing permissions and
16// limitations under the License.
17
18//! Trait for handling imbalances.
19
20use core::marker::PhantomData;
21use frame_support::traits::{fungible, fungibles, misc::TryDrop};
22use sp_core::TypedGet;
23
24/// Handler for when some currency "account" decreased in balance for
25/// some reason.
26///
27/// The only reason at present for an increase would be for validator rewards, but
28/// there may be other reasons in the future or for other chains.
29///
30/// Reasons for decreases include:
31///
32/// - Someone got slashed.
33/// - Someone paid for a transaction to be included.
34pub trait OnUnbalanced<Imbalance: TryDrop> {
35	/// Handler for some imbalances. The different imbalances might have different origins or
36	/// meanings, dependent on the context. Will default to simply calling on_unbalanced for all
37	/// of them. Infallible.
38	fn on_unbalanceds(mut amounts: impl Iterator<Item = Imbalance>)
39	where
40		Imbalance: crate::traits::tokens::imbalance::TryMerge,
41	{
42		let mut sum: Option<Imbalance> = None;
43		while let Some(next) = amounts.next() {
44			sum = match sum {
45				Some(sum) => match sum.try_merge(next) {
46					Ok(sum) => Some(sum),
47					Err((sum, next)) => {
48						Self::on_unbalanced(next);
49						Some(sum)
50					},
51				},
52				None => Some(next),
53			}
54		}
55		if let Some(sum) = sum {
56			Self::on_unbalanced(sum)
57		}
58	}
59
60	/// Handler for some imbalance. Infallible.
61	fn on_unbalanced(amount: Imbalance) {
62		amount.try_drop().unwrap_or_else(Self::on_nonzero_unbalanced)
63	}
64
65	/// Actually handle a non-zero imbalance. You probably want to implement this rather than
66	/// `on_unbalanced`.
67	fn on_nonzero_unbalanced(amount: Imbalance) {
68		drop(amount);
69	}
70}
71
72impl<Imbalance: TryDrop> OnUnbalanced<Imbalance> for () {}
73
74/// Resolves received asset credit to account `A`, implementing [`OnUnbalanced`].
75///
76/// Credits that cannot be resolved to account `A` are dropped. This may occur if the account for
77/// address `A` does not exist and the existential deposit requirement is not met.
78pub struct ResolveTo<A, F>(PhantomData<(A, F)>);
79impl<A: TypedGet, F: fungible::Balanced<A::Type>> OnUnbalanced<fungible::Credit<A::Type, F>>
80	for ResolveTo<A, F>
81{
82	fn on_nonzero_unbalanced(credit: fungible::Credit<A::Type, F>) {
83		let _ = F::resolve(&A::get(), credit).map_err(|c| drop(c));
84	}
85}
86
87/// Resolves received asset credit to account `A`, implementing [`OnUnbalanced`].
88///
89/// Credits that cannot be resolved to account `A` are dropped. This may occur if the account for
90/// address `A` does not exist and the existential deposit requirement is not met.
91pub struct ResolveAssetTo<A, F>(PhantomData<(A, F)>);
92impl<A: TypedGet, F: fungibles::Balanced<A::Type>> OnUnbalanced<fungibles::Credit<A::Type, F>>
93	for ResolveAssetTo<A, F>
94{
95	fn on_nonzero_unbalanced(credit: fungibles::Credit<A::Type, F>) {
96		let _ = F::resolve(&A::get(), credit).map_err(|c| drop(c));
97	}
98}