difftreelog
Merge pull request #268 from UniqueNetwork/hotfix/inflation_year_fix
in: master
Hotfix/inflation year fix
3 files changed
node/cli/src/chain_spec.rsdiffbeforeafterboth1//2// This file is subject to the terms and conditions defined in3// file 'LICENSE', which is part of this source code package.4//56use cumulus_primitives_core::ParaId;7use unique_runtime::*;8use sc_chain_spec::{ChainSpecExtension, ChainSpecGroup};9use sc_service::ChainType;10use sp_core::{sr25519, Pair, Public};11use sp_runtime::traits::{IdentifyAccount, Verify};12use std::collections::BTreeMap;1314use serde::{Deserialize, Serialize};15use serde_json::map::Map;1617/// Specialized `ChainSpec`. This is a specialization of the general Substrate ChainSpec type.18pub type ChainSpec = sc_service::GenericChainSpec<unique_runtime::GenesisConfig, Extensions>;1920/// Helper function to generate a crypto pair from seed21pub fn get_from_seed<TPublic: Public>(seed: &str) -> <TPublic::Pair as Pair>::Public {22 TPublic::Pair::from_string(&format!("//{}", seed), None)23 .expect("static values are valid; qed")24 .public()25}2627/// The extensions for the [`ChainSpec`].28#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, ChainSpecGroup, ChainSpecExtension)]29#[serde(deny_unknown_fields)]30pub struct Extensions {31 /// The relay chain of the Parachain.32 pub relay_chain: String,33 /// The id of the Parachain.34 pub para_id: u32,35}3637impl Extensions {38 /// Try to get the extension from the given `ChainSpec`.39 pub fn try_get(chain_spec: &dyn sc_service::ChainSpec) -> Option<&Self> {40 sc_chain_spec::get_extension(chain_spec.extensions())41 }42}4344type AccountPublic = <Signature as Verify>::Signer;4546/// Helper function to generate an account ID from seed47pub fn get_account_id_from_seed<TPublic: Public>(seed: &str) -> AccountId48where49 AccountPublic: From<<TPublic::Pair as Pair>::Public>,50{51 AccountPublic::from(get_from_seed::<TPublic>(seed)).into_account()52}5354pub fn development_config() -> ChainSpec {55 let mut properties = Map::new();56 properties.insert("tokenSymbol".into(), "OPL".into());57 properties.insert("tokenDecimals".into(), 15.into());58 properties.insert("ss58Format".into(), 42.into());5960 ChainSpec::from_genesis(61 // Name62 "Development",63 // ID64 "dev",65 ChainType::Local,66 move || {67 testnet_genesis(68 // Sudo account69 get_account_id_from_seed::<sr25519::Public>("Alice"),70 vec![71 get_from_seed::<AuraId>("Alice"),72 get_from_seed::<AuraId>("Bob"),73 ],74 // Pre-funded accounts75 vec![76 get_account_id_from_seed::<sr25519::Public>("Alice"),77 get_account_id_from_seed::<sr25519::Public>("Bob"),78 ],79 1000.into(),80 )81 },82 // Bootnodes83 vec![],84 // Telemetry85 None,86 // Protocol ID87 None,88 // Properties89 Some(properties),90 // Extensions91 Extensions {92 relay_chain: "rococo-dev".into(),93 para_id: 1000,94 },95 )96}9798pub fn local_testnet_rococo_config() -> ChainSpec {99 ChainSpec::from_genesis(100 // Name101 "Local Testnet",102 // ID103 "local_testnet",104 ChainType::Local,105 move || {106 testnet_genesis(107 // Sudo account108 get_account_id_from_seed::<sr25519::Public>("Alice"),109 vec![110 get_from_seed::<AuraId>("Alice"),111 get_from_seed::<AuraId>("Bob"),112 ],113 // Pre-funded accounts114 vec![115 get_account_id_from_seed::<sr25519::Public>("Alice"),116 get_account_id_from_seed::<sr25519::Public>("Bob"),117 get_account_id_from_seed::<sr25519::Public>("Charlie"),118 get_account_id_from_seed::<sr25519::Public>("Dave"),119 get_account_id_from_seed::<sr25519::Public>("Eve"),120 get_account_id_from_seed::<sr25519::Public>("Ferdie"),121 get_account_id_from_seed::<sr25519::Public>("Alice//stash"),122 get_account_id_from_seed::<sr25519::Public>("Bob//stash"),123 get_account_id_from_seed::<sr25519::Public>("Charlie//stash"),124 get_account_id_from_seed::<sr25519::Public>("Dave//stash"),125 get_account_id_from_seed::<sr25519::Public>("Eve//stash"),126 get_account_id_from_seed::<sr25519::Public>("Ferdie//stash"),127 ],128 1000.into(),129 )130 },131 // Bootnodes132 vec![],133 // Telemetry134 None,135 // Protocol ID136 None,137 // Properties138 None,139 // Extensions140 Extensions {141 relay_chain: "rococo-local".into(),142 para_id: 1000,143 },144 )145}146147pub fn local_testnet_westend_config() -> ChainSpec {148 ChainSpec::from_genesis(149 // Name150 "Local Testnet",151 // ID152 "local_testnet",153 ChainType::Local,154 move || {155 testnet_genesis(156 // Sudo account157 get_account_id_from_seed::<sr25519::Public>("Alice"),158 vec![159 get_from_seed::<AuraId>("Alice"),160 get_from_seed::<AuraId>("Bob"),161 get_from_seed::<AuraId>("Charlie"),162 get_from_seed::<AuraId>("Dave"),163 get_from_seed::<AuraId>("Eve"),164 ],165 // Pre-funded accounts166 vec![167 get_account_id_from_seed::<sr25519::Public>("Alice"),168 get_account_id_from_seed::<sr25519::Public>("Bob"),169 get_account_id_from_seed::<sr25519::Public>("Charlie"),170 get_account_id_from_seed::<sr25519::Public>("Dave"),171 get_account_id_from_seed::<sr25519::Public>("Eve"),172 get_account_id_from_seed::<sr25519::Public>("Ferdie"),173 get_account_id_from_seed::<sr25519::Public>("Alice//stash"),174 get_account_id_from_seed::<sr25519::Public>("Bob//stash"),175 get_account_id_from_seed::<sr25519::Public>("Charlie//stash"),176 get_account_id_from_seed::<sr25519::Public>("Dave//stash"),177 get_account_id_from_seed::<sr25519::Public>("Eve//stash"),178 get_account_id_from_seed::<sr25519::Public>("Ferdie//stash"),179 ],180 1000.into(),181 )182 },183 // Bootnodes184 vec![],185 // Telemetry186 None,187 // Protocol ID188 None,189 // Properties190 None,191 // Extensions192 Extensions {193 relay_chain: "westend-local".into(),194 para_id: 1000,195 },196 )197}198199fn testnet_genesis(200 root_key: AccountId,201 initial_authorities: Vec<AuraId>,202 endowed_accounts: Vec<AccountId>,203 id: ParaId,204) -> GenesisConfig {205 GenesisConfig {206 system: unique_runtime::SystemConfig {207 code: unique_runtime::WASM_BINARY208 .expect("WASM binary was not build, please build it!")209 .to_vec(),210 },211 balances: BalancesConfig {212 balances: endowed_accounts213 .iter()214 .cloned()215 // 1e13 UNQ216 .map(|k| (k, 1 << 100))217 .collect(),218 },219 treasury: Default::default(),220 sudo: SudoConfig { key: root_key },221 vesting: VestingConfig { vesting: vec![] },222 parachain_info: unique_runtime::ParachainInfoConfig { parachain_id: id },223 aura: unique_runtime::AuraConfig {224 authorities: initial_authorities,225 },226 aura_ext: Default::default(),227 evm: EVMConfig {228 accounts: BTreeMap::new(),229 },230 ethereum: EthereumConfig {},231 }232}pallets/inflation/src/lib.rsdiffbeforeafterboth--- a/pallets/inflation/src/lib.rs
+++ b/pallets/inflation/src/lib.rs
@@ -75,6 +75,10 @@
pub type NextRecalculationBlock<T: Config> =
StorageValue<Value = T::BlockNumber, QueryKind = ValueQuery>;
+ /// Relay block when inflation has started
+ #[pallet::storage]
+ pub type StartBlock<T: Config> = StorageValue<Value = T::BlockNumber, QueryKind = ValueQuery>;
+
#[pallet::hooks]
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
fn on_initialize(_: T::BlockNumber) -> Weight
@@ -145,8 +149,10 @@
ensure_root(origin)?;
// Start inflation if it has not been yet initialized
- let next_inflation: T::BlockNumber = <NextInflationBlock<T>>::get();
- if next_inflation == 0u32.into() {
+ if <StartBlock<T>>::get() == 0u32.into() {
+ // Set inflation global start block
+ <StartBlock<T>>::set(inflation_start_relay_block);
+
// Recalculate inflation. This can be backdated and will catch up.
Self::recalculate_inflation(inflation_start_relay_block);
let block_interval: u32 = T::InflationBlockInterval::get().try_into().unwrap_or(0);
@@ -166,9 +172,10 @@
impl<T: Config> Pallet<T> {
pub fn recalculate_inflation(recalculation_block: T::BlockNumber) {
- let current_year: u32 = (recalculation_block / T::BlockNumber::from(YEAR))
- .try_into()
- .unwrap_or(0);
+ let current_year: u32 = ((recalculation_block - <StartBlock<T>>::get())
+ / T::BlockNumber::from(YEAR))
+ .try_into()
+ .unwrap_or(0);
let block_interval: u32 = T::InflationBlockInterval::get().try_into().unwrap_or(0);
let one_percent = Perbill::from_percent(1);
pallets/inflation/src/tests.rsdiffbeforeafterboth--- a/pallets/inflation/src/tests.rs
+++ b/pallets/inflation/src/tests.rs
@@ -231,6 +231,45 @@
}
#[test]
+fn inflation_start_large_kusama_block() {
+ new_test_ext().execute_with(|| {
+ // Total issuance = 1_000_000_000
+ let initial_issuance: u64 = 1_000_000_000;
+ let start_block: u64 = 10457457;
+ let _ = <Balances as Currency<_>>::deposit_creating(&1234, initial_issuance);
+ assert_eq!(Balances::free_balance(1234), initial_issuance);
+ MockBlockNumberProvider::set(start_block);
+
+ // Start inflation as sudo
+ assert_ok!(Inflation::start_inflation(
+ RawOrigin::Root.into(),
+ start_block
+ ));
+
+ // Go through all the block inflations for year 1,
+ // total issuance will be updated accordingly
+ // Inflation is set to start in block 1, so first iteration is block 101
+ for block in (101..YEAR).step_by(100) {
+ MockBlockNumberProvider::set(start_block + block);
+ Inflation::on_initialize(0);
+ }
+ assert_eq!(
+ initial_issuance + (FIRST_YEAR_BLOCK_INFLATION * (YEAR / 100)),
+ <Balances as Currency<_>>::total_issuance()
+ );
+
+ MockBlockNumberProvider::set(start_block + YEAR + 1);
+ Inflation::on_initialize(0);
+ let block_inflation_year_2 = block_inflation!();
+ // Expected 100-block inflation for year 2: 100 * 9.33% * initial issuance * 110% / YEAR == 1951
+ let expecter_year_2_inflation: u64 = (initial_issuance
+ + FIRST_YEAR_BLOCK_INFLATION * YEAR / 100)
+ * 933 * 100 / (10000 * YEAR);
+ assert_eq!(block_inflation_year_2 / 10, expecter_year_2_inflation / 10); // divide by 10 for approx. equality
+ });
+}
+
+#[test]
fn inflation_after_year_10_is_flat() {
new_test_ext().execute_with(|| {
// Total issuance = 1_000_000_000