1
1
use codec:: FullCodec ;
2
- use sp_runtime:: traits:: { Convert , MaybeSerializeDeserialize , SaturatedConversion } ;
2
+ use frame_support:: traits:: Get ;
3
+ use sp_runtime:: {
4
+ traits:: { Convert , MaybeSerializeDeserialize , SaturatedConversion } ,
5
+ DispatchError ,
6
+ } ;
3
7
use sp_std:: {
4
8
cmp:: { Eq , PartialEq } ,
5
9
fmt:: Debug ,
@@ -36,11 +40,68 @@ impl From<Error> for XcmError {
36
40
}
37
41
}
38
42
43
+ /// Deposit errors handler for `TransactAsset` implementations. Default impl for
44
+ /// `()` returns an `XcmError::FailedToTransactAsset` error.
45
+ pub trait OnDepositFail < CurrencyId , AccountId , Balance > {
46
+ /// Called on deposit errors with a specific `currency_id`.
47
+ fn on_deposit_currency_fail (
48
+ err : DispatchError ,
49
+ currency_id : CurrencyId ,
50
+ who : & AccountId ,
51
+ amount : Balance ,
52
+ ) -> Result ;
53
+
54
+ /// Called on unknown asset deposit errors.
55
+ fn on_deposit_unknown_asset_fail ( err : DispatchError , _asset : & MultiAsset , _location : & MultiLocation ) -> Result {
56
+ Err ( XcmError :: FailedToTransactAsset ( err. into ( ) ) )
57
+ }
58
+ }
59
+
60
+ impl < CurrencyId , AccountId , Balance > OnDepositFail < CurrencyId , AccountId , Balance > for ( ) {
61
+ fn on_deposit_currency_fail (
62
+ err : DispatchError ,
63
+ _currency_id : CurrencyId ,
64
+ _who : & AccountId ,
65
+ _amount : Balance ,
66
+ ) -> Result {
67
+ Err ( XcmError :: FailedToTransactAsset ( err. into ( ) ) )
68
+ }
69
+ }
70
+
71
+ /// `OnDepositFail` impl, will deposit known currencies to an alternative
72
+ /// account.
73
+ pub struct DepositToAlternative < Alternative , MultiCurrency , CurrencyId , AccountId , Balance > (
74
+ PhantomData < ( Alternative , MultiCurrency , CurrencyId , AccountId , Balance ) > ,
75
+ ) ;
76
+ impl <
77
+ Alternative : Get < AccountId > ,
78
+ MultiCurrency : orml_traits:: MultiCurrency < AccountId , CurrencyId = CurrencyId , Balance = Balance > ,
79
+ AccountId : sp_std:: fmt:: Debug + Clone ,
80
+ CurrencyId : FullCodec + Eq + PartialEq + Copy + MaybeSerializeDeserialize + Debug ,
81
+ Balance ,
82
+ > OnDepositFail < CurrencyId , AccountId , Balance >
83
+ for DepositToAlternative < Alternative , MultiCurrency , CurrencyId , AccountId , Balance >
84
+ {
85
+ fn on_deposit_currency_fail (
86
+ _err : DispatchError ,
87
+ currency_id : CurrencyId ,
88
+ _who : & AccountId ,
89
+ amount : Balance ,
90
+ ) -> Result {
91
+ MultiCurrency :: deposit ( currency_id, & Alternative :: get ( ) , amount)
92
+ . map_err ( |e| XcmError :: FailedToTransactAsset ( e. into ( ) ) )
93
+ }
94
+ }
95
+
39
96
/// The `TransactAsset` implementation, to handle `MultiAsset` deposit/withdraw.
40
97
/// Note that teleport related functions are unimplemented.
41
98
///
99
+ /// Methods of `DepositFailureHandler` would be called on multi-currency deposit
100
+ /// errors.
101
+ ///
42
102
/// If the asset is known, deposit/withdraw will be handled by `MultiCurrency`,
43
103
/// else by `UnknownAsset` if unknown.
104
+ #[ allow( clippy:: type_complexity) ]
44
105
pub struct MultiCurrencyAdapter <
45
106
MultiCurrency ,
46
107
UnknownAsset ,
@@ -49,6 +110,7 @@ pub struct MultiCurrencyAdapter<
49
110
AccountIdConvert ,
50
111
CurrencyId ,
51
112
CurrencyIdConvert ,
113
+ DepositFailureHandler ,
52
114
> (
53
115
PhantomData < (
54
116
MultiCurrency ,
@@ -58,6 +120,7 @@ pub struct MultiCurrencyAdapter<
58
120
AccountIdConvert ,
59
121
CurrencyId ,
60
122
CurrencyIdConvert ,
123
+ DepositFailureHandler ,
61
124
) > ,
62
125
) ;
63
126
@@ -69,8 +132,18 @@ impl<
69
132
AccountIdConvert : MoreConvert < MultiLocation , AccountId > ,
70
133
CurrencyId : FullCodec + Eq + PartialEq + Copy + MaybeSerializeDeserialize + Debug ,
71
134
CurrencyIdConvert : Convert < MultiAsset , Option < CurrencyId > > ,
135
+ DepositFailureHandler : OnDepositFail < CurrencyId , AccountId , MultiCurrency :: Balance > ,
72
136
> TransactAsset
73
- for MultiCurrencyAdapter < MultiCurrency , UnknownAsset , Match , AccountId , AccountIdConvert , CurrencyId , CurrencyIdConvert >
137
+ for MultiCurrencyAdapter <
138
+ MultiCurrency ,
139
+ UnknownAsset ,
140
+ Match ,
141
+ AccountId ,
142
+ AccountIdConvert ,
143
+ CurrencyId ,
144
+ CurrencyIdConvert ,
145
+ DepositFailureHandler ,
146
+ >
74
147
{
75
148
fn deposit_asset ( asset : & MultiAsset , location : & MultiLocation ) -> Result {
76
149
match (
@@ -79,11 +152,11 @@ impl<
79
152
Match :: matches_fungible ( asset) ,
80
153
) {
81
154
// known asset
82
- ( Ok ( who) , Some ( currency_id) , Some ( amount) ) => {
83
- MultiCurrency :: deposit ( currency_id, & who, amount) . map_err ( |e| XcmError :: FailedToTransactAsset ( e. into ( ) ) )
84
- }
155
+ ( Ok ( who) , Some ( currency_id) , Some ( amount) ) => MultiCurrency :: deposit ( currency_id, & who, amount)
156
+ . or_else ( |err| DepositFailureHandler :: on_deposit_currency_fail ( err, currency_id, & who, amount) ) ,
85
157
// unknown asset
86
- _ => UnknownAsset :: deposit ( asset, location) . map_err ( |e| XcmError :: FailedToTransactAsset ( e. into ( ) ) ) ,
158
+ _ => UnknownAsset :: deposit ( asset, location)
159
+ . or_else ( |err| DepositFailureHandler :: on_deposit_unknown_asset_fail ( err, asset, location) ) ,
87
160
}
88
161
}
89
162
0 commit comments