frontier_template_node/
chain_spec.rs

1use std::{collections::BTreeMap, str::FromStr};
2
3use hex_literal::hex;
4// Substrate
5use sc_chain_spec::{ChainType, Properties};
6use sp_consensus_aura::sr25519::AuthorityId as AuraId;
7use sp_consensus_grandpa::AuthorityId as GrandpaId;
8#[allow(unused_imports)]
9use sp_core::ecdsa;
10use sp_core::{Pair, Public, H160, U256};
11use sp_runtime::traits::{IdentifyAccount, Verify};
12// Frontier
13use frontier_template_runtime::{AccountId, Balance, SS58Prefix, Signature, WASM_BINARY};
14
15// The URL for the telemetry server.
16// const STAGING_TELEMETRY_URL: &str = "wss://telemetry.polkadot.io/submit/";
17
18/// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type.
19pub type ChainSpec = sc_service::GenericChainSpec;
20
21/// Generate a crypto pair from seed.
22pub fn get_from_seed<TPublic: Public>(seed: &str) -> <TPublic::Pair as Pair>::Public {
23	TPublic::Pair::from_string(&format!("//{seed}"), None)
24		.expect("static values are valid; qed")
25		.public()
26}
27
28#[allow(dead_code)]
29type AccountPublic = <Signature as Verify>::Signer;
30
31/// Generate an account ID from seed.
32/// For use with `AccountId32`, `dead_code` if `AccountId20`.
33#[allow(dead_code)]
34pub fn get_account_id_from_seed<TPublic: Public>(seed: &str) -> AccountId
35where
36	AccountPublic: From<<TPublic::Pair as Pair>::Public>,
37{
38	AccountPublic::from(get_from_seed::<TPublic>(seed)).into_account()
39}
40
41/// Generate an Aura authority key.
42pub fn authority_keys_from_seed(s: &str) -> (AuraId, GrandpaId) {
43	(get_from_seed::<AuraId>(s), get_from_seed::<GrandpaId>(s))
44}
45
46fn properties() -> Properties {
47	let mut properties = Properties::new();
48	properties.insert("tokenDecimals".into(), 18.into());
49	properties.insert("ss58Format".into(), SS58Prefix::get().into());
50	properties
51}
52
53const UNITS: Balance = 1_000_000_000_000_000_000;
54
55pub fn development_config(enable_manual_seal: bool) -> ChainSpec {
56	ChainSpec::builder(WASM_BINARY.expect("WASM not available"), Default::default())
57		.with_name("Development")
58		.with_id("dev")
59		.with_chain_type(ChainType::Development)
60		.with_properties(properties())
61		.with_genesis_config_patch(testnet_genesis(
62			// Sudo account (Alith)
63			AccountId::from(hex!("f24FF3a9CF04c71Dbc94D0b566f7A27B94566cac")),
64			// Pre-funded accounts
65			vec![
66				AccountId::from(hex!("f24FF3a9CF04c71Dbc94D0b566f7A27B94566cac")), // Alith
67				AccountId::from(hex!("3Cd0A705a2DC65e5b1E1205896BaA2be8A07c6e0")), // Baltathar
68				AccountId::from(hex!("798d4Ba9baf0064Ec19eB4F0a1a45785ae9D6DFc")), // Charleth
69				AccountId::from(hex!("773539d4Ac0e786233D90A233654ccEE26a613D9")), // Dorothy
70				AccountId::from(hex!("Ff64d3F6efE2317EE2807d223a0Bdc4c0c49dfDB")), // Ethan
71				AccountId::from(hex!("C0F0f4ab324C46e55D02D0033343B4Be8A55532d")), // Faith
72			],
73			// Initial PoA authorities
74			vec![authority_keys_from_seed("Alice")],
75			// Ethereum chain ID
76			SS58Prefix::get() as u64,
77			enable_manual_seal,
78		))
79		.build()
80}
81
82pub fn local_testnet_config() -> ChainSpec {
83	ChainSpec::builder(WASM_BINARY.expect("WASM not available"), Default::default())
84		.with_name("Local Testnet")
85		.with_id("local_testnet")
86		.with_chain_type(ChainType::Local)
87		.with_properties(properties())
88		.with_genesis_config_patch(testnet_genesis(
89			// Sudo account (Alith)
90			AccountId::from(hex!("f24FF3a9CF04c71Dbc94D0b566f7A27B94566cac")),
91			// Pre-funded accounts
92			vec![
93				AccountId::from(hex!("f24FF3a9CF04c71Dbc94D0b566f7A27B94566cac")), // Alith
94				AccountId::from(hex!("3Cd0A705a2DC65e5b1E1205896BaA2be8A07c6e0")), // Baltathar
95				AccountId::from(hex!("798d4Ba9baf0064Ec19eB4F0a1a45785ae9D6DFc")), // Charleth
96				AccountId::from(hex!("773539d4Ac0e786233D90A233654ccEE26a613D9")), // Dorothy
97				AccountId::from(hex!("Ff64d3F6efE2317EE2807d223a0Bdc4c0c49dfDB")), // Ethan
98				AccountId::from(hex!("C0F0f4ab324C46e55D02D0033343B4Be8A55532d")), // Faith
99			],
100			vec![
101				authority_keys_from_seed("Alice"),
102				authority_keys_from_seed("Bob"),
103			],
104			42,
105			false,
106		))
107		.build()
108}
109
110/// Configure initial storage state for FRAME modules.
111fn testnet_genesis(
112	sudo_key: AccountId,
113	endowed_accounts: Vec<AccountId>,
114	initial_authorities: Vec<(AuraId, GrandpaId)>,
115	chain_id: u64,
116	enable_manual_seal: bool,
117) -> serde_json::Value {
118	let evm_accounts = {
119		let mut map = BTreeMap::new();
120		map.insert(
121			// H160 address of Alice dev account
122			// Derived from SS58 (42 prefix) address
123			// SS58: 5GrwvaEF5zXb26Fz9rcQpDWS57CtERHpNehXCPcNoHGKutQY
124			// hex: 0xd43593c715fdd31c61141abd04a99fd6822c8558854ccde39a5684e7a56da27d
125			// Using the full hex key, truncating to the first 20 bytes (the first 40 hex chars)
126			H160::from_str("d43593c715fdd31c61141abd04a99fd6822c8558")
127				.expect("internal H160 is valid; qed"),
128			fp_evm::GenesisAccount {
129				balance: U256::from_str("0xffffffffffffffffffffffffffffffff")
130					.expect("internal U256 is valid; qed"),
131				code: Default::default(),
132				nonce: Default::default(),
133				storage: Default::default(),
134			},
135		);
136		map.insert(
137			// H160 address of CI test runner account
138			H160::from_str("6be02d1d3665660d22ff9624b7be0551ee1ac91b")
139				.expect("internal H160 is valid; qed"),
140			fp_evm::GenesisAccount {
141				balance: U256::from_str("0xffffffffffffffffffffffffffffffff")
142					.expect("internal U256 is valid; qed"),
143				code: Default::default(),
144				nonce: Default::default(),
145				storage: Default::default(),
146			},
147		);
148		map.insert(
149			// H160 address for benchmark usage
150			H160::from_str("1000000000000000000000000000000000000001")
151				.expect("internal H160 is valid; qed"),
152			fp_evm::GenesisAccount {
153				nonce: U256::from(1),
154				balance: U256::from(1_000_000_000_000_000_000_000_000u128),
155				storage: Default::default(),
156				code: vec![0x00],
157			},
158		);
159		map
160	};
161
162	serde_json::json!({
163		"sudo": { "key": Some(sudo_key) },
164		"balances": {
165			"balances": endowed_accounts
166				.iter()
167				.cloned()
168				.map(|k| (k, 1_000_000 * UNITS))
169				.collect::<Vec<_>>()
170		},
171		"aura": { "authorities": initial_authorities.iter().map(|x| (x.0.clone())).collect::<Vec<_>>() },
172		"grandpa": { "authorities": initial_authorities.iter().map(|x| (x.1.clone(), 1)).collect::<Vec<_>>() },
173		"evmChainId": { "chainId": chain_id },
174		"evm": { "accounts": evm_accounts },
175		"manualSeal": { "enable": enable_manual_seal }
176	})
177}