Skip to content

Commit

Permalink
dApp Staking v3 - Legacy Ledger Support (#1120)
Browse files Browse the repository at this point in the history
* dApp Staking v3 - Legacy Ledger Support

* Doc fix

* Tests
  • Loading branch information
Dinonard authored Jan 3, 2024
1 parent 7be5270 commit 1fa3c7b
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 13 deletions.
50 changes: 37 additions & 13 deletions pallets/dapp-staking-v3/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,30 @@ pub mod pallet {

#[pallet::call]
impl<T: Config> Pallet<T> {
/// Wrapper around _legacy-like_ `unbond_and_unstake`.
///
/// Used to support legacy Ledger users so they can start the unlocking process for their funds.
#[pallet::call_index(4)]
#[pallet::weight(T::WeightInfo::unlock())]
pub fn unbond_and_unstake(
origin: OriginFor<T>,
_contract_id: T::SmartContract,
#[pallet::compact] value: Balance,
) -> DispatchResult {
// Once new period begins, all stakes are reset to zero, so all it remains to be done is the `unlock`
Self::unlock(origin, value)
}

/// Wrapper around _legacy-like_ `withdraw_unbonded`.
///
/// Used to support legacy Ledger users so they can reclaim unlocked chunks back into
/// their _transferable_ free balance.
#[pallet::call_index(5)]
#[pallet::weight(T::WeightInfo::claim_unlocked(T::MaxNumberOfStakedContracts::get()))]
pub fn withdraw_unbonded(origin: OriginFor<T>) -> DispatchResultWithPostInfo {
Self::claim_unlocked(origin)
}

/// Used to enable or disable maintenance mode.
/// Can only be called by manager origin.
#[pallet::call_index(0)]
Expand Down Expand Up @@ -706,7 +730,7 @@ pub mod pallet {
/// This doesn't remove the dApp completely from the system just yet, but it can no longer be used for staking.
///
/// Can be called by dApp staking manager origin.
#[pallet::call_index(4)]
#[pallet::call_index(6)]
#[pallet::weight(T::WeightInfo::unregister())]
pub fn unregister(
origin: OriginFor<T>,
Expand Down Expand Up @@ -744,7 +768,7 @@ pub mod pallet {
/// After adjustment, lock amount must be greater than zero and in total must be equal or greater than the minimum locked amount.
///
/// Locked amount can immediately be used for staking.
#[pallet::call_index(5)]
#[pallet::call_index(7)]
#[pallet::weight(T::WeightInfo::lock())]
pub fn lock(origin: OriginFor<T>, #[pallet::compact] amount: Balance) -> DispatchResult {
Self::ensure_pallet_enabled()?;
Expand Down Expand Up @@ -783,7 +807,7 @@ pub mod pallet {
/// Only the amount that isn't actively used for staking can be unlocked.
/// If the amount is greater than the available amount for unlocking, everything is unlocked.
/// If the remaining locked amount would take the account below the minimum locked amount, everything is unlocked.
#[pallet::call_index(6)]
#[pallet::call_index(8)]
#[pallet::weight(T::WeightInfo::unlock())]
pub fn unlock(origin: OriginFor<T>, #[pallet::compact] amount: Balance) -> DispatchResult {
Self::ensure_pallet_enabled()?;
Expand Down Expand Up @@ -836,7 +860,7 @@ pub mod pallet {
}

/// Claims all of fully unlocked chunks, removing the lock from them.
#[pallet::call_index(7)]
#[pallet::call_index(9)]
#[pallet::weight(T::WeightInfo::claim_unlocked(T::MaxNumberOfStakedContracts::get()))]
pub fn claim_unlocked(origin: OriginFor<T>) -> DispatchResultWithPostInfo {
Self::ensure_pallet_enabled()?;
Expand Down Expand Up @@ -866,7 +890,7 @@ pub mod pallet {
Ok(Some(T::WeightInfo::claim_unlocked(removed_entries)).into())
}

#[pallet::call_index(8)]
#[pallet::call_index(10)]
#[pallet::weight(T::WeightInfo::relock_unlocking())]
pub fn relock_unlocking(origin: OriginFor<T>) -> DispatchResult {
Self::ensure_pallet_enabled()?;
Expand Down Expand Up @@ -903,7 +927,7 @@ pub mod pallet {
/// and same for `Build&Earn` subperiod.
///
/// Staked amount is only eligible for rewards from the next era onwards.
#[pallet::call_index(9)]
#[pallet::call_index(11)]
#[pallet::weight(T::WeightInfo::stake())]
pub fn stake(
origin: OriginFor<T>,
Expand Down Expand Up @@ -1030,7 +1054,7 @@ pub mod pallet {
/// In case amount is unstaked during `Voting` subperiod, the `voting` amount is reduced.
/// In case amount is unstaked during `Build&Earn` subperiod, first the `build_and_earn` is reduced,
/// and any spillover is subtracted from the `voting` amount.
#[pallet::call_index(10)]
#[pallet::call_index(12)]
#[pallet::weight(T::WeightInfo::unstake())]
pub fn unstake(
origin: OriginFor<T>,
Expand Down Expand Up @@ -1132,7 +1156,7 @@ pub mod pallet {

/// Claims some staker rewards, if user has any.
/// In the case of a successfull call, at least one era will be claimed, with the possibility of multiple claims happening.
#[pallet::call_index(11)]
#[pallet::call_index(13)]
#[pallet::weight({
let max_span_length = T::EraRewardSpanLength::get();
T::WeightInfo::claim_staker_rewards_ongoing_period(max_span_length)
Expand Down Expand Up @@ -1226,7 +1250,7 @@ pub mod pallet {
}

/// Used to claim bonus reward for a smart contract, if eligible.
#[pallet::call_index(12)]
#[pallet::call_index(14)]
#[pallet::weight(T::WeightInfo::claim_bonus_reward())]
pub fn claim_bonus_reward(
origin: OriginFor<T>,
Expand Down Expand Up @@ -1291,7 +1315,7 @@ pub mod pallet {
}

/// Used to claim dApp reward for the specified era.
#[pallet::call_index(13)]
#[pallet::call_index(15)]
#[pallet::weight(T::WeightInfo::claim_dapp_reward())]
pub fn claim_dapp_reward(
origin: OriginFor<T>,
Expand Down Expand Up @@ -1347,7 +1371,7 @@ pub mod pallet {

/// Used to unstake funds from a contract that was unregistered after an account staked on it.
/// This is required if staker wants to re-stake these funds on another active contract during the ongoing period.
#[pallet::call_index(14)]
#[pallet::call_index(16)]
#[pallet::weight(T::WeightInfo::unstake_from_unregistered())]
pub fn unstake_from_unregistered(
origin: OriginFor<T>,
Expand Down Expand Up @@ -1416,7 +1440,7 @@ pub mod pallet {
/// Entry is considered to be expired if:
/// 1. It's from a past period & the account wasn't a loyal staker, meaning there's no claimable bonus reward.
/// 2. It's from a period older than the oldest claimable period, regardless whether the account was loyal or not.
#[pallet::call_index(15)]
#[pallet::call_index(17)]
#[pallet::weight(T::WeightInfo::cleanup_expired_entries(
T::MaxNumberOfStakedContracts::get()
))]
Expand Down Expand Up @@ -1481,7 +1505,7 @@ pub mod pallet {
/// Not intended to be used in production, except in case of unforseen circumstances.
///
/// Can only be called by manager origin.
#[pallet::call_index(16)]
#[pallet::call_index(18)]
#[pallet::weight(T::WeightInfo::force())]
pub fn force(origin: OriginFor<T>, forcing_type: ForcingType) -> DispatchResult {
Self::ensure_pallet_enabled()?;
Expand Down
58 changes: 58 additions & 0 deletions pallets/dapp-staking-v3/src/test/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,18 @@ fn maintenace_mode_call_filtering_works() {
DappStaking::force(RuntimeOrigin::root(), ForcingType::Era),
Error::<Test>::Disabled
);
assert_noop!(
DappStaking::unbond_and_unstake(
RuntimeOrigin::signed(1),
MockSmartContract::wasm(1 as AccountId),
100
),
Error::<Test>::Disabled
);
assert_noop!(
DappStaking::withdraw_unbonded(RuntimeOrigin::signed(1),),
Error::<Test>::Disabled
);
})
}

Expand Down Expand Up @@ -503,6 +515,29 @@ fn lock_with_incorrect_amount_fails() {
})
}

#[test]
fn unbond_and_unstake_is_ok() {
ExtBuilder::build().execute_with(|| {
// Lock some amount
let account = 2;
let lock_amount = 101;
assert_lock(account, lock_amount);

// 'unbond_and_unstake' some amount, assert expected event is emitted
let unlock_amount = 19;
let dummy_smart_contract = MockSmartContract::Wasm(1);
assert_ok!(DappStaking::unbond_and_unstake(
RuntimeOrigin::signed(account),
dummy_smart_contract,
unlock_amount
));
System::assert_last_event(RuntimeEvent::DappStaking(Event::Unlocking {
account,
amount: unlock_amount,
}));
})
}

#[test]
fn unlock_basic_example_is_ok() {
ExtBuilder::build().execute_with(|| {
Expand Down Expand Up @@ -682,6 +717,29 @@ fn unlock_with_exceeding_unlocking_chunks_storage_limits_fails() {
})
}

#[test]
fn withdraw_unbonded_is_ok() {
ExtBuilder::build().execute_with(|| {
// Lock & immediatelly unlock some amount
let account = 2;
let lock_amount = 97;
let unlock_amount = 11;
assert_lock(account, lock_amount);
assert_unlock(account, unlock_amount);

// Run for enough blocks so the chunk becomes claimable
let unlocking_blocks = DappStaking::unlocking_period();
run_for_blocks(unlocking_blocks);
assert_ok!(DappStaking::withdraw_unbonded(RuntimeOrigin::signed(
account
)));
System::assert_last_event(RuntimeEvent::DappStaking(Event::ClaimedUnlocked {
account,
amount: unlock_amount,
}));
})
}

#[test]
fn claim_unlocked_is_ok() {
ExtBuilder::build().execute_with(|| {
Expand Down

0 comments on commit 1fa3c7b

Please sign in to comment.