Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DIP-7 improvement #1580

Merged
merged 1 commit into from
Aug 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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