referrerpolicy=no-referrer-when-downgrade

frame_support/traits/tokens/
pay.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//! The Pay trait and associated types.
19
20use codec::{Decode, Encode, FullCodec, MaxEncodedLen};
21use core::fmt::Debug;
22use scale_info::TypeInfo;
23use sp_core::{RuntimeDebug, TypedGet};
24use sp_runtime::DispatchError;
25
26use super::{fungible, fungibles, Balance, Preservation::Expendable};
27
28/// Can be implemented by `PayFromAccount` using a `fungible` impl, but can also be implemented with
29/// XCM/Asset and made generic over assets.
30pub trait Pay {
31	/// The type by which we measure units of the currency in which we make payments.
32	type Balance: Balance;
33	/// The type by which we identify the beneficiaries to whom a payment may be made.
34	type Beneficiary;
35	/// The type for the kinds of asset that are going to be paid.
36	///
37	/// The unit type can be used here to indicate there's only one kind of asset to do payments
38	/// with. When implementing, it should be clear from the context what that asset is.
39	type AssetKind;
40	/// An identifier given to an individual payment.
41	type Id: FullCodec + MaxEncodedLen + TypeInfo + Clone + Eq + PartialEq + Debug + Copy;
42	/// An error which could be returned by the Pay type
43	type Error: Debug;
44	/// Make a payment and return an identifier for later evaluation of success in some off-chain
45	/// mechanism (likely an event, but possibly not on this chain).
46	fn pay(
47		who: &Self::Beneficiary,
48		asset_kind: Self::AssetKind,
49		amount: Self::Balance,
50	) -> Result<Self::Id, Self::Error>;
51	/// Check how a payment has proceeded. `id` must have been previously returned by `pay` for
52	/// the result of this call to be meaningful. Once this returns anything other than
53	/// `InProgress` for some `id` it must return `Unknown` rather than the actual result
54	/// value.
55	fn check_payment(id: Self::Id) -> PaymentStatus;
56	/// Ensure that a call to pay with the given parameters will be successful if done immediately
57	/// after this call. Used in benchmarking code.
58	#[cfg(feature = "runtime-benchmarks")]
59	fn ensure_successful(
60		who: &Self::Beneficiary,
61		asset_kind: Self::AssetKind,
62		amount: Self::Balance,
63	);
64	/// Ensure that a call to `check_payment` with the given parameters will return either `Success`
65	/// or `Failure`.
66	#[cfg(feature = "runtime-benchmarks")]
67	fn ensure_concluded(id: Self::Id);
68}
69
70/// Status for making a payment via the `Pay::pay` trait function.
71#[derive(Encode, Decode, Eq, PartialEq, Clone, TypeInfo, MaxEncodedLen, RuntimeDebug)]
72pub enum PaymentStatus {
73	/// Payment is in progress. Nothing to report yet.
74	InProgress,
75	/// Payment status is unknowable. It may already have reported the result, or if not then
76	/// it will never be reported successful or failed.
77	Unknown,
78	/// Payment happened successfully.
79	Success,
80	/// Payment failed. It may safely be retried.
81	Failure,
82}
83
84/// Simple implementation of `Pay` which makes a payment from a "pot" - i.e. a single account.
85pub struct PayFromAccount<F, A>(core::marker::PhantomData<(F, A)>);
86impl<A, F> Pay for PayFromAccount<F, A>
87where
88	A: TypedGet,
89	F: fungible::Mutate<A::Type>,
90	A::Type: Eq,
91{
92	type Balance = F::Balance;
93	type Beneficiary = A::Type;
94	type AssetKind = ();
95	type Id = ();
96	type Error = DispatchError;
97	fn pay(
98		who: &Self::Beneficiary,
99		_: Self::AssetKind,
100		amount: Self::Balance,
101	) -> Result<Self::Id, Self::Error> {
102		<F as fungible::Mutate<_>>::transfer(&A::get(), who, amount, Expendable)?;
103		Ok(())
104	}
105	fn check_payment(_: ()) -> PaymentStatus {
106		PaymentStatus::Success
107	}
108	#[cfg(feature = "runtime-benchmarks")]
109	fn ensure_successful(_: &Self::Beneficiary, _: Self::AssetKind, amount: Self::Balance) {
110		<F as fungible::Mutate<_>>::mint_into(&A::get(), amount).unwrap();
111	}
112	#[cfg(feature = "runtime-benchmarks")]
113	fn ensure_concluded(_: Self::Id) {}
114}
115
116/// Simple implementation of `Pay` for assets which makes a payment from a "pot" - i.e. a single
117/// account.
118pub struct PayAssetFromAccount<F, A>(core::marker::PhantomData<(F, A)>);
119impl<A, F> frame_support::traits::tokens::Pay for PayAssetFromAccount<F, A>
120where
121	A: TypedGet,
122	F: fungibles::Mutate<A::Type> + fungibles::Create<A::Type>,
123	A::Type: Eq,
124{
125	type Balance = F::Balance;
126	type Beneficiary = A::Type;
127	type AssetKind = F::AssetId;
128	type Id = ();
129	type Error = DispatchError;
130	fn pay(
131		who: &Self::Beneficiary,
132		asset: Self::AssetKind,
133		amount: Self::Balance,
134	) -> Result<Self::Id, Self::Error> {
135		<F as fungibles::Mutate<_>>::transfer(asset, &A::get(), who, amount, Expendable)?;
136		Ok(())
137	}
138	fn check_payment(_: ()) -> PaymentStatus {
139		PaymentStatus::Success
140	}
141	#[cfg(feature = "runtime-benchmarks")]
142	fn ensure_successful(_: &Self::Beneficiary, asset: Self::AssetKind, amount: Self::Balance) {
143		<F as fungibles::Create<_>>::create(asset.clone(), A::get(), true, amount).unwrap();
144		<F as fungibles::Mutate<_>>::mint_into(asset, &A::get(), amount).unwrap();
145	}
146	#[cfg(feature = "runtime-benchmarks")]
147	fn ensure_concluded(_: Self::Id) {}
148}