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
11
	pub enum Runtime {
39
11
		System: frame_system,
40
11
		Balances: pallet_balances,
41
11
		Evm: pallet_evm,
42
11
		Timestamp: pallet_timestamp,
43
11
		RelayStorageRoots: pallet_relay_storage_roots,
44
11
		PrecompileBenchmarks: pallet_precompile_benchmarks
45
11
	}
46
301
);
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
	type ExtensionsWeightInfo = ();
89
}
90

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

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

            
112
parameter_types! {
113
	pub const MinimumPeriod: u64 = 5;
114
}
115

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

            
123
pub struct PersistedValidationDataGetter;
124

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

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

            
140
parameter_types! {
141
	pub const MaxStorageRoots: u32 = 3;
142
}
143

            
144
impl pallet_relay_storage_roots::Config for Runtime {
145
	type MaxStorageRoots = MaxStorageRoots;
146
	type RelaychainStateProvider = PersistedValidationDataGetter;
147
	type WeightInfo = ();
148
}
149

            
150
pub struct MockWeightInfo;
151

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

            
166
pub type Precompiles<R> = PrecompileSetBuilder<
167
	R,
168
	PrecompileAt<AddressU64<1>, RelayDataVerifierPrecompile<R, MockWeightInfo>>,
169
>;
170

            
171
pub type PCall = RelayDataVerifierPrecompileCall<Runtime, MockWeightInfo>;
172

            
173
const MAX_POV_SIZE: u64 = 5 * 1024 * 1024;
174
/// Block storage limit in bytes. Set to 40 KB.
175
const BLOCK_STORAGE_LIMIT: u64 = 40 * 1024;
176

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

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

            
216
impl pallet_precompile_benchmarks::Config for Runtime {
217
	type WeightInfo = MockWeightInfo;
218
}
219

            
220
pub(crate) struct ExtBuilder {
221
	// endowed accounts with balances
222
	balances: Vec<(AccountId, Balance)>,
223
}
224

            
225
impl Default for ExtBuilder {
226
11
	fn default() -> ExtBuilder {
227
11
		ExtBuilder { balances: vec![] }
228
11
	}
229
}
230

            
231
impl ExtBuilder {
232
8
	pub(crate) fn with_balances(mut self, balances: Vec<(AccountId, Balance)>) -> Self {
233
8
		self.balances = balances;
234
8
		self
235
8
	}
236

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

            
242
11
		pallet_balances::GenesisConfig::<Runtime> {
243
11
			balances: self.balances,
244
11
		}
245
11
		.assimilate_storage(&mut t)
246
11
		.expect("Pallet balances storage can be assimilated");
247
11

            
248
11
		let mut ext = sp_io::TestExternalities::new(t);
249
11
		ext.execute_with(|| System::set_block_number(1));
250
11

            
251
11
		ext
252
11
	}
253
}
254

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

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

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

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

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

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

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

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