Skip to content

Commit

Permalink
Genesis config
Browse files Browse the repository at this point in the history
  • Loading branch information
Dinonard committed Oct 25, 2023
1 parent 0197c95 commit 4ea8556
Show file tree
Hide file tree
Showing 6 changed files with 187 additions and 21 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions bin/collator/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ shiden-runtime = { workspace = true, features = ["std"] }
# astar pallets dependencies
astar-primitives = { workspace = true }
pallet-block-reward = { workspace = true }
pallet-dapp-staking-v3 = { workspace = true }

# frame dependencies
frame-system = { workspace = true, features = ["std"] }
Expand Down
40 changes: 36 additions & 4 deletions bin/collator/src/local/chain_spec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,19 @@
use local_runtime::{
wasm_binary_unwrap, AccountId, AuraConfig, AuraId, BalancesConfig, BaseFeeConfig,
BlockRewardConfig, CouncilConfig, DemocracyConfig, EVMConfig, GenesisConfig, GrandpaConfig,
GrandpaId, Precompiles, Signature, SudoConfig, SystemConfig, TechnicalCommitteeConfig,
TreasuryConfig, VestingConfig,
BlockRewardConfig, CouncilConfig, DappStakingConfig, DemocracyConfig, EVMConfig, GenesisConfig,
GrandpaConfig, GrandpaId, Precompiles, Signature, SudoConfig, SystemConfig,
TechnicalCommitteeConfig, TreasuryConfig, VestingConfig,
};
use sc_service::ChainType;
use sp_core::{crypto::Ss58Codec, sr25519, Pair, Public};
use sp_runtime::{
traits::{IdentifyAccount, Verify},
Perbill,
Perbill, Permill,
};

use pallet_dapp_staking_v3::TierThreshold;

type AccountPublic = <Signature as Verify>::Signer;

/// Specialized `ChainSpec` for Shiden Network.
Expand Down Expand Up @@ -181,6 +183,36 @@ fn testnet_genesis(
},
democracy: DemocracyConfig::default(),
treasury: TreasuryConfig::default(),
dapp_staking: DappStakingConfig {
reward_portion: vec![
Permill::from_percent(40),
Permill::from_percent(30),
Permill::from_percent(20),
Permill::from_percent(10),
],
slot_distribution: vec![
Permill::from_percent(10),
Permill::from_percent(20),
Permill::from_percent(30),
Permill::from_percent(40),
],
tier_thresholds: vec![
TierThreshold::DynamicTvlAmount {
amount: 100,
minimum_amount: 80,
},
TierThreshold::DynamicTvlAmount {
amount: 50,
minimum_amount: 40,
},
TierThreshold::DynamicTvlAmount {
amount: 20,
minimum_amount: 20,
},
TierThreshold::FixedTvlAmount { amount: 10 },
],
slots_per_tier: vec![10, 20, 30, 40],
},
}
}

