Skip to content

Commit

Permalink
staking compiles, tests fail
Browse files Browse the repository at this point in the history
  • Loading branch information
Ank4n committed Jun 21, 2024
1 parent 2657cfb commit 192af84
Show file tree
Hide file tree
Showing 9 changed files with 143 additions and 126 deletions.
12 changes: 6 additions & 6 deletions substrate/frame/staking/src/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -612,21 +612,21 @@ benchmarks! {
<ErasValidatorPrefs<T>>::insert(current_era, validator.clone(), <Staking<T>>::validators(&validator));

let caller = whitelisted_caller();
let balance_before = T::Currency::free_balance(&validator);
let balance_before = T::Currency::balance(&validator);
let mut nominator_balances_before = Vec::new();
for (stash, _) in &nominators {
let balance = T::Currency::free_balance(stash);
let balance = T::Currency::balance(stash);
nominator_balances_before.push(balance);
}
}: payout_stakers(RawOrigin::Signed(caller), validator.clone(), current_era)
verify {
let balance_after = T::Currency::free_balance(&validator);
let balance_after = T::Currency::balance(&validator);
ensure!(
balance_before < balance_after,
"Balance of validator stash should have increased after payout.",
);
for ((stash, _), balance_before) in nominators.iter().zip(nominator_balances_before.iter()) {
let balance_after = T::Currency::free_balance(stash);
let balance_after = T::Currency::balance(stash);
ensure!(
balance_before < &balance_after,
"Balance of nominator stash should have increased after payout.",
Expand Down Expand Up @@ -795,7 +795,7 @@ benchmarks! {
}
Ledger::<T>::insert(controller, staking_ledger);
let slash_amount = T::Currency::minimum_balance() * 10u32.into();
let balance_before = T::Currency::free_balance(&stash);
let balance_before = T::Currency::balance(&stash);
}: {
crate::slashing::do_slash::<T>(
&stash,
Expand All @@ -805,7 +805,7 @@ benchmarks! {
EraIndex::zero()
);
} verify {
let balance_after = T::Currency::free_balance(&stash);
let balance_after = T::Currency::balance(&stash);
assert!(balance_before > balance_after);
}

Expand Down
17 changes: 8 additions & 9 deletions substrate/frame/staking/src/ledger.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,14 @@
use frame_support::{
defensive, ensure,
traits::{Defensive, LockableCurrency},
traits::{Defensive, fungible::MutateHold, tokens::Precision},
};
use sp_staking::{StakingAccount, StakingInterface};
use sp_std::prelude::*;

use crate::{
BalanceOf, Bonded, Config, Error, Ledger, Pallet, Payee, RewardDestination, StakingLedger,
VirtualStakers, STAKING_ID,
VirtualStakers, STAKING_ID, HoldReason,
};

#[cfg(any(feature = "runtime-benchmarks", test))]
Expand Down Expand Up @@ -191,12 +191,9 @@ impl<T: Config> StakingLedger<T> {
// We skip locking virtual stakers.
if !Pallet::<T>::is_virtual_staker(&self.stash) {
// for direct stakers, update lock on stash based on ledger.
T::Currency::set_lock(
STAKING_ID,
&self.stash,
self.total,
frame_support::traits::WithdrawReasons::all(),
);
T::Currency::set_on_hold(&HoldReason::Staking.into(), &self.stash, self.total).map_err(|_| {
Error::<T>::NotEnoughFunds
})?
}

Ledger::<T>::insert(
Expand Down Expand Up @@ -270,7 +267,9 @@ impl<T: Config> StakingLedger<T> {
// kill virtual staker if it exists.
if <VirtualStakers<T>>::take(&stash).is_none() {
// if not virtual staker, clear locks.
T::Currency::remove_lock(STAKING_ID, &ledger.stash);
let _ = T::Currency::release_all(&HoldReason::Staking.into(), &ledger.stash, Precision::BestEffort).map_err(|_| {
Error::<T>::BadState
}).defensive()?;
}

Ok(())
Expand Down
11 changes: 4 additions & 7 deletions substrate/frame/staking/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -308,7 +308,8 @@ use codec::{Decode, Encode, HasCompact, MaxEncodedLen};
use frame_support::{
defensive, defensive_assert,
traits::{
ConstU32, Currency, Defensive, DefensiveMax, DefensiveSaturating, Get, LockIdentifier,
tokens::fungible::{Credit, Debt, Inspect as FunInspect}, ConstU32, Defensive, DefensiveMax, DefensiveSaturating, Get,
LockIdentifier,
},
weights::Weight,
BoundedVec, CloneNoBound, EqNoBound, PartialEqNoBound, RuntimeDebugNoBound,
Expand Down Expand Up @@ -358,12 +359,8 @@ pub type RewardPoint = u32;
/// The balance type of this pallet.
pub type BalanceOf<T> = <T as Config>::CurrencyBalance;

type PositiveImbalanceOf<T> = <<T as Config>::Currency as Currency<
<T as frame_system::Config>::AccountId,
>>::PositiveImbalance;
pub type NegativeImbalanceOf<T> = <<T as Config>::Currency as Currency<
<T as frame_system::Config>::AccountId,
>>::NegativeImbalance;
type PositiveImbalanceOf<T> = Debt<<T as frame_system::Config>::AccountId, <T as Config>::Currency>;
pub type NegativeImbalanceOf<T> = Credit<<T as frame_system::Config>::AccountId, <T as Config>::Currency>;

type AccountIdLookupOf<T> = <<T as frame_system::Config>::Lookup as StaticLookup>::Source;

Expand Down
15 changes: 8 additions & 7 deletions substrate/frame/staking/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ use frame_election_provider_support::{
use frame_support::{
assert_ok, derive_impl, ord_parameter_types, parameter_types,
traits::{
ConstU64, Currency, EitherOfDiverse, FindAuthor, Get, Hooks, Imbalance, LockableCurrency,
fungible::{Inspect, Mutate, MutateHold},
ConstU64, EitherOfDiverse, FindAuthor, Get, Hooks, Imbalance,
OnUnbalanced, OneSessionHandler, WithdrawReasons,
},
weights::constants::RocksDbWeight,
Expand Down Expand Up @@ -575,7 +576,7 @@ pub(crate) fn current_era() -> EraIndex {
}

pub(crate) fn bond(who: AccountId, val: Balance) {
let _ = Balances::make_free_balance_be(&who, val);
let _ = Balances::set_balance(&who, val);
assert_ok!(Staking::bond(RuntimeOrigin::signed(who), val, RewardDestination::Stash));
}

Expand Down Expand Up @@ -811,7 +812,7 @@ pub(crate) fn bond_extra_no_checks(stash: &AccountId, amount: Balance) {
let mut ledger = Ledger::<Test>::get(&controller).expect("ledger must exist to bond_extra");

let new_total = ledger.total + amount;
Balances::set_lock(crate::STAKING_ID, stash, new_total, WithdrawReasons::all());
Balances::set_on_hold(&HoldReason::Staking.into(), stash, new_total).expect("account should have enough funds to hold");
ledger.total = new_total;
ledger.active = new_total;
Ledger::<Test>::insert(controller, ledger);
Expand All @@ -820,10 +821,10 @@ pub(crate) fn bond_extra_no_checks(stash: &AccountId, amount: Balance) {
pub(crate) fn setup_double_bonded_ledgers() {
let init_ledgers = Ledger::<Test>::iter().count();

let _ = Balances::make_free_balance_be(&333, 2000);
let _ = Balances::make_free_balance_be(&444, 2000);
let _ = Balances::make_free_balance_be(&555, 2000);
let _ = Balances::make_free_balance_be(&777, 2000);
let _ = Balances::set_balance(&333, 2000);
let _ = Balances::set_balance(&444, 2000);
let _ = Balances::set_balance(&555, 2000);
let _ = Balances::set_balance(&777, 2000);

assert_ok!(Staking::bond(RuntimeOrigin::signed(333), 10, RewardDestination::Staked));
assert_ok!(Staking::bond(RuntimeOrigin::signed(444), 20, RewardDestination::Staked));
Expand Down
24 changes: 13 additions & 11 deletions substrate/frame/staking/src/pallet/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ use frame_support::{
dispatch::WithPostDispatchInfo,
pallet_prelude::*,
traits::{
Currency, Defensive, DefensiveSaturating, EstimateNextNewSession, Get, Imbalance,
InspectLockableCurrency, Len, LockableCurrency, OnUnbalanced, TryCollect, UnixTime,
fungible::{Inspect, InspectHold, MutateHold, Mutate, Balanced}, Defensive, DefensiveSaturating, EstimateNextNewSession, Get, Imbalance,
Len, OnUnbalanced, TryCollect, UnixTime,
},
weights::Weight,
};
Expand All @@ -55,12 +55,14 @@ use crate::{
BalanceOf, EraInfo, EraPayout, Exposure, ExposureOf, Forcing, IndividualExposure,
LedgerIntegrityState, MaxNominationsOf, MaxWinnersOf, Nominations, NominationsQuota,
PositiveImbalanceOf, RewardDestination, SessionInterface, StakingLedger, ValidatorPrefs,
HoldReason,
};

use super::pallet::*;

#[cfg(feature = "try-runtime")]
use frame_support::ensure;
use frame_support::traits::tokens::Precision;
#[cfg(any(test, feature = "try-runtime"))]
use sp_runtime::TryRuntimeError;

Expand Down Expand Up @@ -96,7 +98,7 @@ impl<T: Config> Pallet<T> {
pub(crate) fn inspect_bond_state(
stash: &T::AccountId,
) -> Result<LedgerIntegrityState, Error<T>> {
let lock = T::Currency::balance_locked(crate::STAKING_ID, &stash);
let lock = T::Currency::balance_on_hold(&HoldReason::Staking.into(), &stash);

let controller = <Bonded<T>>::get(stash).ok_or_else(|| {
if lock == Zero::zero() {
Expand Down Expand Up @@ -164,7 +166,7 @@ impl<T: Config> Pallet<T> {
} else {
// additional amount or actual balance of stash whichever is lower.
additional.min(
T::Currency::free_balance(stash)
T::Currency::balance(stash)
.checked_sub(&ledger.total)
.ok_or(ArithmeticError::Overflow)?,
)
Expand Down Expand Up @@ -413,13 +415,13 @@ impl<T: Config> Pallet<T> {
}
let dest = Self::payee(StakingAccount::Stash(stash.clone()))?;

let maybe_imbalance = match dest {
RewardDestination::Stash => T::Currency::deposit_into_existing(stash, amount).ok(),
let maybe_imbalance: Option<PositiveImbalanceOf<T>> = match dest {
RewardDestination::Stash => T::Currency::deposit(stash, amount, Precision::Exact).ok(),
RewardDestination::Staked => Self::ledger(Stash(stash.clone()))
.and_then(|mut ledger| {
ledger.active += amount;
ledger.total += amount;
let r = T::Currency::deposit_into_existing(stash, amount).ok();
let r = T::Currency::deposit(stash, amount, Precision::Exact).ok();

let _ = ledger
.update()
Expand All @@ -429,15 +431,15 @@ impl<T: Config> Pallet<T> {
})
.unwrap_or_default(),
RewardDestination::Account(ref dest_account) =>
Some(T::Currency::deposit_creating(&dest_account, amount)),
T::Currency::deposit(&dest_account, amount, Precision::Exact).ok(),
RewardDestination::None => None,
#[allow(deprecated)]
RewardDestination::Controller => Self::bonded(stash)
.map(|controller| {
defensive!("Paying out controller as reward destination which is deprecated and should be migrated.");
// This should never happen once payees with a `Controller` variant have been migrated.
// But if it does, just pay the controller account.
T::Currency::deposit_creating(&controller, amount)
T::Currency::deposit(&controller, amount, Precision::Exact).unwrap_or_default()
}),
};
maybe_imbalance.map(|imbalance| (imbalance, dest))
Expand Down Expand Up @@ -1919,7 +1921,7 @@ impl<T: Config> StakingInterface for Pallet<T> {

impl<T: Config> sp_staking::StakingUnchecked for Pallet<T> {
fn migrate_to_virtual_staker(who: &Self::AccountId) {
T::Currency::remove_lock(crate::STAKING_ID, who);
let _ = T::Currency::release_all(&HoldReason::Staking.into(), who, Precision::BestEffort).defensive();
VirtualStakers::<T>::insert(who, ());
}

Expand Down Expand Up @@ -2097,7 +2099,7 @@ impl<T: Config> Pallet<T> {
// ensure locks consistency.
if VirtualStakers::<T>::contains_key(stash.clone()) {
ensure!(
T::Currency::balance_locked(crate::STAKING_ID, &stash) == Zero::zero(),
T::Currency::balance_on_hold(&HoldReason::Staking.into(), &stash) == Zero::zero(),
"virtual stakers should not have any locked balance"
);
ensure!(
Expand Down
63 changes: 40 additions & 23 deletions substrate/frame/staking/src/pallet/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,14 @@ use frame_election_provider_support::{
use frame_support::{
pallet_prelude::*,
traits::{
Currency, Defensive, DefensiveSaturating, EnsureOrigin, EstimateNextNewSession, Get,
InspectLockableCurrency, LockableCurrency, OnUnbalanced, UnixTime, WithdrawReasons,
fungible::{
hold::{
Balanced as FunHoldBalanced, Inspect as FunHoldInspect, Mutate as FunHoldMutate,
},
Balanced, Inspect as FunInspect, Mutate as FunMutate,
},
tokens::Precision, Defensive, DefensiveSaturating, EnsureOrigin, EstimateNextNewSession, Get,
OnUnbalanced, UnixTime, WithdrawReasons,
},
weights::Weight,
BoundedVec,
Expand Down Expand Up @@ -90,11 +96,17 @@ pub mod pallet {
pub trait Config: frame_system::Config {
/// The staking balance.
#[pallet::no_default]
type Currency: LockableCurrency<
type Currency: FunHoldMutate<
Self::AccountId,
Moment = BlockNumberFor<Self>,
Reason = Self::RuntimeHoldReason,
Balance = Self::CurrencyBalance,
> + InspectLockableCurrency<Self::AccountId>;
> + FunMutate<Self::AccountId, Balance = Self::CurrencyBalance>
+ FunHoldBalanced<Self::AccountId, Balance = Self::CurrencyBalance>;

/// Overarching hold reason.
#[pallet::no_default_bounds]
type RuntimeHoldReason: From<HoldReason>;

/// Just the `Currency::Balance` type; we have this item to allow us to constrain it to
/// `From<u64>`.
type CurrencyBalance: sp_runtime::traits::AtLeast32BitUnsigned
Expand All @@ -105,6 +117,8 @@ pub mod pallet {
+ Default
+ From<u64>
+ TypeInfo
+ Send
+ Sync
+ MaxEncodedLen;
/// Time used for computing era duration.
///
Expand Down Expand Up @@ -308,6 +322,14 @@ pub mod pallet {
type WeightInfo: WeightInfo;
}

/// A reason for placing a hold on funds.
#[pallet::composite_enum]
pub enum HoldReason {
/// Funds held for stake delegation to another account.
#[codec(index = 0)]
Staking,
}

/// Default implementations of [`DefaultConfig`], which can be used to implement [`Config`].
pub mod config_preludes {
use super::*;
Expand All @@ -326,6 +348,8 @@ pub mod pallet {
impl DefaultConfig for TestDefaultConfig {
#[inject_runtime_type]
type RuntimeEvent = ();
#[inject_runtime_type]
type RuntimeHoldReason = ();
type CurrencyBalance = u128;
type CurrencyToVote = ();
type NominationsQuota = crate::FixedNominationsQuota<16>;
Expand Down Expand Up @@ -779,7 +803,7 @@ pub mod pallet {
status
);
assert!(
T::Currency::free_balance(stash) >= balance,
T::Currency::balance(stash) >= balance,
"Stash does not have enough balance to bond."
);
frame_support::assert_ok!(<Pallet<T>>::bond(
Expand Down Expand Up @@ -1029,7 +1053,7 @@ pub mod pallet {

frame_system::Pallet::<T>::inc_consumers(&stash).map_err(|_| Error::<T>::BadState)?;

let stash_balance = T::Currency::free_balance(&stash);
let stash_balance = T::Currency::balance(&stash);
let value = value.min(stash_balance);
Self::deposit_event(Event::<T>::Bonded { stash: stash.clone(), amount: value });
let ledger = StakingLedger::<T>::new(stash.clone(), value);
Expand Down Expand Up @@ -2073,8 +2097,8 @@ pub mod pallet {
// cannot restore ledger for virtual stakers.
ensure!(!Self::is_virtual_staker(&stash), Error::<T>::VirtualStakerNotAllowed);

let current_lock = T::Currency::balance_locked(crate::STAKING_ID, &stash);
let stash_balance = T::Currency::free_balance(&stash);
let current_lock = T::Currency::balance_on_hold(&HoldReason::Staking.into(), &stash);
let stash_balance = T::Currency::balance(&stash);

let (new_controller, new_total) = match Self::inspect_bond_state(&stash) {
Ok(LedgerIntegrityState::Corrupted) => {
Expand All @@ -2083,12 +2107,7 @@ pub mod pallet {
let new_total = if let Some(total) = maybe_total {
let new_total = total.min(stash_balance);
// enforce lock == ledger.amount.
T::Currency::set_lock(
crate::STAKING_ID,
&stash,
new_total,
WithdrawReasons::all(),
);
T::Currency::set_on_hold(&HoldReason::Staking.into(), &stash, new_total)?;
new_total
} else {
current_lock
Expand All @@ -2115,18 +2134,16 @@ pub mod pallet {
// to enforce a new ledger.total and staking lock for this stash.
let new_total =
maybe_total.ok_or(Error::<T>::CannotRestoreLedger)?.min(stash_balance);
T::Currency::set_lock(
crate::STAKING_ID,
&stash,
new_total,
WithdrawReasons::all(),
);

T::Currency::set_on_hold(&HoldReason::Staking.into(), &stash, new_total)?;
Ok((stash.clone(), new_total))
},
Err(Error::<T>::BadState) => {
// the stash and ledger do not exist but lock is lingering.
T::Currency::remove_lock(crate::STAKING_ID, &stash);
T::Currency::release_all(
&HoldReason::Staking.into(),
&stash,
Precision::BestEffort,
)?;
ensure!(
Self::inspect_bond_state(&stash) == Err(Error::<T>::NotStash),
Error::<T>::BadState
Expand Down
Loading

0 comments on commit 192af84

Please sign in to comment.