@@ -7,33 +7,39 @@ use pallet_asset_registry::AssetType;
77use pallet_circuit_breaker:: types:: EgressOperationKind ;
88use pallet_circuit_breaker:: GlobalAssetCategory ;
99use primitives:: Balance ;
10+ use sp_runtime:: helpers_128bit:: multiply_by_rational_with_rounding;
1011use sp_runtime:: traits:: Convert ;
11- use sp_runtime:: DispatchResult ;
12+ use sp_runtime:: { DispatchResult , FixedPointNumber , FixedU128 , Rounding } ;
1213use sp_std:: marker:: PhantomData ;
1314
14- pub struct WithdrawLimitHandler < RC > ( PhantomData < RC > ) ;
15- impl < RC : Get < AssetId > > AssetWithdrawHandler < AccountId , AssetId , Balance > for WithdrawLimitHandler < RC > {
16- type OnWithdraw = OnWithdrawHook < RC > ;
17- type OnDeposit = OnDepositHook < RC > ;
18- type OnTransfer = OnTransferHook < RC > ;
15+ pub struct WithdrawLimitHandler ;
16+ impl AssetWithdrawHandler < AccountId , AssetId , Balance > for WithdrawLimitHandler {
17+ type OnWithdraw = OnWithdrawHook ;
18+ type OnDeposit = OnDepositHook ;
19+ type OnTransfer = OnTransferHook ;
1920}
2021
21- pub struct WithdrawCircuitBreaker < ReferenceCurrencyId > ( PhantomData < ReferenceCurrencyId > ) ;
22- impl < ReferenceCurrencyId : Get < AssetId > > WithdrawCircuitBreaker < ReferenceCurrencyId > {
22+ pub struct WithdrawCircuitBreaker ;
23+ impl WithdrawCircuitBreaker {
2324 fn convert_to_hdx ( asset_id : AssetId , amount : Balance ) -> Result < Balance , DispatchError > {
24- let ref_currency = ReferenceCurrencyId :: get ( ) ;
25+ let ref_currency = NativeAssetId :: get ( ) ;
2526 if asset_id == ref_currency {
2627 return Ok ( amount) ;
2728 }
2829
29- let ( converted, _) = ConvertBalance :: < TenMinutesOraclePrice , XykPaymentAssetSupport , DotAssetId > :: convert ( (
30- asset_id,
31- ref_currency,
32- amount,
33- ) )
34- . ok_or ( pallet_circuit_breaker:: Error :: < Runtime > :: FailedToConvertAsset ) ?;
35-
36- Ok ( converted)
30+ MultiTransactionPayment :: currency_price ( asset_id)
31+ . and_then ( |price| {
32+ multiply_by_rational_with_rounding ( amount, FixedU128 :: DIV , price. into_inner ( ) , Rounding :: Up )
33+ } )
34+ . or_else ( || {
35+ ConvertBalance :: < TenMinutesOraclePrice , XykPaymentAssetSupport , DotAssetId > :: convert ( (
36+ asset_id,
37+ ref_currency,
38+ amount,
39+ ) )
40+ . map ( |( converted, _) | converted)
41+ } )
42+ . ok_or_else ( || pallet_circuit_breaker:: Error :: < Runtime > :: FailedToConvertAsset . into ( ) )
3743 }
3844
3945 pub fn global_asset_category ( asset_id : AssetId ) -> Option < GlobalAssetCategory > {
@@ -97,22 +103,18 @@ impl<ReferenceCurrencyId: Get<AssetId>> WithdrawCircuitBreaker<ReferenceCurrency
97103 }
98104}
99105
100- pub struct OnWithdrawHook < RC > ( PhantomData < RC > ) ;
101- impl < RC : Get < AssetId > > orml_traits:: Handler < ( AssetId , Balance ) > for OnWithdrawHook < RC > {
106+ pub struct OnWithdrawHook ;
107+ impl orml_traits:: Handler < ( AssetId , Balance ) > for OnWithdrawHook {
102108 fn handle ( t : & ( AssetId , Balance ) ) -> DispatchResult {
103109 // `who` is not used: in XCM path all withdrawals go to buffer regardless of origin;
104110 // in non-XCM path Withdraw is always accounted for both Local and External assets regardless of who.
105111 let ( asset_id, amount) = t;
106112
107- if !WithdrawCircuitBreaker :: < RC > :: should_account_withdraw_operation (
108- * asset_id,
109- EgressOperationKind :: Withdraw ,
110- None ,
111- ) {
113+ if !WithdrawCircuitBreaker :: should_account_withdraw_operation ( * asset_id, EgressOperationKind :: Withdraw , None ) {
112114 return Ok ( ( ) ) ;
113115 }
114116
115- let amount_ref_currency = WithdrawCircuitBreaker :: < RC > :: convert_to_hdx ( * asset_id, * amount) ?;
117+ let amount_ref_currency = WithdrawCircuitBreaker :: convert_to_hdx ( * asset_id, * amount) ?;
116118
117119 if let Some ( mut buffer) = pallet_circuit_breaker:: XcmEgressBuffer :: < Runtime > :: get ( ) {
118120 buffer. 0 = buffer. 0 . saturating_add ( amount_ref_currency) ;
@@ -125,8 +127,8 @@ impl<RC: Get<AssetId>> orml_traits::Handler<(AssetId, Balance)> for OnWithdrawHo
125127 }
126128}
127129
128- pub struct OnTransferHook < RC > ( PhantomData < RC > ) ;
129- impl < RC : Get < AssetId > > orml_traits:: currency:: OnTransfer < AccountId , AssetId , Balance > for OnTransferHook < RC > {
130+ pub struct OnTransferHook ;
131+ impl orml_traits:: currency:: OnTransfer < AccountId , AssetId , Balance > for OnTransferHook {
130132 fn on_transfer ( asset_id : AssetId , from : & AccountId , to : & AccountId , amount : Balance ) -> DispatchResult {
131133 let is_from_egress = CircuitBreaker :: is_account_egress ( from) . is_some ( ) ;
132134 let is_to_egress = CircuitBreaker :: is_account_egress ( to) . is_some ( ) ;
@@ -135,13 +137,10 @@ impl<RC: Get<AssetId>> orml_traits::currency::OnTransfer<AccountId, AssetId, Bal
135137 return Ok ( ( ) ) ;
136138 }
137139
138- let try_convert = || WithdrawCircuitBreaker :: < RC > :: convert_to_hdx ( asset_id, amount) ;
140+ let try_convert = || WithdrawCircuitBreaker :: convert_to_hdx ( asset_id, amount) ;
139141
140- if WithdrawCircuitBreaker :: < RC > :: should_account_withdraw_operation (
141- asset_id,
142- EgressOperationKind :: Transfer ,
143- Some ( to) ,
144- ) {
142+ if WithdrawCircuitBreaker :: should_account_withdraw_operation ( asset_id, EgressOperationKind :: Transfer , Some ( to) )
143+ {
145144 let amount_ref_currency = try_convert ( ) ?;
146145 pallet_circuit_breaker:: Pallet :: < Runtime > :: note_egress ( amount_ref_currency) ?;
147146 }
@@ -151,7 +150,7 @@ impl<RC: Get<AssetId>> orml_traits::currency::OnTransfer<AccountId, AssetId, Bal
151150 // accounts are never ingress — no tokens arrived from another chain)
152151 if is_from_egress
153152 && matches ! (
154- WithdrawCircuitBreaker :: < RC > :: global_asset_category( asset_id) ,
153+ WithdrawCircuitBreaker :: global_asset_category( asset_id) ,
155154 Some ( GlobalAssetCategory :: Local )
156155 ) {
157156 if let Ok ( amount_ref_currency) = try_convert ( ) {
@@ -162,8 +161,8 @@ impl<RC: Get<AssetId>> orml_traits::currency::OnTransfer<AccountId, AssetId, Bal
162161 }
163162}
164163
165- pub struct OnDepositHook < RC > ( PhantomData < RC > ) ;
166- impl < RC : Get < AssetId > > orml_traits:: Handler < ( AssetId , Balance , Option < AccountId > ) > for OnDepositHook < RC > {
164+ pub struct OnDepositHook ;
165+ impl orml_traits:: Handler < ( AssetId , Balance , Option < AccountId > ) > for OnDepositHook {
167166 fn handle ( t : & ( AssetId , Balance , Option < AccountId > ) ) -> DispatchResult {
168167 let ( asset_id, amount, maybe_dest) = t;
169168
@@ -176,14 +175,14 @@ impl<RC: Get<AssetId>> orml_traits::Handler<(AssetId, Balance, Option<AccountId>
176175 // Outside XCM, use the stricter should_account_deposit_operation check which,
177176 // for Local assets, requires the source to be an egress account.
178177 if buffer_active {
179- if WithdrawCircuitBreaker :: < RC > :: global_asset_category ( * asset_id) . is_none ( ) {
178+ if WithdrawCircuitBreaker :: global_asset_category ( * asset_id) . is_none ( ) {
180179 return Ok ( ( ) ) ;
181180 }
182- } else if !WithdrawCircuitBreaker :: < RC > :: should_account_deposit_operation ( * asset_id, maybe_dest. clone ( ) ) {
181+ } else if !WithdrawCircuitBreaker :: should_account_deposit_operation ( * asset_id, maybe_dest. clone ( ) ) {
183182 return Ok ( ( ) ) ;
184183 }
185184
186- let Ok ( amount_ref_currency) = WithdrawCircuitBreaker :: < RC > :: convert_to_hdx ( * asset_id, * amount) else {
185+ let Ok ( amount_ref_currency) = WithdrawCircuitBreaker :: convert_to_hdx ( * asset_id, * amount) else {
187186 return Ok ( ( ) ) ;
188187 } ;
189188
0 commit comments