Expand Down
77 changes: 73 additions & 4 deletions pallets/dapp-staking-v3/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,21 +48,19 @@ use frame_support::{
use frame_system::pallet_prelude::*;
use sp_runtime::{
traits::{BadOrigin, Saturating, Zero},
Perbill,
Perbill, Permill,
};
pub use sp_std::vec::Vec;

use astar_primitives::Balance;

use crate::types::*;
pub use crate::types::{PriceProvider, RewardPoolProvider};

pub use pallet::*;

#[cfg(test)]
mod test;

mod types;
pub use types::*; // TODO: maybe make it more restrictive later

const STAKING_ID: LockIdentifier = *b"dapstake";

Expand Down Expand Up @@ -401,6 +399,77 @@ pub mod pallet {
pub type DAppTiers<T: Config> =
StorageMap<_, Twox64Concat, EraNumber, DAppTierRewardsFor<T>, OptionQuery>;

#[pallet::genesis_config]
#[derive(frame_support::DefaultNoBound)]
pub struct GenesisConfig {
pub reward_portion: Vec<Permill>,
pub slot_distribution: Vec<Permill>,
pub tier_thresholds: Vec<TierThreshold>,
pub slots_per_tier: Vec<u16>,
}

#[pallet::genesis_build]
impl<T: Config> GenesisBuild<T> for GenesisConfig {
fn build(&self) {
// Prepare tier parameters & verify their correctness
let tier_params = TierParameters::<T::NumberOfTiers> {
reward_portion: BoundedVec::<Permill, T::NumberOfTiers>::try_from(
self.reward_portion.clone(),
)
.expect("Invalid number of reward portions provided."),
slot_distribution: BoundedVec::<Permill, T::NumberOfTiers>::try_from(
self.slot_distribution.clone(),
)
.expect("Invalid number of slot distributions provided."),
tier_thresholds: BoundedVec::<TierThreshold, T::NumberOfTiers>::try_from(
self.tier_thresholds.clone(),
)
.expect("Invalid number of tier thresholds provided."),
};
assert!(
tier_params.is_valid(),
"Invalid tier parameters values provided."
);

// Prepare tier configuration and verify its correctness
let number_of_slots = self
.slots_per_tier
.iter()
.fold(0, |acc, &slots| acc + slots);
let tier_config = TiersConfiguration::<T::NumberOfTiers> {
number_of_slots,
slots_per_tier: BoundedVec::<u16, T::NumberOfTiers>::try_from(
self.slots_per_tier.clone(),
)
.expect("Invalid number of slots per tier entries provided."),
reward_portion: tier_params.reward_portion.clone(),
tier_thresholds: tier_params.tier_thresholds.clone(),
};
assert!(
tier_params.is_valid(),
"Invalid tier config values provided."
);

// Prepare initial protocol state
let protocol_state = ProtocolState {
era: 1,
next_era_start: Pallet::<T>::blocks_per_voting_period() + 1_u32.into(),
period_info: PeriodInfo {
number: 1,
period_type: PeriodType::Voting,
ending_era: 2,
},
maintenance: false,
};

// Initialize necessary storage items
ActiveProtocolState::<T>::put(protocol_state);
StaticTierParams::<T>::put(tier_params);
TierConfig::<T>::put(tier_config.clone());
NextTierConfig::<T>::put(tier_config);
}
}

#[pallet::hooks]
impl<T: Config> Hooks<BlockNumberFor<T>> for Pallet<T> {
fn on_initialize(now: BlockNumberFor<T>) -> Weight {
Expand Down
8 changes: 5 additions & 3 deletions pallets/dapp-staking-v3/src/test/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,14 +180,14 @@ impl ExtBuilder {
ext.execute_with(|| {
System::set_block_number(1);

// TODO: not sure why the mess with type happens here, I can check it later
// Not sure why the mess with type happens here, but trait specification is needed to compile
let era_length: BlockNumber =
<<Test as pallet_dapp_staking::Config>::StandardEraLength as sp_core::Get<_>>::get();
let voting_period_length_in_eras: EraNumber =
<<Test as pallet_dapp_staking::Config>::StandardErasPerVotingPeriod as sp_core::Get<_>>::get(
);

// TODO: handle this via GenesisConfig, and some helper functions to set the state
// Init protocol state
pallet_dapp_staking::ActiveProtocolState::<Test>::put(ProtocolState {
era: 1,
next_era_start: era_length.saturating_mul(voting_period_length_in_eras.into()) + 1,
Expand All @@ -199,7 +199,7 @@ impl ExtBuilder {
maintenance: false,
});

// TODO: improve this later, should be handled via genesis?
// Init tier params
let tier_params = TierParameters::<<Test as Config>::NumberOfTiers> {
reward_portion: BoundedVec::try_from(vec![
Permill::from_percent(40),
Expand All @@ -223,6 +223,8 @@ impl ExtBuilder {
])
.unwrap(),
};

// Init tier config, based on the initial params
let init_tier_config = TiersConfiguration::<<Test as Config>::NumberOfTiers> {
number_of_slots: 100,
slots_per_tier: BoundedVec::try_from(vec![10, 20, 30, 40]).unwrap(),
Expand Down
81 changes: 71 additions & 10 deletions pallets/dapp-staking-v3/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use sp_runtime::{
traits::{AtLeast32BitUnsigned, UniqueSaturatedInto, Zero},
FixedPointNumber, Permill, Saturating,
};
pub use sp_std::vec::Vec;
pub use sp_std::{fmt::Debug, vec::Vec};

use astar_primitives::Balance;

Expand Down Expand Up @@ -281,10 +281,19 @@ where
}

/// General info about user's stakes
#[derive(Encode, Decode, MaxEncodedLen, Clone, Debug, PartialEq, Eq, TypeInfo)]
#[derive(
Encode,
Decode,
MaxEncodedLen,
RuntimeDebugNoBound,
PartialEqNoBound,
EqNoBound,
CloneNoBound,
TypeInfo,
)]
#[scale_info(skip_type_params(UnlockingLen))]
pub struct AccountLedger<
BlockNumber: AtLeast32BitUnsigned + MaxEncodedLen + Copy,
BlockNumber: AtLeast32BitUnsigned + MaxEncodedLen + Copy + Debug,
UnlockingLen: Get<u32>,
> {
/// How much active locked amount an account has.
Expand All @@ -307,7 +316,7 @@ pub struct AccountLedger<

impl<BlockNumber, UnlockingLen> Default for AccountLedger<BlockNumber, UnlockingLen>
where
BlockNumber: AtLeast32BitUnsigned + MaxEncodedLen + Copy,
BlockNumber: AtLeast32BitUnsigned + MaxEncodedLen + Copy + Debug,
UnlockingLen: Get<u32>,
{
fn default() -> Self {
Expand All @@ -323,7 +332,7 @@ where

impl<BlockNumber, UnlockingLen> AccountLedger<BlockNumber, UnlockingLen>
where
BlockNumber: AtLeast32BitUnsigned + MaxEncodedLen + Copy,
BlockNumber: AtLeast32BitUnsigned + MaxEncodedLen + Copy + Debug,
UnlockingLen: Get<u32>,
{
/// Empty if no locked/unlocking/staked info exists.
Expand Down Expand Up @@ -1006,7 +1015,17 @@ impl SingularStakingInfo {
const STAKING_SERIES_HISTORY: u32 = 3;

/// Composite type that holds information about how much was staked on a contract during some past eras & periods, including the current era & period.
#[derive(Encode, Decode, MaxEncodedLen, Clone, Debug, PartialEq, Eq, TypeInfo, Default)]
#[derive(
Encode,
Decode,
MaxEncodedLen,
RuntimeDebugNoBound,
PartialEqNoBound,
EqNoBound,
CloneNoBound,
TypeInfo,
Default,
)]
pub struct ContractStakeAmountSeries(BoundedVec<StakeAmount, ConstU32<STAKING_SERIES_HISTORY>>);
impl ContractStakeAmountSeries {
/// Helper function to create a new instance of `ContractStakeAmountSeries`.
Expand Down Expand Up @@ -1246,7 +1265,16 @@ pub enum EraRewardSpanError {
}

/// Used to efficiently store era span information.
#[derive(Encode, Decode, MaxEncodedLen, Clone, Debug, PartialEq, Eq, TypeInfo)]
#[derive(
Encode,
Decode,
MaxEncodedLen,
RuntimeDebugNoBound,
PartialEqNoBound,
EqNoBound,
CloneNoBound,
TypeInfo,
)]
#[scale_info(skip_type_params(SL))]
pub struct EraRewardSpan<SL: Get<u32>> {
/// Span of EraRewardInfo entries.
Expand Down Expand Up @@ -1333,6 +1361,7 @@ where

/// Description of tier entry requirement.
#[derive(Encode, Decode, MaxEncodedLen, Copy, Clone, Debug, PartialEq, Eq, TypeInfo)]
#[cfg_attr(feature = "std", derive(serde::Serialize, serde::Deserialize))]
pub enum TierThreshold {
/// Entry into tier is mandated by minimum amount of staked funds.
/// Value is fixed, and is not expected to change in between periods.
Expand All @@ -1357,7 +1386,16 @@ impl TierThreshold {
}

/// Top level description of tier slot parameters used to calculate tier configuration.
#[derive(Encode, Decode, MaxEncodedLen, Clone, Debug, PartialEq, Eq, TypeInfo)]
#[derive(
Encode,
Decode,
MaxEncodedLen,
RuntimeDebugNoBound,
PartialEqNoBound,
EqNoBound,
CloneNoBound,
TypeInfo,
)]
#[scale_info(skip_type_params(NT))]
pub struct TierParameters<NT: Get<u32>> {
/// Reward distribution per tier, in percentage.
Expand All @@ -1381,6 +1419,8 @@ impl<NT: Get<u32>> TierParameters<NT> {
number_of_tiers == self.reward_portion.len()
&& number_of_tiers == self.slot_distribution.len()
&& number_of_tiers == self.tier_thresholds.len()

// TODO: Make check more detailed, verify that entries sum up to 1 or 100%
}
}

Expand All @@ -1397,7 +1437,16 @@ impl<NT: Get<u32>> Default for TierParameters<NT> {
// TODO: refactor these structs so we only have 1 bounded vector, where each entry contains all the necessary info to describe the tier?

/// Configuration of dApp tiers.
#[derive(Encode, Decode, MaxEncodedLen, Clone, Debug, PartialEq, Eq, TypeInfo)]
#[derive(
Encode,
Decode,
MaxEncodedLen,
RuntimeDebugNoBound,
PartialEqNoBound,
EqNoBound,
CloneNoBound,
TypeInfo,
)]
#[scale_info(skip_type_params(NT))]
pub struct TiersConfiguration<NT: Get<u32>> {
/// Total number of slots.
Expand Down Expand Up @@ -1553,7 +1602,16 @@ pub struct DAppTier {
}

/// Information about all of the dApps that got into tiers, and tier rewards
#[derive(Encode, Decode, MaxEncodedLen, Clone, Debug, PartialEq, Eq, TypeInfo)]
#[derive(
Encode,
Decode,
MaxEncodedLen,
RuntimeDebugNoBound,
PartialEqNoBound,
EqNoBound,
CloneNoBound,
TypeInfo,
)]
#[scale_info(skip_type_params(MD, NT))]
pub struct DAppTierRewards<MD: Get<u32>, NT: Get<u32>> {
/// DApps and their corresponding tiers (or `None` if they have been claimed in the meantime)
Expand Down Expand Up @@ -1651,6 +1709,9 @@ pub trait PriceProvider {
fn average_price() -> FixedU64;
}

// TODO: however the implementation ends up looking,
// it should consider total staked amount when filling up the bonus pool.
// This is to ensure bonus rewards aren't too large in case there is little amount of staked funds.
pub trait RewardPoolProvider {
/// Get the reward pools for stakers and dApps.
///
Expand Down

0 comments on commit 4ea8556

Please sign in to comment.