1
// Copyright 2025 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
//! Test utilities
18
#![allow(non_camel_case_types)]
19

            
20
use super::*;
21
use cumulus_pallet_parachain_system::{RelayChainState, RelaychainStateProvider};
22
use frame_support::{
23
	construct_runtime, parameter_types,
24
	sp_runtime::traits::IdentityLookup,
25
	traits::Everything,
26
	weights::{RuntimeDbWeight, Weight},
27
};
28
use pallet_evm::{
29
	EnsureAddressNever, EnsureAddressRoot, FrameSystemAccountProvider, SubstrateBlockHashMapping,
30
};
31
use parity_scale_codec::Decode;
32
use precompile_utils::{precompile_set::*, testing::MockAccount};
33
use sp_core::{Get, U256};
34
use sp_runtime::{traits::BlakeTwo256, BuildStorage};
35

            
36
// Configure a mock runtime to test the pallet.
37
300
construct_runtime!(
38
	pub enum Runtime {
39
		System: frame_system,
40
		Balances: pallet_balances,
41
		Evm: pallet_evm,
42
		Timestamp: pallet_timestamp,
43
		RelayStorageRoots: pallet_relay_storage_roots,
44
		PrecompileBenchmarks: pallet_precompile_benchmarks
45
	}
46
978
);
47

            
48
pub type AccountId = MockAccount;
49

            
50
pub type Balance = u128;
51
type Block = frame_system::mocking::MockBlockU32<Runtime>;
52

            
53
parameter_types! {
54
	pub const BlockHashCount: u32 = 250;
55
	pub const SS58Prefix: u8 = 42;
56
}
57

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

            
90
parameter_types! {
91
	pub const ExistentialDeposit: u128 = 1;
92
}
93

            
94
impl pallet_balances::Config for Runtime {
95
	type MaxReserves = ();
96
	type ReserveIdentifier = ();
97
	type MaxLocks = ();
98
	type Balance = Balance;
99
	type RuntimeEvent = RuntimeEvent;
100
	type DustRemoval = ();
101
	type ExistentialDeposit = ExistentialDeposit;
102
	type AccountStore = System;
103
	type WeightInfo = ();
104
	type RuntimeHoldReason = ();
105
	type FreezeIdentifier = ();
106
	type MaxFreezes = ();
107
	type RuntimeFreezeReason = ();
108
}
109

            
110
parameter_types! {
111
	pub const MinimumPeriod: u64 = 5;
112
}
113

            
114
impl pallet_timestamp::Config for Runtime {
115
	type Moment = u64;
116
	type OnTimestampSet = ();
117
	type MinimumPeriod = MinimumPeriod;
118
	type WeightInfo = ();
119
}
120

            
121
pub struct PersistedValidationDataGetter;
122

            
123
impl RelaychainStateProvider for PersistedValidationDataGetter {
124
48
	fn current_relay_chain_state() -> RelayChainState {
125
48
		frame_support::storage::unhashed::get(b"MOCK_PERSISTED_VALIDATION_DATA").unwrap()
126
48
	}
127

            
128
	#[cfg(feature = "runtime-benchmarks")]
129
	fn set_current_relay_chain_state(state: RelayChainState) {
130
		frame_support::storage::unhashed::put(b"MOCK_PERSISTED_VALIDATION_DATA", &state);
131
	}
132
}
133

            
134
27
pub fn set_current_relay_chain_state(block_number: u32, state_root: H256) {
135
27
	let state = RelayChainState {
136
27
		number: block_number,
137
27
		state_root,
138
27
	};
139
27
	frame_support::storage::unhashed::put(b"MOCK_PERSISTED_VALIDATION_DATA", &state);
140
27
	pallet_relay_storage_roots::Pallet::<Runtime>::set_relay_storage_root();
141
27
}
142

            
143
parameter_types! {
144
	pub const MaxStorageRoots: u32 = 3;
145
}
146

            
147
impl pallet_relay_storage_roots::Config for Runtime {
148
	type MaxStorageRoots = MaxStorageRoots;
149
	type RelaychainStateProvider = PersistedValidationDataGetter;
150
	type WeightInfo = ();
151
}
152

            
153
pub struct MockWeightInfo;
154

            
155
impl pallet_precompile_benchmarks::WeightInfo for MockWeightInfo {
156
8
	fn verify_entry(x: u32) -> Weight {
157
8
		Weight::from_parts(76_430_000, 0)
158
8
			.saturating_add(Weight::from_parts(678_469, 0).saturating_mul(x.into()))
159
8
	}
160
4
	fn latest_relay_block() -> Weight {
161
4
		Weight::from_parts(4_641_000, 1606)
162
4
			.saturating_add(<() as Get<RuntimeDbWeight>>::get().reads(1_u64))
163
4
	}
164
	fn p256_verify() -> Weight {
165
		Weight::from_parts(1_580_914_000, 0).saturating_mul(1u64)
166
	}
167
}
168

            
169
pub type Precompiles<R> = PrecompileSetBuilder<
170
	R,
