1
// Copyright 2024 Moonbeam foundation
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
//! A minimal runtime including the multi block migrations pallet
18

            
19
use super::*;
20
use crate as pallet_moonbeam_lazy_migrations;
21
use frame_support::traits::AsEnsureOriginWithArg;
22
use frame_support::weights::constants::RocksDbWeight;
23
use frame_support::{construct_runtime, parameter_types, traits::Everything, weights::Weight};
24
use frame_system::{EnsureRoot, EnsureSigned};
25
use pallet_asset_manager::AssetRegistrar;
26
use pallet_evm::{EnsureAddressNever, EnsureAddressRoot, FrameSystemAccountProvider};
27
use precompile_utils::testing::MockAccount;
28
use sp_core::{ConstU32, H160, H256, U256};
29
use sp_runtime::{
30
	traits::{BlakeTwo256, Hash, IdentityLookup},
31
	BuildStorage, Perbill,
32
};
33

            
34
pub type AssetId = u128;
35
pub type Balance = u128;
36
pub type AccountId = MockAccount;
37
type Block = frame_system::mocking::MockBlock<Test>;
38

            
39
// Configure a mock runtime to test the pallet.
40
4148
construct_runtime!(
41
	pub enum Test
42
	{
43
		System: frame_system::{Pallet, Call, Config<T>, Storage, Event<T>},
44
		Balances: pallet_balances::{Pallet, Call, Storage, Config<T>, Event<T>},
45
		Timestamp: pallet_timestamp,
46
		EVM: pallet_evm,
47
		LazyMigrations: pallet_moonbeam_lazy_migrations::{Pallet, Call},
48
		Assets: pallet_assets::{Pallet, Call, Storage, Event<T>},
49
		AssetManager: pallet_asset_manager::{Pallet, Call, Storage, Event<T>},
50
		MoonbeamForeignAssets: pallet_moonbeam_foreign_assets::{Pallet, Call, Storage, Event<T>},
51
	}
52
10067
);
53

            
54
parameter_types! {
55
	pub const BlockHashCount: u32 = 250;
56
	pub const MaximumBlockWeight: Weight = Weight::from_parts(1024, 1);
57
	pub const MaximumBlockLength: u32 = 2 * 1024;
58
	pub const AvailableBlockRatio: Perbill = Perbill::one();
59
	pub const SS58Prefix: u8 = 42;
60
}
61

            
62
impl frame_system::Config for Test {
63
	type BaseCallFilter = Everything;
64
	type DbWeight = RocksDbWeight;
65
	type RuntimeOrigin = RuntimeOrigin;
66
	type RuntimeTask = RuntimeTask;
67
	type Nonce = u64;
68
	type Block = Block;
69
	type RuntimeCall = RuntimeCall;
70
	type Hash = H256;
71
	type Hashing = BlakeTwo256;
72
	type AccountId = AccountId;
73
	type Lookup = IdentityLookup<Self::AccountId>;
74
	type RuntimeEvent = RuntimeEvent;
75
	type BlockHashCount = BlockHashCount;
76
	type Version = ();
77
	type PalletInfo = PalletInfo;
78
	type AccountData = pallet_balances::AccountData<Balance>;
79
	type OnNewAccount = ();
80
	type OnKilledAccount = ();
81
	type SystemWeightInfo = ();
82
	type BlockWeights = ();
83
	type BlockLength = ();
84
	type SS58Prefix = SS58Prefix;
85
	type OnSetCode = ();
86
	type MaxConsumers = frame_support::traits::ConstU32<16>;
87
	type SingleBlockMigrations = ();
88
	type MultiBlockMigrator = ();
89
	type PreInherents = ();
90
	type PostInherents = ();
91
	type PostTransactions = ();
92
}
93

            
94
parameter_types! {
95
	pub const ExistentialDeposit: u128 = 0;
96
}
97
impl pallet_balances::Config for Test {
98
	type MaxReserves = ();
99
	type ReserveIdentifier = ();
100
	type MaxLocks = ();
101
	type Balance = Balance;
102
	type RuntimeEvent = RuntimeEvent;
103
	type DustRemoval = ();
104
	type ExistentialDeposit = ExistentialDeposit;
105
	type AccountStore = System;
106
	type WeightInfo = ();
107
	type RuntimeHoldReason = ();
108
	type FreezeIdentifier = ();
109
	type MaxFreezes = ();
110
	type RuntimeFreezeReason = ();
111
}
112

            
113
parameter_types! {
114
	pub const MinimumPeriod: u64 = 6000 / 2;
115
}
116

            
117
impl pallet_timestamp::Config for Test {
118
	type Moment = u64;
119
	type OnTimestampSet = ();
120
	type MinimumPeriod = MinimumPeriod;
121
	type WeightInfo = ();
122
}
123

            
124
parameter_types! {
125
	pub BlockGasLimit: U256 = U256::from(u64::MAX);
126
	pub const WeightPerGas: Weight = Weight::from_parts(1, 0);
127
	pub GasLimitPovSizeRatio: u64 = 16;
128
	pub GasLimitStorageGrowthRatio: u64 = 366;
129
	pub SuicideQuickClearLimit: u32 = 0;
130
}
131

            
132
impl pallet_evm::Config for Test {
133
	type FeeCalculator = ();
134
	type GasWeightMapping = pallet_evm::FixedGasWeightMapping<Self>;
135
	type WeightPerGas = WeightPerGas;
136
	type CallOrigin = EnsureAddressRoot<AccountId>;
137
	type WithdrawOrigin = EnsureAddressNever<AccountId>;
138
	type AddressMapping = AccountId;
139
	type Currency = Balances;
140
	type RuntimeEvent = RuntimeEvent;
141
	type Runner = pallet_evm::runner::stack::Runner<Self>;
142
	type PrecompilesType = ();
143
	type PrecompilesValue = ();
144
	type ChainId = ();
145
	type OnChargeTransaction = ();
146
	type BlockGasLimit = BlockGasLimit;
147
	type BlockHashMapping = pallet_evm::SubstrateBlockHashMapping<Self>;
148
	type FindAuthor = ();
149
	type OnCreate = ();
150
	type GasLimitPovSizeRatio = GasLimitPovSizeRatio;
151
	type GasLimitStorageGrowthRatio = GasLimitStorageGrowthRatio;
152
	type Timestamp = Timestamp;
153
	type WeightInfo = ();
154
	type SuicideQuickClearLimit = SuicideQuickClearLimit;
155
	type AccountProvider = FrameSystemAccountProvider<Test>;
156
}
157

            
158
parameter_types! {
159
	pub const AssetDeposit: u128 = 1;
160
	pub const MetadataDepositBase: u128 = 1;
161
	pub const MetadataDepositPerByte: u128 = 1;
162
	pub const ApprovalDeposit: u128 = 1;
163
	pub const AssetsStringLimit: u32 = 50;
164
	pub const AssetAccountDeposit: u128 = 1;
165
}
166

            
167
// Required for runtime benchmarks
168
pallet_assets::runtime_benchmarks_enabled! {
169
	pub struct BenchmarkHelper;
170
	impl<AssetIdParameter> pallet_assets::BenchmarkHelper<AssetIdParameter> for BenchmarkHelper
171
	where
172
		AssetIdParameter: From<u128>,
173
	{
174
		fn create_asset_id_parameter(id: u32) -> AssetIdParameter {
175
			(id as u128).into()
176
		}
177
	}
178
}
179

            
180
impl pallet_assets::Config<()> for Test {
181
	type RuntimeEvent = RuntimeEvent;
182
	type Balance = Balance;
183
	type AssetId = AssetId;
184
	type Currency = Balances;
185
	type ForceOrigin = EnsureRoot<AccountId>;
186
	type AssetDeposit = AssetDeposit;
187
	type MetadataDepositBase = MetadataDepositBase;
188
	type MetadataDepositPerByte = MetadataDepositPerByte;
189
	type ApprovalDeposit = ApprovalDeposit;
190
	type StringLimit = AssetsStringLimit;
191
	type Freezer = ();
192
	type Extra = ();
193
	type AssetAccountDeposit = AssetAccountDeposit;
194
	type WeightInfo = ();
195
	type RemoveItemsLimit = ConstU32<656>;
196
	type AssetIdParameter = AssetId;
197
	type CreateOrigin = AsEnsureOriginWithArg<EnsureSigned<AccountId>>;
198
	type CallbackHandle = ();
199
	pallet_assets::runtime_benchmarks_enabled! {
200
		type BenchmarkHelper = BenchmarkHelper;
201
	}
202
}
203

            
204
#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Encode, Decode, RuntimeDebug, TypeInfo)]
205
pub enum MockAssetType {
206
15
	Xcm(Location),
207
	MockAsset(AssetId),
208
}
209

            
210
impl Default for MockAssetType {
211
	fn default() -> Self {
212
		Self::MockAsset(0)
213
	}
214
}
215

            
216
impl From<MockAssetType> for AssetId {
217
34
	fn from(asset: MockAssetType) -> AssetId {
218
34
		match asset {
219
			MockAssetType::MockAsset(id) => id,
220
34
			MockAssetType::Xcm(id) => {
221
34
				let mut result: [u8; 16] = [0u8; 16];
222
34
				let hash: H256 = id.using_encoded(<Test as frame_system::Config>::Hashing::hash);
223
34
				result.copy_from_slice(&hash.as_fixed_bytes()[0..16]);
224
34
				u128::from_le_bytes(result)
225
			}
226
		}
227
34
	}
228
}
229

            
230
impl From<Location> for MockAssetType {
231
	fn from(location: Location) -> Self {
232
		Self::Xcm(location)
233
	}
234
}
235

            
236
impl Into<Option<Location>> for MockAssetType {
237
15
	fn into(self) -> Option<Location> {
238
15
		match self {
239
15
			Self::Xcm(location) => Some(location),
240
			_ => None,
241
		}
242
15
	}
243
}
244

            
245
pub struct MockAssetPalletRegistrar;
246

            
247
impl AssetRegistrar<Test> for MockAssetPalletRegistrar {
248
17
	fn create_foreign_asset(
249
17
		asset: u128,
250
17
		min_balance: u128,
251
17
		_metadata: u32,
252
17
		is_sufficient: bool,
253
17
	) -> Result<(), DispatchError> {
254
17
		Assets::force_create(
255
17
			RuntimeOrigin::root(),
256
17
			asset.into(),
257
17
			AssetManager::account_id(),
258
17
			is_sufficient,
259
17
			min_balance,
260
17
		)?;
261
17
		Ok(())
262
17
	}
263

            
264
	fn destroy_foreign_asset(_asset: u128) -> Result<(), DispatchError> {
265
		Ok(())
266
	}
267

            
268
	fn destroy_asset_dispatch_info_weight(_asset: u128) -> Weight {
269
		Weight::from_parts(0, 0)
270
	}
271
}
272

            
273
impl pallet_asset_manager::Config for Test {
274
	type RuntimeEvent = RuntimeEvent;
275
	type Balance = Balance;
276
	type AssetId = AssetId;
277
	type AssetRegistrarMetadata = u32;
278
	type ForeignAssetType = MockAssetType;
279
	type AssetRegistrar = MockAssetPalletRegistrar;
280
	type ForeignAssetModifierOrigin = EnsureRoot<AccountId>;
281
	type WeightInfo = ();
282
}
283

            
284
pub struct AccountIdToH160;
285
impl sp_runtime::traits::Convert<AccountId, H160> for AccountIdToH160 {
286
74
	fn convert(account_id: AccountId) -> H160 {
287
74
		account_id.into()
288
74
	}
289
}
290

            
291
impl pallet_moonbeam_foreign_assets::Config for Test {
292
	type AccountIdToH160 = AccountIdToH160;
293
	type AssetIdFilter = Everything;
294
	type EvmRunner = pallet_evm::runner::stack::Runner<Self>;
295
	type ForeignAssetCreatorOrigin = EnsureRoot<AccountId>;
296
	type ForeignAssetFreezerOrigin = EnsureRoot<AccountId>;
297
	type ForeignAssetModifierOrigin = EnsureRoot<AccountId>;
298
	type ForeignAssetUnfreezerOrigin = EnsureRoot<AccountId>;
299
	type OnForeignAssetCreated = ();
300
	type MaxForeignAssets = ConstU32<3>;
301
	type RuntimeEvent = RuntimeEvent;
302
	type WeightInfo = ();
303
	type XcmLocationToH160 = ();
304
}
305

            
306
impl Config for Test {
307
	type WeightInfo = ();
308
	type ForeignAssetMigratorOrigin = EnsureRoot<AccountId>;
309
}
310

            
311
// Constants for test accounts
312
pub const ALITH: AccountId = MockAccount(H160([1; 20]));
313
pub const BOB: AccountId = MockAccount(H160([2; 20]));
314

            
315
/// Externality builder for pallet migration's mock runtime
316
pub(crate) struct ExtBuilder {
317
	// endowed accounts with balances
318
	balances: Vec<(AccountId, Balance)>,
319
}
320

            
321
impl Default for ExtBuilder {
322
24
	fn default() -> ExtBuilder {
323
24
		ExtBuilder {
324
24
			balances: vec![
325
24
				(ALITH, 1000),
326
24
				(BOB, 1000),
327
24
				(AssetManager::account_id(), 1000),
328
24
			],
329
24
		}
330
24
	}
331
}
332

            
333
impl ExtBuilder {
334
24
	pub(crate) fn build(self) -> sp_io::TestExternalities {
335
24
		let mut storage = frame_system::GenesisConfig::<Test>::default()
336
24
			.build_storage()
337
24
			.expect("Frame system builds valid default genesis config");
338
24

            
339
24
		pallet_balances::GenesisConfig::<Test> {
340
24
			balances: self.balances,
341
24
		}
342
24
		.assimilate_storage(&mut storage)
343
24
		.expect("Pallet balances storage can be assimilated");
344
24

            
345
24
		let mut ext = sp_io::TestExternalities::new(storage);
346
24
		ext.execute_with(|| System::set_block_number(1));
347
24
		ext
348
24
	}
349
}