difftreelog
fix unstake
in: master
2 files changed
pallets/app-promotion/src/lib.rsdiffbeforeafterboth358 let block = <frame_system::Pallet<T>>::block_number() + T::PendingInterval::get();358 let block = <frame_system::Pallet<T>>::block_number() + T::PendingInterval::get();359 let mut pendings = <PendingUnstake<T>>::get(block);359 let mut pendings = <PendingUnstake<T>>::get(block);360360361 ensure!(pendings.is_full(), Error::<T>::PendingForBlockOverflow);361 ensure!(!pendings.is_full(), Error::<T>::PendingForBlockOverflow);362362363 let mut total_stakes = 0u64;363 let mut total_stakes = 0u64;364364370 .sum();370 .sum();371371372 if total_staked.is_zero() {372 if total_staked.is_zero() {373 return Ok(None.into());373 return Ok(None.into()); // TO-DO374 }374 }375375376 pendings376 pendings387 TotalStaked::<T>::get()387 TotalStaked::<T>::get()388 .checked_sub(&total_staked)388 .checked_sub(&total_staked)389 .ok_or(ArithmeticError::Underflow)?,389 .ok_or(ArithmeticError::Underflow)?,390 ); // when error we should recover initial stake state for the staker390 );391391392 StakesPerAccount::<T>::remove(&staker_id);392 StakesPerAccount::<T>::remove(&staker_id);393393474 let next_recalc_block = current_recalc_block + T::RecalculationInterval::get();474 let next_recalc_block = current_recalc_block + T::RecalculationInterval::get();475475476 let mut storage_iterator = Self::get_next_calculated_key()476 let mut storage_iterator = Self::get_next_calculated_key()477 .map_or(Staked::<T>::iter().skip(0), |key| {477 .map_or(Staked::<T>::iter(), |key| {478 Staked::<T>::iter_from(key).skip(1)478 Staked::<T>::iter_from(key)479 });479 });480480481 NextCalculatedRecord::<T>::set(None);481 NextCalculatedRecord::<T>::set(None);482482483 {483 {484 let mut stakers_number = stakers_number.unwrap_or(20);484 let mut stakers_number = stakers_number.unwrap_or(20);485 let mut current_id = admin_id;485 let mut last_id = admin_id;486 let mut income_acc = BalanceOf::<T>::default();486 let mut income_acc = BalanceOf::<T>::default();487487488 while let Some(((id, staked_block), (amount, next_recalc_block_for_stake))) =488 while let Some(((current_id, staked_block), (amount, next_recalc_block_for_stake))) =489 storage_iterator.next()489 storage_iterator.next()490 {490 {491 if current_id != id {491 if last_id != current_id {492 if income_acc != BalanceOf::<T>::default() {492 if income_acc != BalanceOf::<T>::default() {493 <T::Currency as Currency<T::AccountId>>::transfer(493 <T::Currency as Currency<T::AccountId>>::transfer(494 &T::TreasuryAccountId::get(),494 &T::TreasuryAccountId::get(),495 ¤t_id,495 &last_id,496 income_acc,496 income_acc,497 ExistenceRequirement::KeepAlive,497 ExistenceRequirement::KeepAlive,498 )498 )499 .and_then(|_| Self::add_lock_balance(¤t_id, income_acc))?;499 .and_then(|_| Self::add_lock_balance(&last_id, income_acc))?;500500501 Self::deposit_event(Event::StakingRecalculation(501 Self::deposit_event(Event::StakingRecalculation(502 current_id, amount, income_acc,502 last_id, amount, income_acc,503 ));503 ));504 }504 }505505506 if stakers_number == 0 {506 if stakers_number == 0 {507 NextCalculatedRecord::<T>::set(Some((id, staked_block)));507 NextCalculatedRecord::<T>::set(Some((current_id, staked_block)));508 break;508 break;509 }509 }510 stakers_number -= 1;510 stakers_number -= 1;511 income_acc = BalanceOf::<T>::default();511 income_acc = BalanceOf::<T>::default();512 current_id = id;512 last_id = current_id;513 };513 };514 if current_recalc_block >= next_recalc_block_for_stake {514 if current_recalc_block >= next_recalc_block_for_stake {515 Self::recalculate_and_insert_stake(515 Self::recalculate_and_insert_stake(516 ¤t_id,516 &last_id,517 staked_block,517 staked_block,518 next_recalc_block,518 next_recalc_block,519 amount,519 amount,tests/src/app-promotion.test.tsdiffbeforeafterboth51 if (!promotionStartBlock) {51 if (!promotionStartBlock) {52 promotionStartBlock = (await helper.api!.query.parachainSystem.lastRelayChainBlockNumber()).toNumber();52 promotionStartBlock = (await helper.api!.query.parachainSystem.lastRelayChainBlockNumber()).toNumber();53 }53 }54 await helper.signTransaction(alice, helper.api!.tx.sudo.sudo(helper.api!.tx.promotion.startAppPromotion(promotionStartBlock!)));55 accounts = await helper.arrange.createCrowd(100, 1000n, alice); // create accounts-pool to speed up tests54 accounts = await helper.arrange.createCrowd(100, 1000n, alice); // create accounts-pool to speed up tests56 });55 });57});56});585759after(async function () {58after(async function () {60 await usingPlaygrounds(async (helper) => {59 await usingPlaygrounds(async (helper) => {61 await helper.signTransaction(alice, helper.api!.tx.sudo.sudo(helper.api!.tx.promotion.stopAppPromotion()));62 });60 });63});61});6462241239242 it('should be possible for different accounts in one block', async () => {240 it('should be possible for different accounts in one block', async () => {243 await usingPlaygrounds(async (helper) => {241 await usingPlaygrounds(async (helper) => {244 const stakers = [accounts.pop()!, accounts.pop()!, accounts.pop()!, accounts.pop()!, accounts.pop()!];242 const stakers = [accounts.pop()!, accounts.pop()!, accounts.pop()!];245243246 await Promise.all(stakers.map(staker => helper.staking.stake(staker, 100n * nominal)));244 await Promise.all(stakers.map(staker => helper.staking.stake(staker, 100n * nominal)));247 await Promise.all(stakers.map(staker => helper.staking.unstake(staker)));245 await Promise.all(stakers.map(staker => helper.staking.unstake(staker)));