1
// Copyright 2019-2025 PureStake Inc.
2
// This file is part of Moonbeam.
3

            
4
// Moonbeam is free software: you can redistribute it and/or modify
5
// it under the terms of the GNU General Public License as published by
6
// the Free Software Foundation, either version 3 of the License, or
7
// (at your option) any later version.
8

            
9
// Moonbeam is distributed in the hope that it will be useful,
10
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
// GNU General Public License for more details.
13

            
14
// You should have received a copy of the GNU General Public License
15
// along with Moonbeam.  If not, see <http://www.gnu.org/licenses/>.
16

            
17
pub mod fungible;
18
pub mod generic;
19

            
20
pub use crate::weights::generic::WeightInfo;
21
use core::cmp::min;
22
use frame_support::{weights::Weight, BoundedVec};
23
use fungible::WeightInfo as XcmFungibleWeight;
24
use generic::SubstrateWeight as XcmGeneric;
25
use sp_std::prelude::*;
26
use xcm::{
27
	latest::{prelude::*, Weight as XCMWeight},
28
	opaque::latest::AssetTransferFilter,
29
	v5, DoubleEncoded,
30
};
31
use xcm_primitives::MAX_ASSETS;
32

            
33
trait WeighMultiAssets {
34
	fn weigh_multi_assets(&self, weight: Weight) -> XCMWeight;
35
}
36

            
37
trait WeighMultiAssetsFilter {
38
	fn weigh_multi_assets_filter(&self, weight: Weight) -> XCMWeight;
39
}
40

            
41
impl WeighMultiAssetsFilter for AssetFilter {
42
	fn weigh_multi_assets_filter(&self, weight: Weight) -> XCMWeight {
43
		match self {
44
			Self::Definite(assets) => {
45
				weight.saturating_mul(assets.inner().into_iter().count() as u64)
46
			}
47
			Self::Wild(AllCounted(count) | AllOfCounted { count, .. }) => {
48
				weight.saturating_mul(min(MAX_ASSETS, *count) as u64)
49
			}
50
			Self::Wild(All | AllOf { .. }) => weight.saturating_mul(MAX_ASSETS as u64),
51
		}
52
	}
53
}
54

            
55
impl WeighMultiAssets for Assets {
56
512
	fn weigh_multi_assets(&self, weight: Weight) -> XCMWeight {
57
512
		weight.saturating_mul(self.inner().into_iter().count() as u64)
58
512
	}
59
}
60

            
61
pub struct XcmWeight<Runtime, Call>(core::marker::PhantomData<(Runtime, Call)>);
62
impl<Runtime, Call> XcmWeightInfo<Call> for XcmWeight<Runtime, Call>
63
where
64
	Runtime: frame_system::Config
65
		+ pallet_erc20_xcm_bridge::Config
66
		+ pallet_moonbeam_foreign_assets::Config,
