1
// Copyright 2019-2022 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
//! Test utilities
18
use super::*;
19
use cumulus_primitives_core::{
20
	relay_chain::BlockNumber as RelayChainBlockNumber, AggregateMessageOrigin,
21
	PersistedValidationData,
22
};
23
use cumulus_primitives_parachain_inherent::ParachainInherentData;
24
use cumulus_test_relay_sproof_builder::RelayStateSproofBuilder;
25
use frame_support::{
26
	construct_runtime,
27
	inherent::{InherentData, ProvideInherent},
28
	parameter_types,
29
	traits::{Everything, OnFinalize, OnInitialize, UnfilteredDispatchable},
30
	weights::Weight,
31
};
32
use frame_system::{pallet_prelude::BlockNumberFor, EnsureSigned, RawOrigin};
33
use pallet_evm::{EnsureAddressNever, EnsureAddressRoot};
34
use precompile_utils::{precompile_set::*, testing::MockAccount};
35
use sp_core::{H256, U256};
36
use sp_io;
37
use sp_runtime::{
38
	traits::{BlakeTwo256, IdentityLookup},
39
	BuildStorage, Perbill,
40
};
41

            
42
pub type AccountId = MockAccount;
43
pub type Balance = u128;
44

            
45
type Block = frame_system::mocking::MockBlockU32<Runtime>;
46
pub type BlockNumber = BlockNumberFor<Runtime>;
47

            
48
// Configure a mock runtime to test the pallet.
49
1610
construct_runtime!(
50
	pub enum Runtime	{
51
		System: frame_system,
52
		Balances: pallet_balances,
53
		Evm: pallet_evm,
54
		Timestamp: pallet_timestamp,
55
		ParachainSystem: cumulus_pallet_parachain_system,
56
		Crowdloan: pallet_crowdloan_rewards,
57
		MessageQueue: pallet_message_queue,
58
	}
59
5079
);
60

            
61
parameter_types! {
62
	pub ParachainId: cumulus_primitives_core::ParaId = 100.into();
63
	pub const RelayOrigin: AggregateMessageOrigin = AggregateMessageOrigin::Parent;
64
}
65

            
66
impl cumulus_pallet_parachain_system::Config for Runtime {
67
	type SelfParaId = ParachainId;
68
	type RuntimeEvent = RuntimeEvent;
69
	type OnSystemEvent = ();
70
	type OutboundXcmpMessageSource = ();
71
	type XcmpMessageHandler = ();
72
	type ReservedXcmpWeight = ();
73
	type DmpQueue = frame_support::traits::EnqueueWithOrigin<MessageQueue, RelayOrigin>;
74
	type ReservedDmpWeight = ();
75
	type CheckAssociatedRelayNumber = cumulus_pallet_parachain_system::RelayNumberStrictlyIncreases;
76
	type ConsensusHook = cumulus_pallet_parachain_system::ExpectParentIncluded;
77
	type WeightInfo = cumulus_pallet_parachain_system::weights::SubstrateWeight<Runtime>;
78
}
79

            
80
parameter_types! {
81
	pub MessageQueueServiceWeight: Weight = Weight::from_parts(1_000_000_000, 1_000_000);
82
	pub const MessageQueueHeapSize: u32 = 65_536;
83
	pub const MessageQueueMaxStale: u32 = 16;
84
}
85

            
86
impl pallet_message_queue::Config for Runtime {
87
	type RuntimeEvent = RuntimeEvent;
88
	type Size = u32;
89
	type HeapSize = MessageQueueHeapSize;
90
	type MaxStale = MessageQueueMaxStale;
91
	type ServiceWeight = MessageQueueServiceWeight;
92
	type MessageProcessor =
93
		pallet_message_queue::mock_helpers::NoopMessageProcessor<AggregateMessageOrigin>;
94
	type QueueChangeHandler = ();
95
	type WeightInfo = ();
96
	type QueuePausedQuery = ();
97
	type IdleMaxServiceWeight = MessageQueueServiceWeight;
98
}
99

            
100
parameter_types! {
101
	pub const BlockHashCount: u32 = 250;
102
	pub const SS58Prefix: u8 = 42;
103
}
104
impl frame_system::Config for Runtime {
105
	type BaseCallFilter = Everything;
106
	type DbWeight = ();
107
	type RuntimeOrigin = RuntimeOrigin;
108
	type RuntimeTask = RuntimeTask;
109
	type Nonce = u64;
110
	type Block = Block;
111
	type RuntimeCall = RuntimeCall;
112
	type Hash = H256;
113
	type Hashing = BlakeTwo256;
114
	type AccountId = AccountId;
115
	type Lookup = IdentityLookup<Self::AccountId>;
116
	type RuntimeEvent = RuntimeEvent;
117
	type BlockHashCount = BlockHashCount;
118
	type Version = ();
119
	type PalletInfo = PalletInfo;
120
	type AccountData = pallet_balances::AccountData<Balance>;
121
	type OnNewAccount = ();
122
	type OnKilledAccount = ();
123
	type SystemWeightInfo = ();
124
	type BlockWeights = ();
125
	type BlockLength = ();
126
	type SS58Prefix = SS58Prefix;
127
	type OnSetCode = cumulus_pallet_parachain_system::ParachainSetCode<Self>;
128
	type MaxConsumers = frame_support::traits::ConstU32<16>;
129
	type SingleBlockMigrations = ();
130
	type MultiBlockMigrator = ();
131
	type PreInherents = ();
132
	type PostInherents = ();
133
	type PostTransactions = ();
134
}
135
parameter_types! {
136
	pub const ExistentialDeposit: u128 = 0;
137
}
138
impl pallet_balances::Config for Runtime {
139
	type MaxReserves = ();
140
	type ReserveIdentifier = ();
141
	type MaxLocks = ();
142
	type Balance = Balance;
143
	type RuntimeEvent = RuntimeEvent;
144
	type DustRemoval = ();
145
	type ExistentialDeposit = ExistentialDeposit;
146
	type AccountStore = System;
147
	type WeightInfo = ();
148
	type RuntimeHoldReason = ();
149
	type FreezeIdentifier = ();
150
	type MaxFreezes = ();
151
	type RuntimeFreezeReason = ();
152
}
153

            
154
pub type Precompiles<R> =
155
	PrecompileSetBuilder<R, (PrecompileAt<AddressU64<1>, CrowdloanRewardsPrecompile<R>>,)>;
