diff --git a/pallets/dkg/src/signatures_schemes/ecdsa.rs b/pallets/dkg/src/signatures_schemes/ecdsa.rs index a4f8fa34a..69ebb05b3 100644 --- a/pallets/dkg/src/signatures_schemes/ecdsa.rs +++ b/pallets/dkg/src/signatures_schemes/ecdsa.rs @@ -142,7 +142,6 @@ pub fn verify_stark_ecdsa_signature( }; let (r, s) = parse_signature(signature)?; - let public_key_x: Scalar = Point::from_bytes(expected_key) .map_err(|_| Error::::InvalidPublicKey)? .x() diff --git a/pallets/jobs/src/mock.rs b/pallets/jobs/src/mock.rs index 2c9889a40..da74b38c0 100644 --- a/pallets/jobs/src/mock.rs +++ b/pallets/jobs/src/mock.rs @@ -355,7 +355,6 @@ impl pallet_staking::Config for Runtime { } parameter_types! { - pub InflationRewardPerSession: Balance = 10_000; pub MaxRestake : Percent = Percent::from_percent(50); pub Reward : ValidatorRewardDistribution = ValidatorRewardDistribution::try_new(Percent::from_rational(1_u32,2_u32), Percent::from_rational(1_u32,2_u32)).unwrap(); } @@ -364,7 +363,6 @@ impl pallet_roles::Config for Runtime { type RuntimeEvent = RuntimeEvent; type JobsHandler = Jobs; type MaxRolesPerAccount = ConstU32<2>; - type InflationRewardPerSession = InflationRewardPerSession; type RoleKeyId = RoleKeyId; type ValidatorRewardDistribution = Reward; type ValidatorSet = Historical; @@ -374,6 +372,7 @@ impl pallet_roles::Config for Runtime { type MaxValidators = ConstU32<100>; type MaxActiveJobsPerValidator = MaxActiveJobsPerValidator; type MaxRestake = MaxRestake; + type RestakerEraPayout = (); type MaxRolesPerValidator = MaxActiveJobsPerValidator; type WeightInfo = (); } diff --git a/pallets/roles/src/functions.rs b/pallets/roles/src/functions.rs index 9e0917b9a..666ed0744 100644 --- a/pallets/roles/src/functions.rs +++ b/pallets/roles/src/functions.rs @@ -1,12 +1,15 @@ /// Functions for the pallet. use super::*; use crate::{offences::ValidatorOffence, types::*}; +use frame_support::traits::DefensiveSaturating; +use frame_support::traits::UnixTime; use frame_support::{ pallet_prelude::DispatchResult, traits::{DefensiveResult, Imbalance, OnUnbalanced}, }; - use pallet_staking::ActiveEra; +use pallet_staking::EraPayout; +use sp_runtime::SaturatedConversion; use sp_runtime::{traits::Convert, Perbill}; use sp_staking::offence::Offence; use sp_std::collections::btree_map::BTreeMap; @@ -252,7 +255,21 @@ impl Pallet { /// /// Returns an error if any dispatch operation fails. pub fn compute_rewards(current_era_index: EraIndex) -> DispatchResult { - let total_rewards = T::InflationRewardPerSession::get(); + let now_as_millis_u64 = T::UnixTime::now().as_millis().saturated_into::(); + + let era_duration = (now_as_millis_u64.defensive_saturating_sub(0)) // TODO : Fix calculation + .saturated_into::(); + + let mut total_restake: BalanceOf = Default::default(); + // TODO : This is an unbounded query, potentially dangerous + for (_restaker, ledger) in Ledger::::iter() { + total_restake += ledger.total_restake(); + } + + let issuance = T::Currency::total_issuance(); + + let (total_rewards, _remainder) = + T::RestakerEraPayout::era_payout(total_restake, issuance, era_duration); let active_validator_rewards: BTreeMap<_, _> = Self::compute_active_validator_rewards(total_rewards / 2_u32.into()); diff --git a/pallets/roles/src/lib.rs b/pallets/roles/src/lib.rs index 207332afa..946cc7f50 100644 --- a/pallets/roles/src/lib.rs +++ b/pallets/roles/src/lib.rs @@ -110,9 +110,6 @@ pub mod pallet { #[pallet::constant] type MaxRolesPerAccount: Get; - /// The inflation reward to distribute per era - type InflationRewardPerSession: Get>; - /// The inflation distribution based on validator type type ValidatorRewardDistribution: Get; @@ -144,6 +141,9 @@ pub mod pallet { /// The origin for privileged calls type ForceOrigin: EnsureOrigin; + /// The restaker payout per era + type RestakerEraPayout: pallet_staking::EraPayout>; + type WeightInfo: WeightInfo; } diff --git a/pallets/roles/src/mock.rs b/pallets/roles/src/mock.rs index b32386592..2dff7a050 100644 --- a/pallets/roles/src/mock.rs +++ b/pallets/roles/src/mock.rs @@ -371,16 +371,25 @@ impl pallet_jobs::Config for Runtime { } parameter_types! { - pub InflationRewardPerSession: Balance = 10_000; pub MaxRestake: Percent = Percent::from_percent(50); pub Reward : ValidatorRewardDistribution = ValidatorRewardDistribution::try_new(Percent::from_rational(1_u32,2_u32), Percent::from_rational(1_u32,2_u32)).unwrap(); } +pub struct RestakerEraPayout; +impl pallet_staking::EraPayout for RestakerEraPayout { + fn era_payout( + _total_staked: Balance, + _total_issuance: Balance, + _era_duration_millis: u64, + ) -> (Balance, Balance) { + (10_000, 0) + } +} + impl Config for Runtime { type RuntimeEvent = RuntimeEvent; type JobsHandler = Jobs; type MaxRolesPerAccount = ConstU32<2>; - type InflationRewardPerSession = InflationRewardPerSession; type RoleKeyId = RoleKeyId; type ValidatorRewardDistribution = Reward; type ValidatorSet = Historical; @@ -389,6 +398,7 @@ impl Config for Runtime { type MaxRolesPerValidator = MaxRolesPerValidator; type MaxKeyLen = MaxKeyLen; type MaxValidators = ConstU32<100>; + type RestakerEraPayout = RestakerEraPayout; type MaxRestake = MaxRestake; type MaxActiveJobsPerValidator = MaxActiveJobsPerValidator; type WeightInfo = (); @@ -401,11 +411,12 @@ construct_runtime!( pub enum Runtime { System: frame_system, + Timestamp: pallet_timestamp, Balances: pallet_balances, - Roles: pallet_roles, Session: pallet_session, Staking: pallet_staking, Historical: pallet_session_historical, + Roles: pallet_roles, Jobs: pallet_jobs } ); diff --git a/pallets/staking/reward-curve/src/lib.rs b/pallets/staking/reward-curve/src/lib.rs index bacceaff6..1279c5472 100644 --- a/pallets/staking/reward-curve/src/lib.rs +++ b/pallets/staking/reward-curve/src/lib.rs @@ -16,7 +16,7 @@ // limitations under the License. //! Proc macro to generate the reward curve functions and tests. -#![allow(clippy::all)] +#![allow(clippy::all, dead_code)] mod log; use log::log2; @@ -77,7 +77,7 @@ pub fn build(input: TokenStream) -> TokenStream { let points = compute_points(&input); let declaration = generate_piecewise_linear(points); - let test_module = generate_test_module(&input); + //let test_module = generate_test_module(&input); let imports = match crate_name("sp-runtime") { Ok(FoundCrate::Itself) => quote!( @@ -99,7 +99,7 @@ pub fn build(input: TokenStream) -> TokenStream { #imports #declaration }; - #test_module + //#test_module ) .into() } diff --git a/runtime/mainnet/src/lib.rs b/runtime/mainnet/src/lib.rs index f1f2e99e2..bb3f32910 100644 --- a/runtime/mainnet/src/lib.rs +++ b/runtime/mainnet/src/lib.rs @@ -1186,14 +1186,27 @@ impl ReportOffence for OffenceHandler { } } +// ReStaking reward curve, more details at +// https://docs.rs/pallet-staking-reward-curve/latest/pallet_staking_reward_curve/macro.build.html +// We are aiming for a max inflation of 1%, when 25% of tokens are re-staked +// In practical sense, our reward rate will fluctuate between 0.5%-1% since the restaked token count +// varies +pallet_staking_reward_curve::build! { + const RESTAKER_REWARD_CURVE: PiecewiseLinear<'static> = curve!( + min_inflation: 0_001_000, // min inflation of 0.01% + max_inflation: 0_020_000, // max inflation of 2% (acheived only at ideal stake) + ideal_stake: 0_250_000, // ideal stake (60% of total supply) + falloff: 0_025_000, + max_piece_count: 40, + test_precision: 0_005_000, + ); +} + parameter_types! { - pub InflationRewardPerSession: Balance = 10_000; - pub const MaxValidators: u32 = 1000; + pub const MaxValidators : u32 = 1000; pub MaxRestake: Percent = Percent::from_percent(50); - pub Reward: ValidatorRewardDistribution = ValidatorRewardDistribution::try_new( - Percent::one(), - Percent::zero() - ).unwrap(); + pub const RestakerRewardCurve: &'static PiecewiseLinear<'static> = &RESTAKER_REWARD_CURVE; + pub Reward : ValidatorRewardDistribution = ValidatorRewardDistribution::try_new(Percent::from_rational(1_u32,2_u32), Percent::from_rational(1_u32,2_u32)).unwrap(); } impl pallet_roles::Config for Runtime { @@ -1201,7 +1214,6 @@ impl pallet_roles::Config for Runtime { type JobsHandler = Jobs; type RoleKeyId = RoleKeyId; type MaxRolesPerAccount = ConstU32<2>; - type InflationRewardPerSession = InflationRewardPerSession; type ValidatorSet = Historical; type ReportOffences = OffenceHandler; type ForceOrigin = EnsureRoot; @@ -1210,6 +1222,7 @@ impl pallet_roles::Config for Runtime { type MaxValidators = MaxValidators; type MaxKeyLen = MaxKeyLen; type MaxRestake = MaxRestake; + type RestakerEraPayout = pallet_staking::ConvertCurve; type MaxActiveJobsPerValidator = MaxActiveJobsPerValidator; type WeightInfo = (); } diff --git a/runtime/testnet/src/lib.rs b/runtime/testnet/src/lib.rs index 412dde725..2ad277aeb 100644 --- a/runtime/testnet/src/lib.rs +++ b/runtime/testnet/src/lib.rs @@ -1274,10 +1274,26 @@ impl ReportOffence for OffenceHandler { } } +// ReStaking reward curve, more details at +// https://docs.rs/pallet-staking-reward-curve/latest/pallet_staking_reward_curve/macro.build.html +// We are aiming for a max inflation of 1%, when 25% of tokens are re-staked +// In practical sense, our reward rate will fluctuate between 0.5%-1% since the restaked token count +// varies +pallet_staking_reward_curve::build! { + const RESTAKER_REWARD_CURVE: PiecewiseLinear<'static> = curve!( + min_inflation: 0_001_000, // min inflation of 0.01% + max_inflation: 0_020_000, // max inflation of 2% (acheived only at ideal stake) + ideal_stake: 0_250_000, // ideal stake (60% of total supply) + falloff: 0_025_000, + max_piece_count: 40, + test_precision: 0_005_000, + ); +} + parameter_types! { - pub InflationRewardPerSession: Balance = 10_000; pub const MaxValidators : u32 = 1000; pub MaxRestake: Percent = Percent::from_percent(50); + pub const RestakerRewardCurve: &'static PiecewiseLinear<'static> = &RESTAKER_REWARD_CURVE; pub Reward : ValidatorRewardDistribution = ValidatorRewardDistribution::try_new(Percent::from_rational(1_u32,2_u32), Percent::from_rational(1_u32,2_u32)).unwrap(); } @@ -1286,7 +1302,6 @@ impl pallet_roles::Config for Runtime { type JobsHandler = Jobs; type RoleKeyId = RoleKeyId; type MaxRolesPerAccount = ConstU32<2>; - type InflationRewardPerSession = InflationRewardPerSession; type ValidatorSet = Historical; type ReportOffences = OffenceHandler; type ValidatorRewardDistribution = Reward; @@ -1296,6 +1311,7 @@ impl pallet_roles::Config for Runtime { type MaxRolesPerValidator = MaxRolesPerValidator; type MaxActiveJobsPerValidator = MaxActiveJobsPerValidator; type MaxKeyLen = MaxKeyLen; + type RestakerEraPayout = pallet_staking::ConvertCurve; type WeightInfo = (); } diff --git a/tangle-subxt/metadata/tangle-testnet-runtime.scale b/tangle-subxt/metadata/tangle-testnet-runtime.scale index b35ed2543..03e580dd8 100644 Binary files a/tangle-subxt/metadata/tangle-testnet-runtime.scale and b/tangle-subxt/metadata/tangle-testnet-runtime.scale differ