67
{
68
122
	fn withdraw_asset(assets: &Assets) -> XCMWeight {
69
122
		assets.inner().iter().fold(Weight::zero(), |acc, asset| {
70
122
			acc.saturating_add(XcmFungibleWeight::<Runtime>::withdraw_asset(&asset))
71
122
		})
72
122
	}
73
	// Currently there is no trusted reserve
74
	fn reserve_asset_deposited(_assets: &Assets) -> XCMWeight {
75
		XcmFungibleWeight::<Runtime>::reserve_asset_deposited()
76
	}
77
	fn receive_teleported_asset(assets: &Assets) -> XCMWeight {
78
		assets.weigh_multi_assets(XcmFungibleWeight::<Runtime>::receive_teleported_asset())
79
	}
80
	fn query_response(
81
		_query_id: &u64,
82
		_response: &Response,
83
		_max_weight: &Weight,
84
		_querier: &Option<Location>,
85
	) -> XCMWeight {
86
		XcmGeneric::<Runtime>::query_response()
87
	}
88
18
	fn transfer_asset(assets: &Assets, _dest: &Location) -> XCMWeight {
89
18
		assets.inner().iter().fold(Weight::zero(), |acc, asset| {
90
18
			acc.saturating_add(XcmFungibleWeight::<Runtime>::transfer_asset(&asset))
91
18
		})
92
18
	}
93
	fn transfer_reserve_asset(assets: &Assets, _dest: &Location, _xcm: &Xcm<()>) -> XCMWeight {
94
		assets.inner().iter().fold(Weight::zero(), |acc, asset| {
95
			acc.saturating_add(XcmFungibleWeight::<Runtime>::transfer_reserve_asset(&asset))
96
		})
97
	}
98
	fn transact(
99
		_origin_type: &OriginKind,
100
		_require_weight_at_most: &Option<Weight>,
101
		_call: &DoubleEncoded<Call>,
102
	) -> XCMWeight {
103
		XcmGeneric::<Runtime>::transact()
104
	}
105
	fn hrmp_new_channel_open_request(
106
		_sender: &u32,
107
		_max_message_size: &u32,
108
		_max_capacity: &u32,
109
	) -> XCMWeight {
110
		// XCM Executor does not currently support HRMP channel operations
111
		Weight::MAX
112
	}
113
	fn hrmp_channel_accepted(_recipient: &u32) -> XCMWeight {
114
		// XCM Executor does not currently support HRMP channel operations
115
		Weight::MAX
116
	}
117
	fn hrmp_channel_closing(_initiator: &u32, _sender: &u32, _recipient: &u32) -> XCMWeight {
118
		// XCM Executor does not currently support HRMP channel operations
119
		Weight::MAX
120
	}
121
6
	fn clear_origin() -> XCMWeight {
122
6
		XcmGeneric::<Runtime>::clear_origin()
123
6
	}
124
	fn descend_origin(_who: &InteriorLocation) -> XCMWeight {
125
		XcmGeneric::<Runtime>::descend_origin()
126
	}
127
	fn report_error(_query_response_info: &QueryResponseInfo) -> XCMWeight {
128
		XcmGeneric::<Runtime>::report_error()
129
	}
130
	fn deposit_asset(assets: &AssetFilter, _dest: &Location) -> XCMWeight {
131
		assets.weigh_multi_assets_filter(XcmFungibleWeight::<Runtime>::deposit_asset())
132
	}
133
	fn deposit_reserve_asset(assets: &AssetFilter, _dest: &Location, _xcm: &Xcm<()>) -> XCMWeight {
134
		assets.weigh_multi_assets_filter(XcmFungibleWeight::<Runtime>::deposit_reserve_asset())
135
	}
136
	fn exchange_asset(_give: &AssetFilter, _receive: &Assets, _maximal: &bool) -> XCMWeight {
137
		Weight::MAX
138
	}
139
	fn initiate_reserve_withdraw(
140
		_assets: &AssetFilter,
141
		_reserve: &Location,
142
		_xcm: &Xcm<()>,
143
	) -> XCMWeight {
144
		// This is not correct. initiate reserve withdraw does not to that many db reads
145
		// the only thing it does based on number of assets is a take from a local variable
146
		//assets.weigh_multi_assets(XcmGeneric::<Runtime>::initiate_reserve_withdraw())
147
		XcmGeneric::<Runtime>::initiate_reserve_withdraw()
148
	}
149
	fn initiate_teleport(_assets: &AssetFilter, _dest: &Location, _xcm: &Xcm<()>) -> XCMWeight {
150
		XcmFungibleWeight::<Runtime>::initiate_teleport()
151
	}
152
	fn report_holding(_response_info: &QueryResponseInfo, _assets: &AssetFilter) -> Weight {
153
		XcmGeneric::<Runtime>::report_holding()
154
	}
155
	fn buy_execution(_fees: &Asset, _weight_limit: &WeightLimit) -> XCMWeight {
156
		XcmGeneric::<Runtime>::buy_execution()
157
	}
158
	fn refund_surplus() -> XCMWeight {
159
		XcmGeneric::<Runtime>::refund_surplus()
160
	}
161
	fn set_error_handler(_xcm: &Xcm<Call>) -> XCMWeight {
162
		XcmGeneric::<Runtime>::set_error_handler()
163
	}
164
	fn set_appendix(_xcm: &Xcm<Call>) -> XCMWeight {
165
		XcmGeneric::<Runtime>::set_appendix()
166
	}
167
	fn clear_error() -> XCMWeight {
168
		XcmGeneric::<Runtime>::clear_error()
169
	}
170
	fn claim_asset(_assets: &Assets, _ticket: &Location) -> XCMWeight {
171
		XcmGeneric::<Runtime>::claim_asset()
172
	}
173
	fn trap(_code: &u64) -> XCMWeight {
174
		XcmGeneric::<Runtime>::trap()
175
	}
176
	fn subscribe_version(_query_id: &QueryId, _max_response_weight: &Weight) -> XCMWeight {
177
		XcmGeneric::<Runtime>::subscribe_version()
178
	}
179
	fn unsubscribe_version() -> XCMWeight {
180
		XcmGeneric::<Runtime>::unsubscribe_version()
181
	}
182
122
	fn burn_asset(assets: &Assets) -> Weight {
183
122
		assets.weigh_multi_assets(XcmGeneric::<Runtime>::burn_asset())
184
122
	}
185
	fn expect_asset(assets: &Assets) -> Weight {
186
		assets.weigh_multi_assets(XcmGeneric::<Runtime>::expect_asset())
187
	}
188
	fn expect_origin(_origin: &Option<Location>) -> Weight {
189
		XcmGeneric::<Runtime>::expect_origin()
190
	}
191
	fn expect_error(_error: &Option<(u32, XcmError)>) -> Weight {
192
		XcmGeneric::<Runtime>::expect_error()
193
	}
194
	fn expect_transact_status(_transact_status: &MaybeErrorCode) -> Weight {
195
		XcmGeneric::<Runtime>::expect_transact_status()
196
	}
197
	fn query_pallet(_module_name: &Vec<u8>, _response_info: &QueryResponseInfo) -> Weight {
198
		XcmGeneric::<Runtime>::query_pallet()
199
	}
200
	fn expect_pallet(
201
		_index: &u32,
202
		_name: &Vec<u8>,
203
		_module_name: &Vec<u8>,
204
		_crate_major: &u32,
205
		_min_crate_minor: &u32,
206
	) -> Weight {
207
		XcmGeneric::<Runtime>::expect_pallet()
208
	}
209
	fn report_transact_status(_response_info: &QueryResponseInfo) -> Weight {
210
		XcmGeneric::<Runtime>::report_transact_status()
211
	}
212
	fn clear_transact_status() -> Weight {
213
		XcmGeneric::<Runtime>::clear_transact_status()
214
	}
215
	fn universal_origin(_: &Junction) -> Weight {
216
		Weight::MAX
217
	}
218
	fn export_message(_: &NetworkId, _: &Junctions, _: &Xcm<()>) -> Weight {
219
		Weight::MAX
220
	}
221
	fn lock_asset(_: &Asset, _: &Location) -> Weight {
222
		Weight::MAX
223
	}
224
	fn unlock_asset(_: &Asset, _: &Location) -> Weight {
225
		Weight::MAX
226
	}
227
	fn note_unlockable(_: &Asset, _: &Location) -> Weight {
228
		Weight::MAX
229
	}
230
	fn request_unlock(_: &Asset, _: &Location) -> Weight {
231
		Weight::MAX
232
	}
233
	fn set_fees_mode(_: &bool) -> Weight {
234
		XcmGeneric::<Runtime>::set_fees_mode()
235
	}
236
	fn set_topic(_topic: &[u8; 32]) -> Weight {
237
		XcmGeneric::<Runtime>::set_topic()
238
	}
239
	fn clear_topic() -> Weight {
240
		XcmGeneric::<Runtime>::clear_topic()
241
	}
242
	fn alias_origin(_: &Location) -> Weight {
243
		// XCM Executor does not currently support alias origin operations
244
		Weight::MAX
245
	}
246
	fn unpaid_execution(_: &WeightLimit, _: &Option<Location>) -> Weight {
247
		XcmGeneric::<Runtime>::unpaid_execution()
248
	}
249
	fn pay_fees(_: &v5::Asset) -> Weight {
250
		XcmGeneric::<Runtime>::pay_fees()
251
	}
252
	fn initiate_transfer(
253
		_: &v5::Location,
254
		_: &Option<AssetTransferFilter>,
255
		_: &bool,
256
		_: &BoundedVec<AssetTransferFilter, MaxAssetTransferFilters>,
257
		_: &v5::Xcm<()>,
258
	) -> Weight {
259
		XcmGeneric::<Runtime>::initiate_transfer()
260
	}
261
	fn execute_with_origin(_: &Option<v5::Junctions>, _: &v5::Xcm<Call>) -> Weight {
262
		XcmGeneric::<Runtime>::execute_with_origin()
263
	}
264
	fn set_hints(_: &BoundedVec<Hint, HintNumVariants>) -> Weight {
265
		XcmGeneric::<Runtime>::set_hints()
266
	}
267
}