156

            
157
pub type PCall = CrowdloanRewardsPrecompileCall<Runtime>;
158

            
159
const MAX_POV_SIZE: u64 = 5 * 1024 * 1024;
160
/// Block storage limit in bytes. Set to 40 KB.
161
const BLOCK_STORAGE_LIMIT: u64 = 40 * 1024;
162

            
163
parameter_types! {
164
	pub BlockGasLimit: U256 = U256::from(u64::MAX);
165
	pub PrecompilesValue: Precompiles<Runtime> = Precompiles::new();
166
	pub const WeightPerGas: Weight = Weight::from_parts(1, 0);
167
	pub GasLimitPovSizeRatio: u64 = {
168
		let block_gas_limit = BlockGasLimit::get().min(u64::MAX.into()).low_u64();
169
		block_gas_limit.saturating_div(MAX_POV_SIZE)
170
	};
171
	pub GasLimitStorageGrowthRatio: u64 = {
172
		let block_gas_limit = BlockGasLimit::get().min(u64::MAX.into()).low_u64();
173
		block_gas_limit.saturating_div(BLOCK_STORAGE_LIMIT)
174
	};
175
	pub SuicideQuickClearLimit: u32 = 0;
176
}
177

            
178
impl pallet_evm::Config for Runtime {
179
	type FeeCalculator = ();
180
	type GasWeightMapping = pallet_evm::FixedGasWeightMapping<Self>;
181
	type WeightPerGas = WeightPerGas;
182
	type CallOrigin = EnsureAddressRoot<AccountId>;
183
	type WithdrawOrigin = EnsureAddressNever<AccountId>;
184
	type AddressMapping = AccountId;
185
	type Currency = Balances;
186
	type RuntimeEvent = RuntimeEvent;
187
	type Runner = pallet_evm::runner::stack::Runner<Self>;
188
	type PrecompilesValue = PrecompilesValue;
189
	type PrecompilesType = Precompiles<Self>;
190
	type ChainId = ();
191
	type OnChargeTransaction = ();
192
	type BlockGasLimit = BlockGasLimit;
193
	type BlockHashMapping = pallet_evm::SubstrateBlockHashMapping<Self>;
194
	type FindAuthor = ();
195
	type OnCreate = ();
196
	type GasLimitPovSizeRatio = GasLimitPovSizeRatio;
197
	type SuicideQuickClearLimit = SuicideQuickClearLimit;
198
	type GasLimitStorageGrowthRatio = GasLimitStorageGrowthRatio;
199
	type Timestamp = Timestamp;
200
	type WeightInfo = pallet_evm::weights::SubstrateWeight<Runtime>;
201
}
202

            
203
parameter_types! {
204
	pub const MinimumPeriod: u64 = 5;
205
}
206
impl pallet_timestamp::Config for Runtime {
207
	type Moment = u64;
208
	type OnTimestampSet = ();
209
	type MinimumPeriod = MinimumPeriod;
210
	type WeightInfo = ();
211
}
212

            
213
parameter_types! {
214
	pub const TestMaxInitContributors: u32 = 8;
215
	pub const TestMinimumReward: u128 = 0;
216
	pub const TestInitialized: bool = false;
217
	pub const TestInitializationPayment: Perbill = Perbill::from_percent(20);
218
	pub const RelaySignaturesThreshold: Perbill = Perbill::from_percent(100);
219
	pub const TestSignatureNetworkIdentifier: &'static [u8] = b"test-";
220
}
221

            
222
impl pallet_crowdloan_rewards::Config for Runtime {
223
	type RuntimeEvent = RuntimeEvent;
224
	type Initialized = TestInitialized;
225
	type InitializationPayment = TestInitializationPayment;
226
	type MaxInitContributors = TestMaxInitContributors;
227
	type MinimumReward = TestMinimumReward;
228
	type RewardCurrency = Balances;
229
	type RelayChainAccountId = [u8; 32];
230
	type RewardAddressAssociateOrigin = EnsureSigned<Self::AccountId>;
231
	type RewardAddressRelayVoteThreshold = RelaySignaturesThreshold;
232
	type RewardAddressChangeOrigin = EnsureSigned<Self::AccountId>;
233
	type SignatureNetworkIdentifier = TestSignatureNetworkIdentifier;
234

            
235
	type VestingBlockNumber = cumulus_primitives_core::relay_chain::BlockNumber;
236
	type VestingBlockProvider = cumulus_pallet_parachain_system::RelaychainDataProvider<Self>;
237
	type WeightInfo = ();
238
}
239
pub(crate) struct ExtBuilder {
240
	// endowed accounts with balances
241
	balances: Vec<(AccountId, Balance)>,
242
	crowdloan_pot: Balance,
243
}
244

            
245
impl Default for ExtBuilder {
246
9
	fn default() -> ExtBuilder {
247
9
		ExtBuilder {
248
9
			balances: vec![],
249
9
			crowdloan_pot: 0u32.into(),
250
9
		}
251
9
	}
252
}
253

            
254
impl ExtBuilder {
255
6
	pub(crate) fn with_balances(mut self, balances: Vec<(AccountId, Balance)>) -> Self {
256
6
		self.balances = balances;
257
6
		self
258
6
	}
259
5
	pub(crate) fn with_crowdloan_pot(mut self, pot: Balance) -> Self {
260
5
		self.crowdloan_pot = pot;
261
5
		self
262
5
	}
263
9
	pub(crate) fn build(self) -> sp_io::TestExternalities {
264
9
		let mut t = frame_system::GenesisConfig::<Runtime>::default()
265
9
			.build_storage()
266
9
			.expect("Frame system builds valid default genesis config");
267
9

            
268
9
		pallet_balances::GenesisConfig::<Runtime> {
269
9
			balances: self.balances,
270
9
		}
271
9
		.assimilate_storage(&mut t)
272
9
		.expect("Pallet balances storage can be assimilated");
273
9

            
274
9
		pallet_crowdloan_rewards::GenesisConfig::<Runtime> {
275
9
			funded_amount: self.crowdloan_pot,
276
9
		}
277
9
		.assimilate_storage(&mut t)
278
9
		.expect("Crowdloan Rewards storage can be assimilated");
279
9

            
280
9
		let mut ext = sp_io::TestExternalities::new(t);
281
9
		ext.execute_with(|| System::set_block_number(1));
282
9
		ext
283
9
	}
284
}
285

            
286
//TODO Add pallets here if necessary
287
7
pub(crate) fn roll_to(n: BlockNumber) {
288
20
	while System::block_number() < n {
289
13
		// Relay chain Stuff. I might actually set this to a number different than N
290
13
		let sproof_builder = RelayStateSproofBuilder::default();
291
13
		let (relay_parent_storage_root, relay_chain_state) =
292
13
			sproof_builder.into_state_root_and_proof();
293
13
		let vfp = PersistedValidationData {
294
13
			relay_parent_number: (System::block_number() + 1) as RelayChainBlockNumber,
295
13
			relay_parent_storage_root,
296
13
			..Default::default()
297
13
		};
298
13
		let inherent_data = {
299
13
			let mut inherent_data = InherentData::default();
300
13
			let system_inherent_data = ParachainInherentData {
301
13
				validation_data: vfp.clone(),
302
13
				relay_chain_state,
303
13
				downward_messages: Default::default(),
304
13
				horizontal_messages: Default::default(),
305
13
			};
306
13
			inherent_data
307
13
				.put_data(
308
13
					cumulus_primitives_parachain_inherent::INHERENT_IDENTIFIER,
309
13
					&system_inherent_data,
310
13
				)
311
13
				.expect("failed to put VFP inherent");
312
13
			inherent_data
313
13
		};
314
13

            
315
13
		ParachainSystem::on_initialize(System::block_number());
316
13
		ParachainSystem::create_inherent(&inherent_data)
317
13
			.expect("got an inherent")
318
13
			.dispatch_bypass_filter(RawOrigin::None.into())
319
13
			.expect("dispatch succeeded");
320
13
		ParachainSystem::on_finalize(System::block_number());
321
13

            
322
13
		Balances::on_finalize(System::block_number());
323
13
		System::on_finalize(System::block_number());
324
13
		System::set_block_number(System::block_number() + 1);
325
13
		System::on_initialize(System::block_number());
326
13
		Balances::on_initialize(System::block_number());
327
13
	}
328
7
}
329

            
330
2
pub(crate) fn events() -> Vec<RuntimeEvent> {
331
2
	System::events()
332
2
		.into_iter()
333
17
		.map(|r| r.event)
334
2
		.collect::<Vec<_>>()
335
2
}