Skip to content

Commit

Permalink
DIP-7 improvement
Browse files Browse the repository at this point in the history
Signed-off-by: Xavier Lau <xavier@inv.cafe>
  • Loading branch information
AurevoirXavier committed Aug 27, 2024
1 parent 005222d commit ef64d77
Show file tree
Hide file tree
Showing 13 changed files with 188 additions and 114 deletions.
1 change: 0 additions & 1 deletion pallet/account-migration/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,6 @@ impl darwinia_deposit::Config for Runtime {
type DepositMigrator = ();
type Kton = Dummy;
type MaxDeposits = frame_support::traits::ConstU32<512>;
type MinLockingAmount = ();
type Ring = Balances;
type RuntimeEvent = RuntimeEvent;
type Treasury = ();
Expand Down
6 changes: 1 addition & 5 deletions pallet/deposit/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,10 +86,6 @@ pub mod pallet {
#[pallet::constant]
type Treasury: Get<Self::AccountId>;

/// Minimum amount to lock at least.
#[pallet::constant]
type MinLockingAmount: Get<Balance>;

/// Maximum deposit count.
///
/// In currently design, this should not be greater than `u16::MAX`.
Expand Down Expand Up @@ -165,7 +161,7 @@ pub mod pallet {
pub fn lock(origin: OriginFor<T>, amount: Balance, months: u8) -> DispatchResult {
let who = ensure_signed(origin)?;

if amount < T::MinLockingAmount::get() {
if amount == 0 {
Err(<Error<T>>::LockAtLeastSome)?;
}
if months == 0 {
Expand Down
1 change: 0 additions & 1 deletion pallet/deposit/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ impl crate::Config for Runtime {
type DepositMigrator = ();
type Kton = KtonMinting;
type MaxDeposits = frame_support::traits::ConstU32<16>;
type MinLockingAmount = frame_support::traits::ConstU128<UNIT>;
type Ring = Balances;
type RuntimeEvent = RuntimeEvent;
type Treasury = ();
Expand Down
2 changes: 1 addition & 1 deletion pallet/staking/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ mod benchmarks {
let a = frame_benchmarking::whitelisted_caller::<T::AccountId>();
let a_cloned = a.clone();

call_on_exposure!(<Previous<T>>::insert(
call_on_cache_v1!(<Previous<T>>::insert(
&a,
Exposure {
commission: Perbill::zero(),
Expand Down
122 changes: 77 additions & 45 deletions pallet/staking/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ pub use darwinia_staking_traits::*;
use codec::FullCodec;
use ethabi::{Function, Param, ParamType, StateMutability, Token};
// darwinia
use dc_types::{Balance, Moment, UNIT};
use dc_types::{Balance, Moment};
// polkadot-sdk
use frame_support::{
pallet_prelude::*,
Expand All @@ -68,7 +68,7 @@ use sp_std::{collections::btree_map::BTreeMap, prelude::*};

/// Make it easier to call a function on a specific exposure storage.
#[macro_export]
macro_rules! call_on_exposure {
macro_rules! call_on_cache_v1 {
($s_e:expr, <$s:ident<$t:ident>>$($f:tt)*) => {{
match $s_e {
($crate::CacheState::$s, _, _) => Ok(<$crate::ExposureCache0<$t>>$($f)*),
Expand All @@ -84,12 +84,12 @@ macro_rules! call_on_exposure {
(<$s:ident<$t:ident>>$($f:tt)*) => {{
let s = <$crate::CacheStates<$t>>::get();

$crate::call_on_exposure!(s, <$s<$t>>$($f)*)
$crate::call_on_cache_v1!(s, <$s<$t>>$($f)*)
}};
}
/// Make it easier to call a function on a specific collators storage.
#[macro_export]
macro_rules! call_on_cache {
macro_rules! call_on_cache_v2 {
($s_e:expr, <$s:ident<$t:ident>>$($f:tt)*) => {{
match $s_e {
($crate::CacheState::$s, _, _) => Ok(<$crate::CollatorsCache0<$t>>$($f)*),
Expand All @@ -105,7 +105,7 @@ macro_rules! call_on_cache {
(<$s:ident<$t:ident>>$($f:tt)*) => {{
let s = <$crate::CacheStates<$t>>::get();

$crate::call_on_cache!(s, <$s<$t>>$($f)*)
$crate::call_on_cache_v2!(s, <$s<$t>>$($f)*)
}};
}

Expand Down Expand Up @@ -398,12 +398,29 @@ pub mod pallet {
// There are already plenty of tasks to handle during the new session,
// so refrain from assigning any additional ones here.
if !T::ShouldEndSession::get() {
call_on_exposure!(<Previous<T>>::iter_keys()
// TODO?: make this value adjustable
let w2 = call_on_cache_v2!(<Previous<T>>::get())
.map(|cs| {
let mut cs = cs.into_iter();
let w = cs
.by_ref()
// ? make this value adjustable.
.take(1)
.fold(Weight::zero(), |acc, c| {
acc + Self::payout_inner(c).unwrap_or(Zero::zero())
});
let _ = call_on_cache_v2!(<Previous<T>>::put(cs.collect::<Vec<_>>()));

w
})
.unwrap_or_default();
let w1 = call_on_cache_v1!(<Previous<T>>::iter_keys()
// ? make this value adjustable.
.take(1)
.fold(Zero::zero(), |acc, e| acc
+ Self::payout_inner(e).unwrap_or(Zero::zero())))
.unwrap_or_default()
.fold(Weight::zero(), |acc, c| acc
+ Self::payout_inner(c).unwrap_or(Zero::zero())))
.unwrap_or_default();

w1 + w2
} else {
Zero::zero()
}
Expand Down Expand Up @@ -721,47 +738,61 @@ pub mod pallet {
let reward_r = amount.saturating_div(2);
let reward_k = amount.saturating_sub(reward_r);
let (b_total, map) = <AuthoredBlocksCount<T>>::take();
let collators_v2 = call_on_cache!(<Current<T>>::get()).unwrap_or_default();

map.into_iter().for_each(|(c, b)| {
let r = Perbill::from_rational(b, b_total).mul_floor(reward_r);

if collators_v2.contains(&c) {
T::RingStaking::distribute(Some(c), r);
} else {
<PendingRewards<T>>::mutate(c, |u| *u = u.map(|u| u + r).or(Some(r)));
}
<PendingRewards<T>>::mutate(c, |u| *u = u.map(|u| u + r).or(Some(r)));
});

T::KtonStaking::distribute(None, reward_k);
}

/// Pay the reward to the collator and its nominators.
pub fn payout_inner(collator: T::AccountId) -> Result<Weight, DispatchError> {
let c_exposure =
call_on_exposure!(<Previous<T>>::take(&collator).ok_or(<Error<T>>::NoReward)?)?;
let c_total_payout =
<PendingRewards<T>>::take(&collator).ok_or(<Error<T>>::NoReward)?;
let mut c_payout = c_exposure.commission * c_total_payout;
let n_payout = c_total_payout - c_payout;
for n_exposure in c_exposure.nominators {
let n_payout = Perbill::from_rational(n_exposure.vote, c_exposure.vote) * n_payout;

if collator == n_exposure.who {
// If the collator nominated themselves.

c_payout += n_payout;
} else if T::IssuingManager::reward(&n_exposure.who, n_payout).is_ok() {
Self::deposit_event(Event::Payout { who: n_exposure.who, amount: n_payout });
} else {
Self::deposit_event(Event::Unpaid { who: n_exposure.who, amount: n_payout });
}
// Pay to V2.
if call_on_cache_v2!(<Previous<T>>::get()).unwrap_or_default().contains(&collator) {
T::RingStaking::distribute(
Some(collator.clone()),
<PendingRewards<T>>::take(&collator).ok_or(<Error<T>>::NoReward)?,
);
}
// Pay to V1.
else if let Ok(Some(c_exposure)) = call_on_cache_v1!(<Previous<T>>::take(&collator)) {
let c_total_payout =
<PendingRewards<T>>::take(&collator).ok_or(<Error<T>>::NoReward)?;
let mut c_payout = c_exposure.commission * c_total_payout;
let n_payout = c_total_payout - c_payout;
for n_exposure in c_exposure.nominators {
let n_payout =
Perbill::from_rational(n_exposure.vote, c_exposure.vote) * n_payout;

if collator == n_exposure.who {
// If the collator nominated themselves.

c_payout += n_payout;
} else if T::IssuingManager::reward(&n_exposure.who, n_payout).is_ok() {
Self::deposit_event(Event::Payout {
who: n_exposure.who,
amount: n_payout,
});
} else {
Self::deposit_event(Event::Unpaid {
who: n_exposure.who,
amount: n_payout,
});
}
}

if T::IssuingManager::reward(&collator, c_payout).is_ok() {
Self::deposit_event(Event::Payout { who: collator, amount: c_payout });
if T::IssuingManager::reward(&collator, c_payout).is_ok() {
Self::deposit_event(Event::Payout { who: collator, amount: c_payout });
} else {
Self::deposit_event(Event::Unpaid { who: collator, amount: c_payout });
}
} else {
Self::deposit_event(Event::Unpaid { who: collator, amount: c_payout });
// Impossible case.

Err(<Error<T>>::NoReward)?;
}

Ok(<T as Config>::WeightInfo::payout())
Expand All @@ -773,8 +804,8 @@ pub mod pallet {
<Pallet<T>>::shift_cache_states();

#[allow(deprecated)]
call_on_exposure!(<Next<T>>::remove_all(None)).ok()?;
call_on_cache!(<Next<T>>::kill()).ok()?;
call_on_cache_v1!(<Next<T>>::remove_all(None)).ok()?;
call_on_cache_v2!(<Next<T>>::kill()).ok()?;

let bn = <frame_system::Pallet<T>>::block_number();

Expand All @@ -794,7 +825,7 @@ pub mod pallet {

if cs.is_empty() {
// TODO: update this once the migration is completed.
// Possible case under the hyper election mode.
// Possible case under the hybrid election mode.

// Impossible case.
//
Expand Down Expand Up @@ -857,7 +888,7 @@ pub mod pallet {
.into_iter()
.take(n as _)
.map(|((c, e), _)| {
call_on_exposure!(cache_states, <Next<T>>::insert(&c, e)).map(|_| c).ok()
call_on_cache_v1!(cache_states, <Next<T>>::insert(&c, e)).map(|_| c).ok()
})
.collect()
}
Expand Down Expand Up @@ -895,7 +926,7 @@ pub mod pallet {
fn elect_from_contract(n: u32) -> Option<Vec<T::AccountId>> {
let winners = T::RingStaking::elect(n)?;

call_on_cache!(<Next<T>>::put(winners.clone())).ok()?;
call_on_cache_v2!(<Next<T>>::put(winners.clone())).ok()?;

Some(winners)
}
Expand Down Expand Up @@ -1083,13 +1114,14 @@ where
}

/// Transfer issued token from pallet-treasury.
pub struct TreasuryIssuing<T>(PhantomData<T>);
impl<T> IssuingManager<T> for TreasuryIssuing<T>
pub struct TreasuryIssuing<T, R>(PhantomData<(T, R)>);
impl<T, R> IssuingManager<T> for TreasuryIssuing<T, R>
where
T: Config,
R: Get<Balance>,
{
fn calculate_reward(_: Balance) -> Balance {
20_000 * UNIT
R::get()
}

fn reward(who: &T::AccountId, amount: Balance) -> DispatchResult {
Expand Down
14 changes: 9 additions & 5 deletions pallet/staking/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ use scale_info::TypeInfo;
use serde::{Deserialize, Serialize};
// darwinia
use crate::*;
use dc_types::UNIT;
// polkadot-sdk
use frame_support::{assert_ok, derive_impl, traits::OnInitialize};
use sp_core::H160;
Expand Down Expand Up @@ -105,7 +106,6 @@ impl darwinia_deposit::Config for Runtime {
type DepositMigrator = ();
type Kton = KtonMinting;
type MaxDeposits = frame_support::traits::ConstU32<16>;
type MinLockingAmount = frame_support::traits::ConstU128<UNIT>;
type Ring = Balances;
type RuntimeEvent = RuntimeEvent;
type Treasury = TreasuryAcct;
Expand Down Expand Up @@ -216,23 +216,23 @@ impl crate::IssuingManager<Runtime> for StatedOnSessionEnd {
if INFLATION_TYPE.with(|v| *v.borrow()) == 0 {
<crate::BalanceIssuing<Runtime>>::inflate()
} else {
<crate::TreasuryIssuing<Runtime>>::inflate()
<crate::TreasuryIssuing<Runtime, frame_support::traits::ConstU128<{ 20_000 * UNIT }>>>::inflate()
}
}

fn calculate_reward(issued: Balance) -> Balance {
if INFLATION_TYPE.with(|v| *v.borrow()) == 0 {
<crate::BalanceIssuing<Runtime>>::calculate_reward(issued)
} else {
<crate::TreasuryIssuing<Runtime>>::calculate_reward(issued)
<crate::TreasuryIssuing<Runtime, frame_support::traits::ConstU128<{ 20_000 * UNIT }>>>::calculate_reward(issued)
}
}

fn reward(who: &AccountId, amount: Balance) -> sp_runtime::DispatchResult {
if INFLATION_TYPE.with(|v| *v.borrow()) == 0 {
<crate::BalanceIssuing<Runtime>>::reward(who, amount)
} else {
<crate::TreasuryIssuing<Runtime>>::reward(who, amount)
<crate::TreasuryIssuing<Runtime,frame_support::traits::ConstU128<{20_000 * UNIT}>>>::reward(who, amount)
}
}
}
Expand Down Expand Up @@ -454,7 +454,11 @@ pub fn new_session() {
}

pub fn payout() {
crate::call_on_exposure!(<Previous<Runtime>>::iter_keys().for_each(|c| {
crate::call_on_cache_v2!(<Previous<Runtime>>::get().into_iter().for_each(|c| {
let _ = Staking::payout_inner(c);
}))
.unwrap();
crate::call_on_cache_v1!(<Previous<Runtime>>::iter_keys().for_each(|c| {
let _ = Staking::payout_inner(c);
}))
.unwrap();
Expand Down
Loading

0 comments on commit ef64d77

Please sign in to comment.