171
	PrecompileAt<AddressU64<1>, RelayDataVerifierPrecompile<R, MockWeightInfo>>,
172
>;
173

            
174
pub type PCall = RelayDataVerifierPrecompileCall<Runtime, MockWeightInfo>;
175

            
176
const MAX_POV_SIZE: u64 = 5 * 1024 * 1024;
177
/// Block storage limit in bytes. Set to 40 KB.
178
const BLOCK_STORAGE_LIMIT: u64 = 40 * 1024;
179

            
180
parameter_types! {
181
	pub BlockGasLimit: U256 = U256::from(u64::MAX);
182
	pub PrecompilesValue: Precompiles<Runtime> = Precompiles::new();
183
	pub const WeightPerGas: Weight = Weight::from_parts(1, 0);
184
	pub GasLimitPovSizeRatio: u64 = {
185
		let block_gas_limit = BlockGasLimit::get().min(u64::MAX.into()).low_u64();
186
		block_gas_limit.saturating_div(MAX_POV_SIZE)
187
	};
188
	pub GasLimitStorageGrowthRatio: u64 = {
189
		let block_gas_limit = BlockGasLimit::get().min(u64::MAX.into()).low_u64();
190
		block_gas_limit.saturating_div(BLOCK_STORAGE_LIMIT)
191
	};
192
}
193

            
194
impl pallet_evm::Config for Runtime {
195
	type FeeCalculator = ();
196
	type GasWeightMapping = pallet_evm::FixedGasWeightMapping<Self>;
197
	type WeightPerGas = WeightPerGas;
198
	type CallOrigin = EnsureAddressRoot<AccountId>;
199
	type WithdrawOrigin = EnsureAddressNever<AccountId>;
200
	type AddressMapping = AccountId;
201
	type Currency = Balances;
202
	type RuntimeEvent = RuntimeEvent;
203
	type Runner = pallet_evm::runner::stack::Runner<Self>;
204
	type PrecompilesValue = PrecompilesValue;
205
	type PrecompilesType = Precompiles<Self>;
206
	type ChainId = ();
207
	type OnChargeTransaction = ();
208
	type BlockGasLimit = BlockGasLimit;
209
	type BlockHashMapping = SubstrateBlockHashMapping<Self>;
210
	type FindAuthor = ();
211
	type OnCreate = ();
212
	type GasLimitPovSizeRatio = GasLimitPovSizeRatio;
213
	type SuicideQuickClearLimit = ConstU32<0>;
214
	type GasLimitStorageGrowthRatio = GasLimitStorageGrowthRatio;
215
	type Timestamp = Timestamp;
216
	type WeightInfo = pallet_evm::weights::SubstrateWeight<Runtime>;
217
	type AccountProvider = FrameSystemAccountProvider<Runtime>;
218
}
219

            
220
impl pallet_precompile_benchmarks::Config for Runtime {
221
	type WeightInfo = MockWeightInfo;
222
}
223

            
224
pub(crate) struct ExtBuilder {
225
	// endowed accounts with balances
226
	balances: Vec<(AccountId, Balance)>,
227
}
228

            
229
impl Default for ExtBuilder {
230
11
	fn default() -> ExtBuilder {
231
11
		ExtBuilder { balances: vec![] }
232
11
	}
233
}
234

            
235
impl ExtBuilder {
236
8
	pub(crate) fn with_balances(mut self, balances: Vec<(AccountId, Balance)>) -> Self {
237
8
		self.balances = balances;
238
8
		self
239
8
	}
240

            
241
11
	pub(crate) fn build(self) -> sp_io::TestExternalities {
242
11
		let mut t = frame_system::GenesisConfig::<Runtime>::default()
243
11
			.build_storage()
244
11
			.expect("Frame system builds valid default genesis config");
245
11

            
246
11
		pallet_balances::GenesisConfig::<Runtime> {
247
11
			balances: self.balances,
248
11
		}
249
11
		.assimilate_storage(&mut t)
250
11
		.expect("Pallet balances storage can be assimilated");
251
11

            
252
11
		let mut ext = sp_io::TestExternalities::new(t);
253
11
		ext.execute_with(|| System::set_block_number(1));
254
11

            
255
11
		ext
256
11
	}
257
}
258

            
259
7
pub fn fill_relay_storage_roots<T: pallet_relay_storage_roots::Config>() {
260
21
	(1..=T::MaxStorageRoots::get()).for_each(|i| {
261
21
		set_current_relay_chain_state(i, H256::default());
262
21
		pallet_relay_storage_roots::Pallet::<T>::set_relay_storage_root();
263
21
	})
264
7
}
265

            
266
// Storage Root: 767caa877bcea0d34dd515a202b75efa41bffbc9f814ab59e2c1c96716d4c65d
267
pub const STORAGE_ROOT: &[u8] = &[
268
	118, 124, 170, 135, 123, 206, 160, 211, 77, 213, 21, 162, 2, 183, 94, 250, 65, 191, 251, 201,
269
	248, 20, 171, 89, 226, 193, 201, 103, 22, 212, 198, 93,
270
];
271

            
272
// Timestamp key: f0c365c3cf59d671eb72da0e7a4113c49f1f0515f462cdcf84e0f1d6045dfcbb
273
pub const TIMESTAMP_KEY: &[u8] = &[
274
	240, 195, 101, 195, 207, 89, 214, 113, 235, 114, 218, 14, 122, 65, 19, 196, 159, 31, 5, 21,
275
	244, 98, 205, 207, 132, 224, 241, 214, 4, 93, 252, 187,
276
];
277

            
278
// Total Issuance Key: c2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80
279
pub const TOTAL_ISSUANCE_KEY: &[u8] = &[
280
	194, 38, 18, 118, 204, 157, 31, 133, 152, 234, 75, 106, 116, 177, 92, 47, 87, 200, 117, 228,
281
	207, 247, 65, 72, 228, 98, 143, 38, 75, 151, 76, 128,
282
];
283

            
284
// Treasury Approval Key: 89d139e01a5eb2256f222e5fc5dbe6b33c9c1284130706f5aea0c8b3d4c54d89
285
pub const TREASURY_APPROVALS_KEY: &[u8] = &[
286
	137, 209, 57, 224, 26, 94, 178, 37, 111, 34, 46, 95, 197, 219, 230, 179, 60, 156, 18, 132, 19,
287
	7, 6, 245, 174, 160, 200, 179, 212, 197, 77, 137,
288
];
289

            
290
// Mock a storage proof obtained from the relay chain using the
291
// state_getReadProof RPC call, for the following keys:
292
// TimeStamp:
293
// 0xf0c365c3cf59d671eb72da0e7a4113c49f1f0515f462cdcf84e0f1d6045dfcbb
294
// Balances (Total Issuance):
295
// 0xc2261276cc9d1f8598ea4b6a74b15c2f57c875e4cff74148e4628f264b974c80
296
// Treasury Approvals
297
// 0x89d139e01a5eb2256f222e5fc5dbe6b33c9c1284130706f5aea0c8b3d4c54d89
298
// at Block Hash:
299
// 0x1272470f226fc0e955838262e8dd17a7d7bad6563739cc53a3b1744ddf0ea872
300

            
301
9
pub fn mocked_read_proof() -> ReadProof {
302
9
	// Mock a storage proof obtained from the relay chain using the
303
9
	// state_getReadProof RPC call, for the following
304
9
	let proof: Vec<Vec<u8>> = Vec::decode(&mut &include_bytes!("../proof").to_vec()[..]).unwrap();
305
9

            
306
9
	ReadProof {
307
9
		at: H256::default(),
308
9
		proof: BoundedVec::from(
309
9
			proof
310
9
				.iter()
311
72
				.map(|x| BoundedBytes::from(x.clone()))
312
9
				.collect::<Vec<_>>(),
313
9
		),
314
9
	}
315
9
}