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
extern crate alloc;
18

            
19
use crate::{
20
	currency::UNIT, AccountId, AuthorFilterConfig, AuthorMappingConfig, Balance, BalancesConfig,
21
	CrowdloanRewardsConfig, EVMConfig, EligibilityValue, EthereumChainIdConfig, EthereumConfig,
22
	InflationInfo, MaintenanceModeConfig, MoonbeamOrbitersConfig,
23
	OpenTechCommitteeCollectiveConfig, ParachainInfoConfig, ParachainStakingConfig,
24
	PolkadotXcmConfig, Precompiles, Range, RuntimeGenesisConfig, SudoConfig,
25
	TransactionPaymentConfig, TreasuryCouncilCollectiveConfig, XcmTransactorConfig, HOURS,
26
};
27
use alloc::{vec, vec::Vec};
28
use cumulus_primitives_core::ParaId;
29
use fp_evm::GenesisAccount;
30
use nimbus_primitives::NimbusId;
31
use pallet_transaction_payment::Multiplier;
32
use parachains_common::genesis_config_helpers::get_from_seed;
33
use sp_genesis_builder::PresetId;
34
use sp_runtime::{traits::One, Perbill, Percent};
35

            
36
const COLLATOR_COMMISSION: Perbill = Perbill::from_percent(20);
37
const PARACHAIN_BOND_RESERVE_PERCENT: Percent = Percent::from_percent(30);
38
const BLOCKS_PER_ROUND: u32 = 2 * HOURS;
39
const BLOCKS_PER_YEAR: u32 = 31_557_600 / 6;
40
const NUM_SELECTED_CANDIDATES: u32 = 8;
41

            
42
26
pub fn moonbase_inflation_config() -> InflationInfo<Balance> {
43
26
	fn to_round_inflation(annual: Range<Perbill>) -> Range<Perbill> {
44
26
		use pallet_parachain_staking::inflation::perbill_annual_to_perbill_round;
45
26
		perbill_annual_to_perbill_round(
46
26
			annual,
47
26
			// rounds per year
48
26
			BLOCKS_PER_YEAR / BLOCKS_PER_ROUND,
49
26
		)
50
26
	}
51
26
	let annual = Range {
52
26
		min: Perbill::from_percent(4),
53
26
		ideal: Perbill::from_percent(5),
54
26
		max: Perbill::from_percent(5),
55
26
	};
56
26
	InflationInfo {
57
26
		// staking expectations
58
26
		expect: Range {
59
26
			min: 100_000 * UNIT,
60
26
			ideal: 200_000 * UNIT,
61
26
			max: 500_000 * UNIT,
62
26
		},
63
26
		// annual inflation
64
26
		annual,
65
26
		round: to_round_inflation(annual),
66
26
	}
67
26
}
68

            
69
26
pub fn testnet_genesis(
70
26
	root_key: AccountId,
71
26
	treasury_council_members: Vec<AccountId>,
72
26
	open_tech_committee_members: Vec<AccountId>,
73
26
	candidates: Vec<(AccountId, NimbusId, Balance)>,
74
26
	delegations: Vec<(AccountId, AccountId, Balance, Percent)>,
75
26
	endowed_accounts: Vec<AccountId>,
76
26
	crowdloan_fund_pot: Balance,
77
26
	para_id: ParaId,
78
26
	chain_id: u64,
79
26
) -> serde_json::Value {
80
26
	// This is the simplest bytecode to revert without returning any data.
81
26
	// We will pre-deploy it under all of our precompiles to ensure they can be called from
82
26
	// within contracts.
83
26
	// (PUSH1 0x00 PUSH1 0x00 REVERT)
84
26
	let revert_bytecode = vec![0x60, 0x00, 0x60, 0x00, 0xFD];
85
26

            
86
26
	let config = RuntimeGenesisConfig {
87
26
		system: Default::default(),
88
26
		balances: BalancesConfig {
89
26
			balances: endowed_accounts
90
26
				.iter()
91
26
				.cloned()
92
46
				.map(|k| (k, 1 << 80))
93
26
				.collect(),
94
26
		},
95
26
		crowdloan_rewards: CrowdloanRewardsConfig {
96
26
			funded_amount: crowdloan_fund_pot,
97
26
		},
98
26
		sudo: SudoConfig {
99
26
			key: Some(root_key),
100
26
		},
101
26
		parachain_info: ParachainInfoConfig {
102
26
			parachain_id: para_id,
103
26
			..Default::default()
104
26
		},
105
26
		ethereum_chain_id: EthereumChainIdConfig {
106
26
			chain_id,
107
26
			..Default::default()
108
26
		},
109
26
		evm: EVMConfig {
110
26
			// We need _some_ code inserted at the precompile address so that
111
26
			// the evm will actually call the address.
112
26
			accounts: Precompiles::used_addresses()
113
1482
				.map(|addr| {
114
1482
					(
115
1482
						addr.into(),
116
1482
						GenesisAccount {
117
1482
							nonce: Default::default(),
118
1482
							balance: Default::default(),
119
1482
							storage: Default::default(),
120
1482
							code: revert_bytecode.clone(),
121
1482
						},
122
1482
					)
123
1482
				})
124
26
				.collect(),
125
26
			..Default::default()
126
26
		},
127
26
		ethereum: EthereumConfig {
128
26
			..Default::default()
129
26
		},
130
26
		parachain_staking: ParachainStakingConfig {
131
26
			candidates: candidates
132
26
				.iter()
133
26
				.cloned()
134
26
				.map(|(account, _, bond)| (account, bond))
135
26
				.collect(),
136
26
			delegations,
137
26
			inflation_config: moonbase_inflation_config(),
138
26
			collator_commission: COLLATOR_COMMISSION,
139
26
			parachain_bond_reserve_percent: PARACHAIN_BOND_RESERVE_PERCENT,
140
26
			blocks_per_round: BLOCKS_PER_ROUND,
141
26
			num_selected_candidates: NUM_SELECTED_CANDIDATES,
142
26
		},
143
26
		treasury_council_collective: TreasuryCouncilCollectiveConfig {
144
26
			phantom: Default::default(),
145
26
			members: treasury_council_members,
146
26
		},
147
26
		open_tech_committee_collective: OpenTechCommitteeCollectiveConfig {
148
26
			phantom: Default::default(),
149
26
			members: open_tech_committee_members,
150
26
		},
151
26
		author_filter: AuthorFilterConfig {
152
26
			eligible_count: EligibilityValue::new_unchecked(50),
153
26
			..Default::default()
154
26
		},
155
26
		author_mapping: AuthorMappingConfig {
156
26
			mappings: candidates
157
26
				.iter()
158
26
				.cloned()
159
26
				.map(|(account_id, author_id, _)| (author_id, account_id))
160
26
				.collect(),
161
26
		},
162
26
		proxy_genesis_companion: Default::default(),
163
26
		treasury: Default::default(),
164
26
		migrations: Default::default(),
165
26
		maintenance_mode: MaintenanceModeConfig {
166
26
			start_in_maintenance_mode: false,
167
26
			..Default::default()
168
26
		},
169
26
		// This should initialize it to whatever we have set in the pallet
170
26
		polkadot_xcm: PolkadotXcmConfig::default(),
171
26
		transaction_payment: TransactionPaymentConfig {
172
26
			multiplier: Multiplier::from(8u128),
173
26
			..Default::default()
174
26
		},
175
26
		moonbeam_orbiters: MoonbeamOrbitersConfig {
176
26
			min_orbiter_deposit: One::one(),
177
26
		},
178
26
		xcm_transactor: XcmTransactorConfig {
179
26
			relay_indices: moonbeam_relay_encoder::westend::WESTEND_RELAY_INDICES,
180
26
			..Default::default()
181
26
		},
182
26
	};
183
26

            
184
26
	serde_json::to_value(&config).expect("Could not build genesis config.")
185
26
}
186

            
187
pub fn development() -> serde_json::Value {
188
	testnet_genesis(
189
		// Alith is Sudo
190
		AccountId::from(sp_core::hex2array!(
191
			"f24FF3a9CF04c71Dbc94D0b566f7A27B94566cac"
192
		)),
193
		// Treasury Council members: Baltathar, Charleth and Dorothy
194
		vec![
195
			AccountId::from(sp_core::hex2array!(
196
				"3Cd0A705a2DC65e5b1E1205896BaA2be8A07c6e0"
197
			)),
198
			AccountId::from(sp_core::hex2array!(
199
				"798d4Ba9baf0064Ec19eB4F0a1a45785ae9D6DFc"
200
			)),
201
			AccountId::from(sp_core::hex2array!(
202
				"773539d4Ac0e786233D90A233654ccEE26a613D9"
203
			)),
204
		],
205
		// Open Tech committee members: Alith and Baltathar
206
		vec![
207
			AccountId::from(sp_core::hex2array!(
208
				"f24FF3a9CF04c71Dbc94D0b566f7A27B94566cac"
209
			)),
210
			AccountId::from(sp_core::hex2array!(
211
				"3Cd0A705a2DC65e5b1E1205896BaA2be8A07c6e0"
212
			)),
213
		],
214
		// Collator Candidates
215
		vec![(
216
			// Alice -> Alith
217
			AccountId::from(sp_core::hex2array!(
218
				"f24FF3a9CF04c71Dbc94D0b566f7A27B94566cac"
219
			)),
220
			get_from_seed::<NimbusId>("Alice"),
221
			1_000 * UNIT,
222
		)],
223
		// Delegations
224
		vec![],
225
		// Endowed: Alith, Baltathar, Charleth and Dorothy
226
		vec![
227
			AccountId::from(sp_core::hex2array!(
228
				"f24FF3a9CF04c71Dbc94D0b566f7A27B94566cac"
229
			)),
230
			AccountId::from(sp_core::hex2array!(
231
				"3Cd0A705a2DC65e5b1E1205896BaA2be8A07c6e0"
232
			)),
233
			AccountId::from(sp_core::hex2array!(
234
				"798d4Ba9baf0064Ec19eB4F0a1a45785ae9D6DFc"
235
			)),
236
			AccountId::from(sp_core::hex2array!(
237
				"773539d4Ac0e786233D90A233654ccEE26a613D9"
238
			)),
239
		],
240
		3_000_000 * UNIT,
241
		Default::default(), // para_id
242
		1280,               //ChainId
243
	)
244
}
245

            
246
/// Provides the JSON representation of predefined genesis config for given `id`.
247
pub fn get_preset(id: &PresetId) -> Option<Vec<u8>> {
248
	let patch = match id.try_into() {
249
		Ok(sp_genesis_builder::DEV_RUNTIME_PRESET) => development(),
250
		_ => return None,
251
	};
252
	Some(
253
		serde_json::to_string(&patch)
254
			.expect("serialization to json is expected to work. qed.")
255
			.into_bytes(),
256
	)
257
}
258

            
259
/// List of supported presets.
260
pub fn preset_names() -> Vec<PresetId> {
261
	vec![PresetId::from(sp_genesis_builder::DEV_RUNTIME_PRESET)]
262
}