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