fn remove_stake(
			&mut self,
			user: &mut UserStakeInfo<AccountId, Balance>,
			shares: Balance,
		) -> Option<(Balance, Balance)> {
			debug_assert!(is_nondust_balance(shares));
			self.assert_slash_clean(user);
			self.assert_reward_clean(user);

			// It's tricky to deal with the fixed point precision loss. Generally we drop the dust
			// shares, because shares are just a virtual value representing the ownership of a
			// pool. However for balances, even the dust of 1 pico PHA must be absorbed.
			//
			// In StakePool, all the balances are PHA locked in user's account. Therefore once we
			// want to absorb some dust, we have to withdraw the funds from the users' stake, and
			// deposit it to the Treasury.
			let price = self.share_price()?;
			let amount = bmul(shares, &price);
			// In case `amount` is a little bit larger than `free_stake`. It also implies that
			// amount will never exceed user.stake.
			let amount = amount.min(self.free_stake);
			// Remove shares and stake from the user record
			let user_shares = user.shares.checked_sub(&shares)?;
			let (user_shares, shares_dust) = extract_dust(user_shares);
			let user_locked = user.locked.checked_sub(&amount)?;
			let (user_locked, user_dust) = extract_dust(user_locked);
			// Whenver we remove dust shares in user's account, we remove it in the total_shares
			// as well. It keeps the invariant:
			//   pool.total_shares == sum(pool_user.shares)
			let total_shares = self.total_shares.checked_sub(&(shares + shares_dust))?;
			debug_assert!(
				extract_dust(total_shares).1 == Zero::zero(),
				"total_shares should never have dust"
			);
			// Apply updates
			//
			// Note that ideally we should maintain the invariant:
			//   pool.total_stake == sum(pool_user.stake)
			//
			// When we extracted some dust, we should also deduct it from the total_stake. However,
			// the invarant will be broken anyway when a pool got any slash settled. For example,
			// when the total stake got slashed by 1 pico-PHA, the sum of pool users' stake will
			// be always larger than total_stake.
			//
			// So we'd rather just don't deduct the the removed dust at all. Instead, we drop the
			// dust in pool.total_stake after the user stake is removed. In other words, we always
			// drop the dust in total_stake without more bookkeeping.
			let (total_stake, _) = extract_dust(self.total_stake - amount);
			if total_stake > Zero::zero() {
				self.free_stake -= amount;
				self.total_stake -= amount;
			} else {
				self.free_stake = Zero::zero();
				self.total_stake = Zero::zero();
			}
			self.total_shares = total_shares;
			user.shares = user_shares;
			user.locked = user_locked;
			self.reset_pending_reward(user);
			Some((amount, user_dust))
		}
/// Removes some shares from a user and returns the removed stake amount.
///
/// This function can deal with fixed point precision issue (I hope so). However it also
/// requires:
///
/// - There's no dirty slash
/// - `shares` mustn't exceed the user shares.
///
/// It returns `None` and makes no change if there's any error. Otherwise it returns a
/// tuple with the amount of the actual removed stake, and potentially the dust stake to
/// remove.
Removes some shares from a user and returns the removed stake amount.
This function can deal with fixed point precision issue (I hope so). However it also
requires.

There's no dirty slash
`shares` mustn't exceed the user shares.

