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
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
);
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 Runner = pallet_evm::runner::stack::Runner<Self>;
200
	type PrecompilesValue = PrecompilesValue;
201
	type PrecompilesType = Precompiles<Self>;
202
	type ChainId = ();
203
	type OnChargeTransaction = ();
204
	type BlockGasLimit = BlockGasLimit;
205
	type BlockHashMapping = SubstrateBlockHashMapping<Self>;
206
	type FindAuthor = ();
207
	type OnCreate = ();
208
	type GasLimitPovSizeRatio = GasLimitPovSizeRatio;
209
	type GasLimitStorageGrowthRatio = GasLimitStorageGrowthRatio;
210
	type Timestamp = Timestamp;
211
	type WeightInfo = pallet_evm::weights::SubstrateWeight<Runtime>;
212
	type AccountProvider = FrameSystemAccountProvider<Runtime>;
213
	type CreateOriginFilter = ();
214
	type CreateInnerOriginFilter = ();
215
}
216

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

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

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

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

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

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

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

            
253
11
		ext
254
11
	}
255
}
256

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

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

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

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

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

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

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

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