moonbeam_runtime/
genesis_config_preset.rs

1// Copyright 2019-2025 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
17extern crate alloc;
18
19use crate::{
20	currency::GLMR, currency::SUPPLY_FACTOR, AccountId, AuthorFilterConfig, AuthorMappingConfig,
21	Balance, Balances, BalancesConfig, BridgeKusamaGrandpaConfig, BridgeKusamaMessagesConfig,
22	BridgeKusamaParachainsConfig, BridgeXcmOverMoonriverConfig, EVMConfig, EligibilityValue,
23	EthereumChainIdConfig, EthereumConfig, EvmForeignAssetsConfig, InflationInfo,
24	MaintenanceModeConfig, OpenTechCommitteeCollectiveConfig, ParachainInfoConfig,
25	ParachainStakingConfig, PolkadotXcmConfig, Precompiles, Range, RuntimeGenesisConfig,
26	TransactionPaymentConfig, TreasuryCouncilCollectiveConfig, XcmWeightTraderConfig, HOURS,
27};
28use alloc::{vec, vec::Vec};
29use bp_messages::MessagesOperatingMode;
30use bp_runtime::BasicOperatingMode;
31use cumulus_primitives_core::ParaId;
32use fp_evm::GenesisAccount;
33use frame_support::pallet_prelude::PalletInfoAccess;
34use nimbus_primitives::NimbusId;
35use pallet_moonbeam_foreign_assets::EvmForeignAssetInfo;
36use pallet_transaction_payment::Multiplier;
37use pallet_xcm_weight_trader::XcmWeightTraderAssetInfo;
38use sp_genesis_builder::PresetId;
39use sp_keyring::Sr25519Keyring;
40use sp_runtime::{Perbill, Percent};
41use xcm::prelude::{GlobalConsensus, Junctions, Location, NetworkId, PalletInstance, Parachain};
42
43const COLLATOR_COMMISSION: Perbill = Perbill::from_percent(20);
44const PARACHAIN_BOND_RESERVE_PERCENT: Percent = Percent::from_percent(30);
45const BLOCKS_PER_ROUND: u32 = 6 * HOURS;
46const BLOCKS_PER_YEAR: u32 = 31_557_600 / 12;
47const NUM_SELECTED_CANDIDATES: u32 = 8;
48
49pub fn moonbeam_inflation_config() -> InflationInfo<Balance> {
50	fn to_round_inflation(annual: Range<Perbill>) -> Range<Perbill> {
51		use pallet_parachain_staking::inflation::perbill_annual_to_perbill_round;
52		perbill_annual_to_perbill_round(
53			annual,
54			// rounds per year
55			BLOCKS_PER_YEAR / BLOCKS_PER_ROUND,
56		)
57	}
58	let annual = Range {
59		min: Perbill::from_percent(4),
60		ideal: Perbill::from_percent(5),
61		max: Perbill::from_percent(5),
62	};
63	InflationInfo {
64		// staking expectations
65		expect: Range {
66			min: 100_000 * GLMR * SUPPLY_FACTOR,
67			ideal: 200_000 * GLMR * SUPPLY_FACTOR,
68			max: 500_000 * GLMR * SUPPLY_FACTOR,
69		},
70		// annual inflation
71		annual,
72		round: to_round_inflation(annual),
73	}
74}
75
76pub fn testnet_genesis(
77	treasury_council_members: Vec<AccountId>,
78	open_tech_committee_members: Vec<AccountId>,
79	candidates: Vec<(AccountId, NimbusId, Balance)>,
80	delegations: Vec<(AccountId, AccountId, Balance, Percent)>,
81	endowed_accounts: Vec<AccountId>,
82	para_id: ParaId,
83	chain_id: u64,
84) -> serde_json::Value {
85	// This is the simplest bytecode to revert without returning any data.
86	// We will pre-deploy it under all of our precompiles to ensure they can be called from
87	// within contracts.
88	// (PUSH1 0x00 PUSH1 0x00 REVERT)
89	let revert_bytecode = vec![0x60, 0x00, 0x60, 0x00, 0xFD];
90
91	let config = RuntimeGenesisConfig {
92		system: Default::default(),
93		balances: BalancesConfig {
94			balances: endowed_accounts
95				.iter()
96				.cloned()
97				.map(|k| (k, 1 << 110))
98				.collect(),
99			dev_accounts: Default::default(),
100		},
101		parachain_info: ParachainInfoConfig {
102			parachain_id: para_id,
103			..Default::default()
104		},
105		ethereum_chain_id: EthereumChainIdConfig {
106			chain_id,
107			..Default::default()
108		},
109		evm: EVMConfig {
110			// We need _some_ code inserted at the precompile address so that
111			// the evm will actually call the address.
112			accounts: Precompiles::used_addresses()
113				.map(|addr| {
114					(
115						addr.into(),
116						GenesisAccount {
117							nonce: Default::default(),
118							balance: Default::default(),
119							storage: Default::default(),
120							code: revert_bytecode.clone(),
121						},
122					)
123				})
124				.collect(),
125			..Default::default()
126		},
127		ethereum: EthereumConfig {
128			..Default::default()
129		},
130		parachain_staking: ParachainStakingConfig {
131			candidates: candidates
132				.iter()
133				.cloned()
134				.map(|(account, _, bond)| (account, bond))
135				.collect(),
136			delegations,
137			inflation_config: moonbeam_inflation_config(),
138			collator_commission: COLLATOR_COMMISSION,
139			parachain_bond_reserve_percent: PARACHAIN_BOND_RESERVE_PERCENT,
140			blocks_per_round: BLOCKS_PER_ROUND,
141			num_selected_candidates: NUM_SELECTED_CANDIDATES,
142		},
143		treasury_council_collective: TreasuryCouncilCollectiveConfig {
144			phantom: Default::default(),
145			members: treasury_council_members,
146		},
147		open_tech_committee_collective: OpenTechCommitteeCollectiveConfig {
148			phantom: Default::default(),
149			members: open_tech_committee_members,
150		},
151		author_filter: AuthorFilterConfig {
152			eligible_count: EligibilityValue::new_unchecked(50),
153			..Default::default()
154		},
155		author_mapping: AuthorMappingConfig {
156			mappings: candidates
157				.iter()
158				.cloned()
159				.map(|(account_id, author_id, _)| (author_id, account_id))
160				.collect(),
161		},
162		proxy_genesis_companion: Default::default(),
163		treasury: Default::default(),
164		maintenance_mode: MaintenanceModeConfig {
165			start_in_maintenance_mode: false,
166			..Default::default()
167		},
168		polkadot_xcm: PolkadotXcmConfig {
169			supported_version: vec![
170				// Required for bridging Moonbeam with Moonriver
171				(
172					bp_moonriver::GlobalConsensusLocation::get(),
173					xcm::latest::VERSION,
174				),
175			],
176			..Default::default()
177		},
178		transaction_payment: TransactionPaymentConfig {
179			multiplier: Multiplier::from(8u128),
180			..Default::default()
181		},
182		evm_foreign_assets: EvmForeignAssetsConfig {
183			assets: vec![EvmForeignAssetInfo {
184				asset_id: 1001,
185				name: b"xcMOVR".to_vec().try_into().expect("Invalid asset name"),
186				symbol: b"xcMOVR".to_vec().try_into().expect("Invalid asset symbol"),
187				decimals: 18,
188				xcm_location: Location::new(
189					2,
190					[
191						GlobalConsensus(crate::bridge_config::KusamaGlobalConsensusNetwork::get()),
192						Parachain(<bp_moonriver::Moonriver as bp_runtime::Parachain>::PARACHAIN_ID),
193						PalletInstance(<Balances as PalletInfoAccess>::index() as u8),
194					],
195				),
196			}],
197			_phantom: Default::default(),
198		},
199		xcm_weight_trader: XcmWeightTraderConfig {
200			assets: vec![XcmWeightTraderAssetInfo {
201				location: Location::new(
202					2,
203					[
204						GlobalConsensus(crate::bridge_config::KusamaGlobalConsensusNetwork::get()),
205						Parachain(<bp_moonriver::Moonriver as bp_runtime::Parachain>::PARACHAIN_ID),
206						PalletInstance(<Balances as PalletInfoAccess>::index() as u8),
207					],
208				),
209				relative_price: GLMR,
210			}],
211			_phantom: Default::default(),
212		},
213		bridge_kusama_grandpa: BridgeKusamaGrandpaConfig {
214			owner: Some(endowed_accounts[0]),
215			init_data: None,
216		},
217		bridge_kusama_parachains: BridgeKusamaParachainsConfig {
218			owner: Some(endowed_accounts[0]),
219			operating_mode: BasicOperatingMode::Normal,
220			..Default::default()
221		},
222		bridge_kusama_messages: BridgeKusamaMessagesConfig {
223			owner: Some(endowed_accounts[0]),
224			opened_lanes: vec![],
225			operating_mode: MessagesOperatingMode::Basic(BasicOperatingMode::Normal),
226			_phantom: Default::default(),
227		},
228		bridge_xcm_over_moonriver: BridgeXcmOverMoonriverConfig {
229			opened_bridges: vec![(
230				Location::new(
231					1,
232					[Parachain(
233						<bp_moonbeam::Moonbeam as bp_runtime::Parachain>::PARACHAIN_ID,
234					)],
235				),
236				Junctions::from([
237					NetworkId::Kusama.into(),
238					Parachain(<bp_moonriver::Moonriver as bp_runtime::Parachain>::PARACHAIN_ID),
239				]),
240				Some(Default::default()),
241			)],
242			_phantom: Default::default(),
243		},
244	};
245
246	serde_json::to_value(&config).expect("Could not build genesis config.")
247}
248
249/// Generate a chain spec for use with the development service.
250pub fn development() -> serde_json::Value {
251	testnet_genesis(
252		// Treasury Council members: Baltathar, Charleth and Dorothy
253		vec![
254			AccountId::from(sp_core::hex2array!(
255				"3Cd0A705a2DC65e5b1E1205896BaA2be8A07c6e0"
256			)),
257			AccountId::from(sp_core::hex2array!(
258				"798d4Ba9baf0064Ec19eB4F0a1a45785ae9D6DFc"
259			)),
260			AccountId::from(sp_core::hex2array!(
261				"773539d4Ac0e786233D90A233654ccEE26a613D9"
262			)),
263		],
264		// Open Tech committee members: Alith and Baltathar
265		vec![
266			AccountId::from(sp_core::hex2array!(
267				"f24FF3a9CF04c71Dbc94D0b566f7A27B94566cac"
268			)),
269			AccountId::from(sp_core::hex2array!(
270				"3Cd0A705a2DC65e5b1E1205896BaA2be8A07c6e0"
271			)),
272		],
273		// Collator Candidate: Alice -> Alith
274		vec![(
275			AccountId::from(sp_core::hex2array!(
276				"f24FF3a9CF04c71Dbc94D0b566f7A27B94566cac"
277			)),
278			NimbusId::from(Sr25519Keyring::Alice.public()),
279			20_000 * GLMR * SUPPLY_FACTOR,
280		)],
281		// Delegations
282		vec![],
283		vec![
284			AccountId::from(sp_core::hex2array!(
285				"f24FF3a9CF04c71Dbc94D0b566f7A27B94566cac"
286			)),
287			AccountId::from(sp_core::hex2array!(
288				"3Cd0A705a2DC65e5b1E1205896BaA2be8A07c6e0"
289			)),
290			AccountId::from(sp_core::hex2array!(
291				"798d4Ba9baf0064Ec19eB4F0a1a45785ae9D6DFc"
292			)),
293			AccountId::from(sp_core::hex2array!(
294				"773539d4Ac0e786233D90A233654ccEE26a613D9"
295			)),
296		],
297		Default::default(), // para_id
298		1281,               //ChainId
299	)
300}
301
302/// Provides the JSON representation of predefined genesis config for given `id`.
303pub fn get_preset(id: &PresetId) -> Option<Vec<u8>> {
304	let patch = match id.as_str() {
305		sp_genesis_builder::DEV_RUNTIME_PRESET => development(),
306		_ => return None,
307	};
308	Some(
309		serde_json::to_string(&patch)
310			.expect("serialization to json is expected to work. qed.")
311			.into_bytes(),
312	)
313}
314
315/// List of supported presets.
316pub fn preset_names() -> Vec<PresetId> {
317	vec![PresetId::from(sp_genesis_builder::DEV_RUNTIME_PRESET)]
318}