Skip to content

Commit

Permalink
Inflate defensively (#1195)
Browse files Browse the repository at this point in the history
* inflate defensively

* add tests

* Update zrml/court/src/tests.rs

Co-authored-by: Malte Kliemann <mail@maltekliemann.com>

* fix test

* fix test name

---------

Co-authored-by: Malte Kliemann <mail@maltekliemann.com>
  • Loading branch information
Chralt98 and maltekliemann authored Dec 12, 2023
1 parent 8790095 commit 6c2e9f7
Show file tree
Hide file tree
Showing 9 changed files with 70 additions and 16 deletions.
1 change: 1 addition & 0 deletions primitives/src/constants/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ parameter_types! {
pub const MaxDelegations: u32 = 5;
pub const MaxSelectedDraws: u32 = 510;
pub const MaxCourtParticipants: u32 = 1_000;
pub const MaxYearlyInflation: Perbill = Perbill::from_percent(10u32);
pub const MinJurorStake: Balance = 50 * CENT;
pub const InflationPeriod: BlockNumber = 20;
}
Expand Down
2 changes: 2 additions & 0 deletions runtime/battery-station/src/parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ parameter_types! {
pub const MaxSelectedDraws: u32 = 510;
/// The maximum number of jurors / delegators that can be registered.
pub const MaxCourtParticipants: u32 = 1_000;
/// The maximum yearly inflation for court incentivisation.
pub const MaxYearlyInflation: Perbill = Perbill::from_percent(10);
/// The minimum stake a user needs to reserve to become a juror.
pub const MinJurorStake: Balance = 500 * BASE;
/// The interval for requesting multiple court votes at once.
Expand Down
1 change: 1 addition & 0 deletions runtime/common/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1077,6 +1077,7 @@ macro_rules! impl_config_traits {
type MaxDelegations = MaxDelegations;
type MaxSelectedDraws = MaxSelectedDraws;
type MaxCourtParticipants = MaxCourtParticipants;
type MaxYearlyInflation = MaxYearlyInflation;
type MinJurorStake = MinJurorStake;
type MonetaryGovernanceOrigin = EnsureRoot<AccountId>;
type Random = RandomnessCollectiveFlip;
Expand Down
2 changes: 2 additions & 0 deletions runtime/zeitgeist/src/parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ parameter_types! {
pub const MaxSelectedDraws: u32 = 510;
/// The maximum number of jurors / delegators that can be registered.
pub const MaxCourtParticipants: u32 = 1_000;
/// The maximum yearly inflation for court incentivisation.
pub const MaxYearlyInflation: Perbill = Perbill::from_percent(10);
/// The minimum stake a user needs to reserve to become a juror.
pub const MinJurorStake: Balance = 500 * BASE;
/// The interval for requesting multiple court votes at once.
Expand Down
16 changes: 15 additions & 1 deletion zrml/court/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,10 @@ mod pallet {
#[pallet::constant]
type MaxCourtParticipants: Get<u32>;

/// The maximum yearly inflation rate.
#[pallet::constant]
type MaxYearlyInflation: Get<Perbill>;

/// The minimum stake a user needs to lock to become a juror.
#[pallet::constant]
type MinJurorStake: Get<BalanceOf<Self>>;
Expand Down Expand Up @@ -290,7 +294,7 @@ mod pallet {

#[pallet::type_value]
pub fn DefaultYearlyInflation<T: Config>() -> Perbill {
Perbill::from_perthousand(20u32)
Perbill::from_perthousand(0u32)
}

/// The current inflation rate.
Expand Down Expand Up @@ -465,6 +469,8 @@ mod pallet {
/// Action cannot be completed because an unexpected error has occurred. This should be
/// reported to protocol maintainers.
Unexpected(UnexpectedError),
/// The inflation rate is too high.
InflationExceedsMaxYearlyInflation,
}

// NOTE: these errors should never happen.
Expand Down Expand Up @@ -1161,6 +1167,11 @@ mod pallet {
pub fn set_inflation(origin: OriginFor<T>, inflation: Perbill) -> DispatchResult {
T::MonetaryGovernanceOrigin::ensure_origin(origin)?;

ensure!(
inflation <= T::MaxYearlyInflation::get(),
Error::<T>::InflationExceedsMaxYearlyInflation
);

<YearlyInflation<T>>::put(inflation);

Self::deposit_event(Event::InflationSet { inflation });
Expand Down Expand Up @@ -1293,6 +1304,9 @@ mod pallet {
}

let yearly_inflation_rate = <YearlyInflation<T>>::get();
if yearly_inflation_rate.is_zero() {
return T::WeightInfo::handle_inflation(0u32);
}
// example: 1049272791644671442
let total_supply = T::Currency::total_issuance();
// example: 0.02 * 1049272791644671442 = 20985455832893428
Expand Down
5 changes: 3 additions & 2 deletions zrml/court/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ use zeitgeist_primitives::{
constants::mock::{
AggregationPeriod, AppealBond, AppealPeriod, BlockHashCount, BlocksPerYear, CourtPalletId,
InflationPeriod, LockId, MaxAppeals, MaxApprovals, MaxCourtParticipants, MaxDelegations,
MaxReserves, MaxSelectedDraws, MinJurorStake, MinimumPeriod, PmPalletId, RequestInterval,
VotePeriod, BASE,
MaxReserves, MaxSelectedDraws, MaxYearlyInflation, MinJurorStake, MinimumPeriod,
PmPalletId, RequestInterval, VotePeriod, BASE,
},
traits::DisputeResolutionApi,
types::{
Expand Down Expand Up @@ -152,6 +152,7 @@ impl crate::Config for Runtime {
type MaxDelegations = MaxDelegations;
type MaxSelectedDraws = MaxSelectedDraws;
type MaxCourtParticipants = MaxCourtParticipants;
type MaxYearlyInflation = MaxYearlyInflation;
type MinJurorStake = MinJurorStake;
type MonetaryGovernanceOrigin = EnsureRoot<AccountIdTest>;
type PalletId = CourtPalletId;
Expand Down
37 changes: 34 additions & 3 deletions zrml/court/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,24 +29,26 @@ use crate::{
AppealInfo, BalanceOf, CourtId, CourtIdToMarketId, CourtParticipantInfo,
CourtParticipantInfoOf, CourtPool, CourtPoolItem, CourtPoolOf, Courts, Error, Event,
MarketIdToCourtId, MarketOf, NegativeImbalanceOf, Participants, RequestBlock, SelectedDraws,
YearlyInflation,
};
use alloc::collections::BTreeMap;
use frame_support::{
assert_noop, assert_ok,
assert_noop, assert_ok, storage_root,
traits::{fungible::Balanced, tokens::imbalance::Imbalance, Currency, NamedReservableCurrency},
StateVersion,
};
use pallet_balances::{BalanceLock, NegativeImbalance};
use rand::seq::SliceRandom;
use sp_runtime::{
traits::{BlakeTwo256, Hash, Zero},
Perquintill,
Perbill, Perquintill,
};
use test_case::test_case;
use zeitgeist_primitives::{
constants::{
mock::{
AggregationPeriod, AppealBond, AppealPeriod, InflationPeriod, LockId, MaxAppeals,
MaxCourtParticipants, MinJurorStake, RequestInterval, VotePeriod,
MaxCourtParticipants, MaxYearlyInflation, MinJurorStake, RequestInterval, VotePeriod,
},
BASE,
},
Expand Down Expand Up @@ -3053,9 +3055,24 @@ fn random_jurors_returns_a_subset_of_jurors() {
});
}

#[test]
fn set_inflation_fails_if_inflation_exceeds_max_yearly_inflation() {
ExtBuilder::default().build().execute_with(|| {
assert_noop!(
Court::set_inflation(
RuntimeOrigin::root(),
MaxYearlyInflation::get() + Perbill::from_percent(1)
),
Error::<Runtime>::InflationExceedsMaxYearlyInflation
);
});
}

#[test]
fn handle_inflation_works() {
ExtBuilder::default().build().execute_with(|| {
assert_ok!(Court::set_inflation(RuntimeOrigin::root(), Perbill::from_percent(2u32)));

let mut jurors = <CourtPool<Runtime>>::get();
let mut free_balances_before = BTreeMap::new();
let jurors_list = [1000, 10_000, 100_000, 1_000_000, 10_000_000];
Expand Down Expand Up @@ -3099,6 +3116,20 @@ fn handle_inflation_works() {
});
}

#[test]
fn handle_inflation_is_noop_if_yearly_inflation_is_zero() {
ExtBuilder::default().build().execute_with(|| {
YearlyInflation::<Runtime>::kill();

let inflation_period_block = InflationPeriod::get();
// save current storage root
let tmp = storage_root(StateVersion::V1);
// handle_inflation is a noop for the storage
Court::handle_inflation(inflation_period_block);
assert_eq!(tmp, storage_root(StateVersion::V1));
});
}

#[test]
fn handle_inflation_without_waiting_one_inflation_period() {
ExtBuilder::default().build().execute_with(|| {
Expand Down
11 changes: 6 additions & 5 deletions zrml/neo-swaps/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,11 +55,11 @@ use zeitgeist_primitives::{
MaxEditReasonLen, MaxGlobalDisputeVotes, MaxGracePeriod, MaxInRatio, MaxLocks,
MaxMarketLifetime, MaxOracleDuration, MaxOutRatio, MaxOwners, MaxRejectReasonLen,
MaxReserves, MaxSelectedDraws, MaxSubsidyPeriod, MaxSwapFee, MaxTotalWeight, MaxWeight,
MinAssets, MinCategories, MinDisputeDuration, MinJurorStake, MinOracleDuration,
MinOutcomeVoteAmount, MinSubsidy, MinSubsidyPeriod, MinWeight, MinimumPeriod,
NeoMaxSwapFee, NeoSwapsPalletId, OutcomeBond, OutcomeFactor, OutsiderBond, PmPalletId,
RemoveKeysLimit, RequestInterval, SimpleDisputesPalletId, SwapsPalletId, TreasuryPalletId,
VotePeriod, VotingOutcomeFee, BASE, CENT,
MaxYearlyInflation, MinAssets, MinCategories, MinDisputeDuration, MinJurorStake,
MinOracleDuration, MinOutcomeVoteAmount, MinSubsidy, MinSubsidyPeriod, MinWeight,
MinimumPeriod, NeoMaxSwapFee, NeoSwapsPalletId, OutcomeBond, OutcomeFactor, OutsiderBond,
PmPalletId, RemoveKeysLimit, RequestInterval, SimpleDisputesPalletId, SwapsPalletId,
TreasuryPalletId, VotePeriod, VotingOutcomeFee, BASE, CENT,
},
math::fixed::FixedMul,
traits::{DeployPoolApi, DistributeFees},
Expand Down Expand Up @@ -291,6 +291,7 @@ impl zrml_court::Config for Runtime {
type MaxDelegations = MaxDelegations;
type MaxSelectedDraws = MaxSelectedDraws;
type MaxCourtParticipants = MaxCourtParticipants;
type MaxYearlyInflation = MaxYearlyInflation;
type MinJurorStake = MinJurorStake;
type MonetaryGovernanceOrigin = EnsureRoot<AccountIdTest>;
type PalletId = CourtPalletId;
Expand Down
11 changes: 6 additions & 5 deletions zrml/prediction-markets/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,11 @@ use zeitgeist_primitives::{
MaxDisputes, MaxEditReasonLen, MaxGlobalDisputeVotes, MaxGracePeriod, MaxInRatio,
MaxMarketLifetime, MaxOracleDuration, MaxOutRatio, MaxOwners, MaxRejectReasonLen,
MaxReserves, MaxSelectedDraws, MaxSubsidyPeriod, MaxSwapFee, MaxTotalWeight, MaxWeight,
MinAssets, MinCategories, MinDisputeDuration, MinJurorStake, MinOracleDuration,
MinOutcomeVoteAmount, MinSubsidy, MinSubsidyPeriod, MinWeight, MinimumPeriod, OutcomeBond,
OutcomeFactor, OutsiderBond, PmPalletId, RemoveKeysLimit, RequestInterval,
SimpleDisputesPalletId, SwapsPalletId, TreasuryPalletId, VotePeriod, VotingOutcomeFee,
BASE, CENT, MILLISECS_PER_BLOCK,
MaxYearlyInflation, MinAssets, MinCategories, MinDisputeDuration, MinJurorStake,
MinOracleDuration, MinOutcomeVoteAmount, MinSubsidy, MinSubsidyPeriod, MinWeight,
MinimumPeriod, OutcomeBond, OutcomeFactor, OutsiderBond, PmPalletId, RemoveKeysLimit,
RequestInterval, SimpleDisputesPalletId, SwapsPalletId, TreasuryPalletId, VotePeriod,
VotingOutcomeFee, BASE, CENT, MILLISECS_PER_BLOCK,
},
traits::DeployPoolApi,
types::{
Expand Down Expand Up @@ -343,6 +343,7 @@ impl zrml_court::Config for Runtime {
type MaxDelegations = MaxDelegations;
type MaxSelectedDraws = MaxSelectedDraws;
type MaxCourtParticipants = MaxCourtParticipants;
type MaxYearlyInflation = MaxYearlyInflation;
type MinJurorStake = MinJurorStake;
type MonetaryGovernanceOrigin = EnsureRoot<AccountIdTest>;
type PalletId = CourtPalletId;
Expand Down

0 comments on commit 6c2e9f7

Please sign in to comment.