It returns `None` and makes no change if there's any error. Otherwise it returns a
tuple with the amount of the actual removed stake, and potentially the dust stake to
remove.
Removes some shares from a user and returns the removed stake amount . This function can deal with fixed point precision issue ( I hope so ) . However it also requires . There ' s no dirty slash ` shares ` mustn ' t exceed the user shares . It returns ` None ` and makes no change if there ' s any error . Otherwise it returns a tuple with the amount of the actual removed stake and potentially the dust stake to remove .
fn remove_stake(
			&mut self,
			user: &mut UserStakeInfo<AccountId, Balance>,
			shares: Balance,
		) -> Option<(Balance, Balance)> {
			debug_assert!(is_nondust_balance(shares));
			self.assert_slash_clean(user);
			self.assert_reward_clean(user);
			// It's tricky to deal with the fixed point precision loss. Generally we drop the dust
			// shares, because shares are just a virtual value representing the ownership of a
			// pool. However for balances, even the dust of 1 pico PHA must be absorbed.
			//
			// In StakePool, all the balances are PHA locked in user's account. Therefore once we
			// want to absorb some dust, we have to withdraw the funds from the users' stake, and
			// deposit it to the Treasury.
			let price = self.share_price()?;
			let amount = bmul(shares, &price);
			// In case `amount` is a little bit larger than `free_stake`. It also implies that
			// amount will never exceed user.stake.
			let amount = amount.min(self.free_stake);
			// Remove shares and stake from the user record
			let user_shares = user.shares.checked_sub(&shares)?;
			let (user_shares, shares_dust) = extract_dust(user_shares);
			let user_locked = user.locked.checked_sub(&amount)?;
			let (user_locked, user_dust) = extract_dust(user_locked);
			// Whenver we remove dust shares in user's account, we remove it in the total_shares
			// as well. It keeps the invariant:
			//   pool.total_shares == sum(pool_user.shares)
			let total_shares = self.total_shares.checked_sub(&(shares + shares_dust))?;
			debug_assert!(
				extract_dust(total_shares).1 == Zero::zero(),
				"total_shares should never have dust"
			);
			// Apply updates
			//
			// Note that ideally we should maintain the invariant:
			//   pool.total_stake == sum(pool_user.stake)
			//
			// When we extracted some dust, we should also deduct it from the total_stake. However,
			// the invarant will be broken anyway when a pool got any slash settled. For example,
			// when the total stake got slashed by 1 pico-PHA, the sum of pool users' stake will
			// be always larger than total_stake.
			//
			// So we'd rather just don't deduct the the removed dust at all. Instead, we drop the
			// dust in pool.total_stake after the user stake is removed. In other words, we always
			// drop the dust in total_stake without more bookkeeping.
			let (total_stake, _) = extract_dust(self.total_stake - amount);
			if total_stake > Zero::zero() {
				self.free_stake -= amount;
				self.total_stake -= amount;
			} else {
				self.free_stake = Zero::zero();
				self.total_stake = Zero::zero();
			}
			self.total_shares = total_shares;
			user.shares = user_shares;
			user.locked = user_locked;
			self.reset_pending_reward(user);
			Some((amount, user_dust))
		}
fn remove_stake ( & mut self , user : & mut UserStakeInfo < AccountId , Balance > , shares : Balance , ) -> Option < ( Balance , Balance ) > { debug_assert ! ( is_nondust_balance ( shares ) ) ; self . assert_slash_clean ( user ) ; self . assert_reward_clean ( user ) ; // It's tricky to deal with the fixed point precision loss. Generally we drop the dust // shares, because shares are just a virtual value representing the ownership of a // pool. However for balances, even the dust of 1 pico PHA must be absorbed. // // In StakePool, all the balances are PHA locked in user's account. Therefore once we // want to absorb some dust, we have to withdraw the funds from the users' stake, and // deposit it to the Treasury. let price = self . share_price ( ) ? ; let amount = bmul ( shares , & price ) ; // In case `amount` is a little bit larger than `free_stake`. It also implies that // amount will never exceed user.stake. let amount = amount . min ( self . free_stake ) ; // Remove shares and stake from the user record let user_shares = user . shares . checked_sub ( & shares ) ? ; let ( user_shares , shares_dust ) = extract_dust ( user_shares ) ; let user_locked = user . locked . checked_sub ( & amount ) ? ; let ( user_locked , user_dust ) = extract_dust ( user_locked ) ; // Whenver we remove dust shares in user's account, we remove it in the total_shares // as well. It keeps the invariant: //   pool.total_shares == sum(pool_user.shares) let total_shares = self . total_shares . checked_sub ( & ( shares + shares_dust ) ) ? ; debug_assert ! ( extract_dust ( total_shares ) 1 Zero zero ( ) " " ) ; // Apply updates // // Note that ideally we should maintain the invariant: //   pool.total_stake == sum(pool_user.stake) // // When we extracted some dust, we should also deduct it from the total_stake. However, // the invarant will be broken anyway when a pool got any slash settled. For example, // when the total stake got slashed by 1 pico-PHA, the sum of pool users' stake will // be always larger than total_stake. // // So we'd rather just don't deduct the the removed dust at all. Instead, we drop the // dust in pool.total_stake after the user stake is removed. In other words, we always // drop the dust in total_stake without more bookkeeping. let ( total_stake , _ ) = extract_dust ( self . total_stake - amount ) ; if total_stake > Zero :: zero ( ) { self . free_stake -= amount ; self . total_stake -= amount ; } else { self . free_stake = Zero :: zero ( ) ; self . total_stake = Zero :: zero ( ) ; } self . total_shares = total_shares ; user . shares = user_shares ; user . locked = user_locked ; self . reset_pending_reward ( user ) ; Some ( ( amount , user_dust ) ) }
Removes some shares from a user and returns the removed stake amount.
Removes some shares from a user and returns the removed stake amount .
&mut self
user
&mut UserStakeInfo<AccountId, Balance>
shares
Balance
&mut self
user
&mut UserStakeInfo<AccountId, Balance>
shares
Balance