@@ -43,6 +43,7 @@ pub use module::*;
4343
4444#[ frame_support:: pallet]
4545pub mod module {
46+
4647 use super :: * ;
4748
4849 #[ pallet:: config]
@@ -76,10 +77,14 @@ pub mod module {
7677 type Handler : RewardHandler < Self :: AccountId , Self :: CurrencyId , Balance = Self :: Balance , PoolId = Self :: PoolId > ;
7778 }
7879
80+ type WithdrawnRewards < T > = BTreeMap < <T as Config >:: CurrencyId , <T as Config >:: Balance > ;
81+
7982 #[ pallet:: error]
8083 pub enum Error < T > {
8184 /// Pool does not exist
8285 PoolDoesNotExist ,
86+ ShareDoesNotExist ,
87+ CanSplitOnlyLessThanShare ,
8388 }
8489
8590 /// Record reward pool info.
@@ -102,7 +107,7 @@ pub mod module {
102107 T :: PoolId ,
103108 Twox64Concat ,
104109 T :: AccountId ,
105- ( T :: Share , BTreeMap < T :: CurrencyId , T :: Balance > ) ,
110+ ( T :: Share , WithdrawnRewards < T > ) ,
106111 ValueQuery ,
107112 > ;
108113
@@ -316,6 +321,51 @@ impl<T: Config> Pallet<T> {
316321 } ) ;
317322 }
318323
324+ /// Splits share into two parts.
325+ ///
326+ /// `move_share` - amount of share to remove and put into `other` share
327+ /// `other` - new account who will own new share
328+ ///
329+ /// Similar too claim and add 2 shares later, but does not requires pool
330+ /// inflation and is more efficient.
331+ pub fn transfer_share_and_rewards (
332+ who : & T :: AccountId ,
333+ pool : & T :: PoolId ,
334+ move_share : T :: Share ,
335+ other : & T :: AccountId ,
336+ ) -> DispatchResult {
337+ SharesAndWithdrawnRewards :: < T > :: mutate ( pool, other, |increased_share| {
338+ let ( increased_share, increased_rewards) = increased_share;
339+ SharesAndWithdrawnRewards :: < T > :: mutate_exists ( pool, who, |share| {
340+ let ( share, rewards) = share. as_mut ( ) . ok_or ( Error :: < T > :: ShareDoesNotExist ) ?;
341+ ensure ! ( move_share < * share, Error :: <T >:: CanSplitOnlyLessThanShare ) ;
342+ for ( reward_currency, balance) in rewards {
343+ // u128 * u128 is always less than u256
344+ // move_share / share always less then 1 and share > 0
345+ // so final results is computable and is always less or equal than u128
346+ let move_balance = U256 :: from ( balance. to_owned ( ) . saturated_into :: < u128 > ( ) )
347+ * U256 :: from ( move_share. to_owned ( ) . saturated_into :: < u128 > ( ) )
348+ / U256 :: from ( share. to_owned ( ) . saturated_into :: < u128 > ( ) ) ;
349+ let move_balance: Option < u128 > = move_balance. try_into ( ) . ok ( ) ;
350+ if let Some ( move_balance) = move_balance {
351+ let move_balance: T :: Balance = move_balance. unique_saturated_into ( ) ;
352+ * balance = balance. saturating_sub ( move_balance) ;
353+ increased_rewards
354+ . entry ( * reward_currency)
355+ . and_modify ( |increased_reward| {
356+ * increased_reward = increased_reward. saturating_add ( move_balance) ;
357+ } )
358+ . or_insert ( move_balance) ;
359+ }
360+ }
361+ * share = share. saturating_sub ( move_share) ;
362+ * increased_share = increased_share. saturating_add ( move_share) ;
363+ Ok ( ( ) )
364+ } )
365+ } )
366+ }
367+
368+ #[ allow( clippy:: too_many_arguments) ] // just we need to have all these to do the stuff
319369 fn claim_one (
320370 withdrawn_rewards : & mut BTreeMap < T :: CurrencyId , T :: Balance > ,
321371 reward_currency : T :: CurrencyId ,
0 commit comments