Skip to content

Commit 1fa3c7b

Browse files
authored
dApp Staking v3 - Legacy Ledger Support (#1120)
* dApp Staking v3 - Legacy Ledger Support * Doc fix * Tests
1 parent 7be5270 commit 1fa3c7b

File tree

2 files changed

+95
-13
lines changed

2 files changed

+95
-13
lines changed

pallets/dapp-staking-v3/src/lib.rs

+37-13
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,30 @@ pub mod pallet {
561561

562562
#[pallet::call]
563563
impl<T: Config> Pallet<T> {
564+
/// Wrapper around _legacy-like_ `unbond_and_unstake`.
565+
///
566+
/// Used to support legacy Ledger users so they can start the unlocking process for their funds.
567+
#[pallet::call_index(4)]
568+
#[pallet::weight(T::WeightInfo::unlock())]
569+
pub fn unbond_and_unstake(
570+
origin: OriginFor<T>,
571+
_contract_id: T::SmartContract,
572+
#[pallet::compact] value: Balance,
573+
) -> DispatchResult {
574+
// Once new period begins, all stakes are reset to zero, so all it remains to be done is the `unlock`
575+
Self::unlock(origin, value)
576+
}
577+
578+
/// Wrapper around _legacy-like_ `withdraw_unbonded`.
579+
///
580+
/// Used to support legacy Ledger users so they can reclaim unlocked chunks back into
581+
/// their _transferable_ free balance.
582+
#[pallet::call_index(5)]
583+
#[pallet::weight(T::WeightInfo::claim_unlocked(T::MaxNumberOfStakedContracts::get()))]
584+
pub fn withdraw_unbonded(origin: OriginFor<T>) -> DispatchResultWithPostInfo {
585+
Self::claim_unlocked(origin)
586+
}
587+
564588
/// Used to enable or disable maintenance mode.
565589
/// Can only be called by manager origin.
566590
#[pallet::call_index(0)]
@@ -706,7 +730,7 @@ pub mod pallet {
706730
/// This doesn't remove the dApp completely from the system just yet, but it can no longer be used for staking.
707731
///
708732
/// Can be called by dApp staking manager origin.
709-
#[pallet::call_index(4)]
733+
#[pallet::call_index(6)]
710734
#[pallet::weight(T::WeightInfo::unregister())]
711735
pub fn unregister(
712736
origin: OriginFor<T>,
@@ -744,7 +768,7 @@ pub mod pallet {
744768
/// After adjustment, lock amount must be greater than zero and in total must be equal or greater than the minimum locked amount.
745769
///
746770
/// Locked amount can immediately be used for staking.
747-
#[pallet::call_index(5)]
771+
#[pallet::call_index(7)]
748772
#[pallet::weight(T::WeightInfo::lock())]
749773
pub fn lock(origin: OriginFor<T>, #[pallet::compact] amount: Balance) -> DispatchResult {
750774
Self::ensure_pallet_enabled()?;
@@ -783,7 +807,7 @@ pub mod pallet {
783807
/// Only the amount that isn't actively used for staking can be unlocked.
784808
/// If the amount is greater than the available amount for unlocking, everything is unlocked.
785809
/// If the remaining locked amount would take the account below the minimum locked amount, everything is unlocked.
786-
#[pallet::call_index(6)]
810+
#[pallet::call_index(8)]
787811
#[pallet::weight(T::WeightInfo::unlock())]
788812
pub fn unlock(origin: OriginFor<T>, #[pallet::compact] amount: Balance) -> DispatchResult {
789813
Self::ensure_pallet_enabled()?;
@@ -836,7 +860,7 @@ pub mod pallet {
836860
}
837861

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

869-
#[pallet::call_index(8)]
893+
#[pallet::call_index(10)]
870894
#[pallet::weight(T::WeightInfo::relock_unlocking())]
871895
pub fn relock_unlocking(origin: OriginFor<T>) -> DispatchResult {
872896
Self::ensure_pallet_enabled()?;
@@ -903,7 +927,7 @@ pub mod pallet {
903927
/// and same for `Build&Earn` subperiod.
904928
///
905929
/// Staked amount is only eligible for rewards from the next era onwards.
906-
#[pallet::call_index(9)]
930+
#[pallet::call_index(11)]
907931
#[pallet::weight(T::WeightInfo::stake())]
908932
pub fn stake(
909933
origin: OriginFor<T>,
@@ -1030,7 +1054,7 @@ pub mod pallet {
10301054
/// In case amount is unstaked during `Voting` subperiod, the `voting` amount is reduced.
10311055
/// In case amount is unstaked during `Build&Earn` subperiod, first the `build_and_earn` is reduced,
10321056
/// and any spillover is subtracted from the `voting` amount.
1033-
#[pallet::call_index(10)]
1057+
#[pallet::call_index(12)]
10341058
#[pallet::weight(T::WeightInfo::unstake())]
10351059
pub fn unstake(
10361060
origin: OriginFor<T>,
@@ -1132,7 +1156,7 @@ pub mod pallet {
11321156

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

12281252
/// Used to claim bonus reward for a smart contract, if eligible.
1229-
#[pallet::call_index(12)]
1253+
#[pallet::call_index(14)]
12301254
#[pallet::weight(T::WeightInfo::claim_bonus_reward())]
12311255
pub fn claim_bonus_reward(
12321256
origin: OriginFor<T>,
@@ -1291,7 +1315,7 @@ pub mod pallet {
12911315
}
12921316

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

13481372
/// Used to unstake funds from a contract that was unregistered after an account staked on it.
13491373
/// This is required if staker wants to re-stake these funds on another active contract during the ongoing period.
1350-
#[pallet::call_index(14)]
1374+
#[pallet::call_index(16)]
13511375
#[pallet::weight(T::WeightInfo::unstake_from_unregistered())]
13521376
pub fn unstake_from_unregistered(
13531377
origin: OriginFor<T>,
@@ -1416,7 +1440,7 @@ pub mod pallet {
14161440
/// Entry is considered to be expired if:
14171441
/// 1. It's from a past period & the account wasn't a loyal staker, meaning there's no claimable bonus reward.
14181442
/// 2. It's from a period older than the oldest claimable period, regardless whether the account was loyal or not.
1419-
#[pallet::call_index(15)]
1443+
#[pallet::call_index(17)]
14201444
#[pallet::weight(T::WeightInfo::cleanup_expired_entries(
14211445
T::MaxNumberOfStakedContracts::get()
14221446
))]
@@ -1481,7 +1505,7 @@ pub mod pallet {
14811505
/// Not intended to be used in production, except in case of unforseen circumstances.
14821506
///
14831507
/// Can only be called by manager origin.
1484-
#[pallet::call_index(16)]
1508+
#[pallet::call_index(18)]
14851509
#[pallet::weight(T::WeightInfo::force())]
14861510
pub fn force(origin: OriginFor<T>, forcing_type: ForcingType) -> DispatchResult {
14871511
Self::ensure_pallet_enabled()?;

pallets/dapp-staking-v3/src/test/tests.rs

+58
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,18 @@ fn maintenace_mode_call_filtering_works() {
156156
DappStaking::force(RuntimeOrigin::root(), ForcingType::Era),
157157
Error::<Test>::Disabled
158158
);
159+
assert_noop!(
160+
DappStaking::unbond_and_unstake(
161+
RuntimeOrigin::signed(1),
162+
MockSmartContract::wasm(1 as AccountId),
163+
100
164+
),
165+
Error::<Test>::Disabled
166+
);
167+
assert_noop!(
168+
DappStaking::withdraw_unbonded(RuntimeOrigin::signed(1),),
169+
Error::<Test>::Disabled
170+
);
159171
})
160172
}
161173

@@ -503,6 +515,29 @@ fn lock_with_incorrect_amount_fails() {
503515
})
504516
}
505517

518+
#[test]
519+
fn unbond_and_unstake_is_ok() {
520+
ExtBuilder::build().execute_with(|| {
521+
// Lock some amount
522+
let account = 2;
523+
let lock_amount = 101;
524+
assert_lock(account, lock_amount);
525+
526+
// 'unbond_and_unstake' some amount, assert expected event is emitted
527+
let unlock_amount = 19;
528+
let dummy_smart_contract = MockSmartContract::Wasm(1);
529+
assert_ok!(DappStaking::unbond_and_unstake(
530+
RuntimeOrigin::signed(account),
531+
dummy_smart_contract,
532+
unlock_amount
533+
));
534+
System::assert_last_event(RuntimeEvent::DappStaking(Event::Unlocking {
535+
account,
536+
amount: unlock_amount,
537+
}));
538+
})
539+
}
540+
506541
#[test]
507542
fn unlock_basic_example_is_ok() {
508543
ExtBuilder::build().execute_with(|| {
@@ -682,6 +717,29 @@ fn unlock_with_exceeding_unlocking_chunks_storage_limits_fails() {
682717
})
683718
}
684719

720+
#[test]
721+
fn withdraw_unbonded_is_ok() {
722+
ExtBuilder::build().execute_with(|| {
723+
// Lock & immediatelly unlock some amount
724+
let account = 2;
725+
let lock_amount = 97;
726+
let unlock_amount = 11;
727+
assert_lock(account, lock_amount);
728+
assert_unlock(account, unlock_amount);
729+
730+
// Run for enough blocks so the chunk becomes claimable
731+
let unlocking_blocks = DappStaking::unlocking_period();
732+
run_for_blocks(unlocking_blocks);
733+
assert_ok!(DappStaking::withdraw_unbonded(RuntimeOrigin::signed(
734+
account
735+
)));
736+
System::assert_last_event(RuntimeEvent::DappStaking(Event::ClaimedUnlocked {
737+
account,
738+
amount: unlock_amount,
739+
}));
740+
})
741+
}
742+
685743
#[test]
686744
fn claim_unlocked_is_ok() {
687745
ExtBuilder::build().execute_with(|| {

0 commit comments

Comments
 (0)