From 574fb6756b142da65869ff646145218f7be2499a Mon Sep 17 00:00:00 2001 From: Greg Zaitsev Date: Mon, 06 Dec 2021 18:24:41 +0000 Subject: [PATCH] Convert inflation to FRAMEv2 and update --- --- a/pallets/inflation/src/lib.rs +++ b/pallets/inflation/src/lib.rs @@ -5,45 +5,32 @@ #![recursion_limit = "1024"] #![cfg_attr(not(feature = "std"), no_std)] - -#[cfg(feature = "std")] -pub use std::*; - -pub use serde::{Serialize, Deserialize}; +#![allow( + clippy::too_many_arguments, + clippy::unnecessary_mut_passed, + clippy::unused_unit +)] -#[cfg(feature = "runtime-benchmarks")] mod benchmarking; - #[cfg(test)] +mod mock; +#[cfg(test)] mod tests; -pub use frame_support::{ - construct_runtime, decl_module, decl_storage, ensure, - traits::{ - Currency, ExistenceRequirement, Get, Imbalance, KeyOwnerProofSystem, OnUnbalanced, - Randomness, IsSubType, WithdrawReasons, - }, - weights::{ - constants::{BlockExecutionWeight, ExtrinsicBaseWeight, RocksDbWeight, WEIGHT_PER_SECOND}, - DispatchInfo, GetDispatchInfo, IdentityFee, Pays, PostDispatchInfo, Weight, - WeightToFeePolynomial, DispatchClass, - }, - StorageValue, transactional, +use frame_support::{ + dispatch::{DispatchResult}, + ensure, + traits::{Currency, Get}, }; - -// #[cfg(feature = "runtime-benchmarks")] -pub use frame_support::dispatch::DispatchResult; - +pub use pallet::*; use sp_runtime::{ Perbill, - traits::{BlockNumberProvider}, + traits::{BlockNumberProvider} }; -use sp_std::convert::TryInto; -use frame_system::{self as system}; +use std::convert::TryInto; -/// The balance type of this module. -pub type BalanceOf = +type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; pub const YEAR: u32 = 5_259_600; // 6-second block @@ -52,39 +39,55 @@ pub const START_INFLATION_PERCENT: u32 = 10; pub const END_INFLATION_PERCENT: u32 = 4; -pub trait Config: system::Config { - type Currency: Currency; - type TreasuryAccountId: Get; - type InflationBlockInterval: Get; +#[frame_support::pallet] +pub mod pallet { + use super::*; + use frame_support::pallet_prelude::*; + use frame_system::pallet_prelude::*; - // The block number provider - type BlockNumberProvider: BlockNumberProvider; -} + #[pallet::error] + pub enum Error { + /// Inflation has already been initialized + AlreadyInitialized, + } -decl_storage! { - trait Store for Module as Inflation { - /// starting year total issuance - pub StartingYearTotalIssuance get(fn starting_year_total_issuance): BalanceOf; + #[pallet::config] + pub trait Config: frame_system::Config { + type Currency: Currency; + type TreasuryAccountId: Get; + + // The block number provider + type BlockNumberProvider: BlockNumberProvider; - /// Current block inflation - pub BlockInflation get(fn block_inflation): BalanceOf; + /// Number of blocks that pass between treasury balance updates due to inflation + #[pallet::constant] + type InflationBlockInterval: Get; + } - /// Next (relay) block when inflation is applied. This value is approximate. - pub NextInflationBlock get(fn next_inflation_block): T::BlockNumber; + #[pallet::pallet] + #[pallet::generate_store(pub(super) trait Store)] + pub struct Pallet(_); - /// Next (relay) block when inflation is recalculated. This value is approximate. - pub NextRecalculationBlock get(fn next_recalculation_block): T::BlockNumber; - } -} + /// starting year total issuance + #[pallet::storage] + pub type StartingYearTotalIssuance = StorageValue, QueryKind = ValueQuery>; -decl_module! { - pub struct Module for enum Call - where - origin: T::Origin, - { - const InflationBlockInterval: T::BlockNumber = T::InflationBlockInterval::get(); + /// Current inflation for `InflationBlockInterval` number of blocks + #[pallet::storage] + pub type BlockInflation = StorageValue, QueryKind = ValueQuery>; - fn on_initialize() -> Weight + /// Next target (relay) block when inflation will be applied + #[pallet::storage] + pub type NextInflationBlock = StorageValue; + + /// Next target (relay) block when inflation is recalculated + #[pallet::storage] + pub type NextRecalculationBlock = StorageValue; + + #[pallet::hooks] + impl Hooks> for Pallet { + fn on_initialize(_: T::BlockNumber) -> Weight + where ::BlockNumber: From { let mut consumed_weight = 0; let mut add_weight = |reads, writes, weight| { @@ -93,55 +96,96 @@ }; let block_interval: u32 = T::InflationBlockInterval::get().try_into().unwrap_or(0); - let _now = T::BlockNumberProvider::current_block_number(); - let next_recalculation: T::BlockNumber = >::get(); + let current_relay_block = T::BlockNumberProvider::current_block_number(); let next_inflation: T::BlockNumber = >::get(); - add_weight(2, 0, 5_000_000); + add_weight(1, 0, 5_000_000); - // Recalculate inflation on the first block of the year (or if it is not initialized yet) - if _now >= next_recalculation { - let current_year: u32 = (next_recalculation / T::BlockNumber::from(YEAR)).try_into().unwrap_or(0); + // Apply inflation every InflationBlockInterval blocks + // If next_inflation == 0, this means inflation wasn't yet initialized + if (next_inflation != 0u32.into()) && (current_relay_block >= next_inflation) { - let one_percent = Perbill::from_percent(1); - - if current_year <= TOTAL_YEARS_UNTIL_FLAT { - let amount: BalanceOf = Perbill::from_rational( - block_interval * (START_INFLATION_PERCENT * TOTAL_YEARS_UNTIL_FLAT - current_year * (START_INFLATION_PERCENT - END_INFLATION_PERCENT)), - YEAR * TOTAL_YEARS_UNTIL_FLAT - ) * ( one_percent * T::Currency::total_issuance() ); - >::put(amount); - } - else { - let amount: BalanceOf = Perbill::from_rational( - block_interval * END_INFLATION_PERCENT, - YEAR - ) * (one_percent * T::Currency::total_issuance()); - >::put(amount); + // Recalculate inflation on the first block of the year (or if it is not initialized yet) + // Do the "current_relay_block >= next_recalculation" check in the "current_relay_block >= next_inflation" + // block because it saves InflationBlockInterval DB reads for NextRecalculationBlock. + let next_recalculation: T::BlockNumber = >::get(); + add_weight(1, 0, 0); + if current_relay_block >= next_recalculation { + Self::recalculate_inflation(next_recalculation); + add_weight(0, 4, 5_000_000); } - >::set(T::Currency::total_issuance()); - - // First time deposit - T::Currency::deposit_creating(&T::TreasuryAccountId::get(), >::get()); - - // Update recalculation and inflation blocks - >::set(next_recalculation + YEAR.into()); - >::set(next_recalculation + block_interval.into()); - add_weight(7, 8, 28_300_000); - } - - // Apply inflation every InflationBlockInterval blocks and in the 1st block to initialize Treasury account - else if _now >= next_inflation { T::Currency::deposit_into_existing(&T::TreasuryAccountId::get(), >::get()).ok(); // Update inflation block >::set(next_inflation + block_interval.into()); - add_weight(3, 3, 12_900_000); + add_weight(3, 3, 10_000_000); } consumed_weight } + } + #[pallet::call] + impl Pallet { + /// This method sets the inflation start date. Can be only called once. + /// Inflation start block can be backdated and will catch up. The method will create Treasury + /// account if it does not exist and perform the first inflation deposit. + /// + /// # Permissions + /// + /// * Root + /// + /// # Arguments + /// + /// * inflation_start_relay_block: The relay chain block at which inflation should start + #[pallet::weight(0)] + pub fn start_inflation(origin: OriginFor, inflation_start_relay_block: T::BlockNumber) -> DispatchResult + where ::BlockNumber: From { + ensure_root(origin)?; + + // Ensure inflation has not been yet initialized + let next_inflation: T::BlockNumber = >::get(); + ensure!(next_inflation == 0u32.into(), Error::::AlreadyInitialized); + + // 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); + >::set(inflation_start_relay_block + block_interval.into()); + + // First time deposit - create Treasury account so that we can call deposit_into_existing everywhere else + T::Currency::deposit_creating(&T::TreasuryAccountId::get(), >::get()); + + Ok(()) + } } } + +impl Pallet { + pub fn recalculate_inflation(recalculation_block: T::BlockNumber) { + + let current_year: u32 = (recalculation_block / 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); + + if current_year <= TOTAL_YEARS_UNTIL_FLAT { + let amount: BalanceOf = Perbill::from_rational( + block_interval * (START_INFLATION_PERCENT * TOTAL_YEARS_UNTIL_FLAT - current_year * (START_INFLATION_PERCENT - END_INFLATION_PERCENT)), + YEAR * TOTAL_YEARS_UNTIL_FLAT + ) * ( one_percent * T::Currency::total_issuance() ); + >::put(amount); + } + else { + let amount: BalanceOf = Perbill::from_rational( + block_interval * END_INFLATION_PERCENT, + YEAR + ) * (one_percent * T::Currency::total_issuance()); + >::put(amount); + } + >::set(T::Currency::total_issuance()); + + // Update recalculation and inflation blocks + >::set(recalculation_block + YEAR.into()); + } +} \ No newline at end of file --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -377,7 +377,7 @@ pallet-unique = { path = '../pallets/unique', default-features = false } up-rpc = { path = "../primitives/rpc", default-features = false } up-evm-mapping = { path = "../primitives/evm-mapping", default-features = false } -pallet-inflation = { path = '../pallets/inflation', default-features = false } +pallet-inflation = { path = '../pallets/inflation' } up-data-structs = { path = '../primitives/data-structs', default-features = false } pallet-common = { default-features = false, path = "../pallets/common" } pallet-fungible = { default-features = false, path = "../pallets/fungible" } --- a/tests/src/inflation.test.ts +++ b/tests/src/inflation.test.ts @@ -14,6 +14,9 @@ it('First year inflation is 10%', async () => { await usingApi(async (api) => { + // Start inflation on relay block 1 + await api.tx.inflation.start_inflation(1); + const blockInterval = (api.consts.inflation.inflationBlockInterval).toBigInt(); const totalIssuanceStart = (await api.query.inflation.startingYearTotalIssuance()).toBigInt(); const blockInflation = (await api.query.inflation.blockInflation()).toBigInt(); -- gitstuff