11use crate :: * ;
22use primitives:: TruncateFixedPointToInt ;
3- use std:: collections:: BTreeMap ;
3+ use std:: collections:: { BTreeMap , HashMap } ;
44
55pub type StakeId = ( VaultId , AccountId ) ;
66
@@ -10,7 +10,7 @@ pub struct IdealRewardPool {
1010 secure_threshold : BTreeMap < VaultId , FixedU128 > ,
1111 accept_new_issues : BTreeMap < VaultId , bool > ,
1212 commission : BTreeMap < VaultId , FixedU128 > ,
13- collateral : BTreeMap < StakeId , u128 > ,
13+ collateral : BTreeMap < StakeId , FixedU128 > ,
1414 rewards : BTreeMap < AccountId , ( FixedU128 , FixedU128 ) > ,
1515}
1616
@@ -36,27 +36,33 @@ impl IdealRewardPool {
3636 pub fn deposit_nominator_collateral ( & mut self , account : & StakeId , amount : u128 ) -> & mut Self {
3737 log:: debug!( "deposit_nominator_collateral {amount}" ) ;
3838 let current_collateral = self . collateral . get ( account) . map ( |x| * x) . unwrap_or_default ( ) ;
39- self . collateral . insert ( account. clone ( ) , current_collateral + amount) ;
39+ self . collateral
40+ . insert ( account. clone ( ) , current_collateral + FixedU128 :: from ( amount) ) ;
4041 self
4142 }
4243
4344 pub fn withdraw_nominator_collateral ( & mut self , account : & StakeId , amount : u128 ) -> & mut Self {
4445 log:: debug!( "withdraw_nominator_collateral {amount}" ) ;
4546 let current_collateral = self . collateral . get ( account) . map ( |x| * x) . unwrap_or_default ( ) ;
46- self . collateral . insert ( account. clone ( ) , current_collateral - amount) ;
47+ self . collateral
48+ . insert ( account. clone ( ) , current_collateral - FixedU128 :: from ( amount) ) ;
4749 self
4850 }
4951
5052 pub fn slash_collateral ( & mut self , account : & VaultId , amount : u128 ) -> & mut Self {
5153 log:: error!( "slash_collateral {amount}" ) ;
54+ let amount = FixedU128 :: from ( amount) ;
5255 let nominators: Vec < _ > = {
5356 self . collateral
5457 . iter ( )
5558 . filter ( |( ( vault, _nominator) , _stake) | vault == account)
5659 . map ( |( key, value) | ( key. clone ( ) , value. clone ( ) ) )
5760 . collect ( )
5861 } ;
59- let total_stake: u128 = nominators. iter ( ) . map ( |( _key, value) | * value) . sum ( ) ;
62+ let total_stake: FixedU128 = nominators
63+ . iter ( )
64+ . map ( |( _key, value) | * value)
65+ . fold ( Zero :: zero ( ) , |x : FixedU128 , y : FixedU128 | x + y) ;
6066 for ( key, stake) in nominators {
6167 let new_stake = stake - ( stake * amount) / total_stake;
6268 self . collateral . insert ( key, new_stake) ;
@@ -77,26 +83,91 @@ impl IdealRewardPool {
7783 return self ;
7884 }
7985
80- for ( stake_id, _) in self . collateral . iter ( ) {
81- let stake = self . stake ( stake_id) ;
82- let reward = ( stake * reward) / total_stake;
83-
84- let ( vault_id, nominator_id) = stake_id;
85-
86- let commission = self . commission . get ( vault_id) . cloned ( ) . unwrap_or_default ( ) ;
87-
88- let ( vault_commission, vault_reward) = self . rewards . get ( & vault_id. account_id ) . cloned ( ) . unwrap_or_default ( ) ;
89- self . rewards . insert (
90- vault_id. account_id . clone ( ) ,
91- ( vault_commission + reward * commission, vault_reward) ,
92- ) ;
93-
94- let ( nominator_commission, nominator_reward) = self . rewards . get ( & nominator_id) . cloned ( ) . unwrap_or_default ( ) ;
95- self . rewards . insert (
96- nominator_id. clone ( ) ,
97- ( nominator_commission, nominator_reward + ( reward - reward * commission) ) ,
98- ) ;
86+ let vault_stakes: HashMap < _ , _ > = self
87+ . collateral
88+ . iter ( )
89+ . map ( |( ( vault, _nominator) , collateral) | ( vault, collateral) )
90+ . filter ( |( vault, _) | * self . accept_new_issues . get ( vault) . unwrap_or ( & true ) )
91+ . into_group_map ( )
92+ . into_iter ( )
93+ . map ( |( vault, nominator_collaterals) | {
94+ let vault_collateral = nominator_collaterals
95+ . into_iter ( )
96+ . cloned ( )
97+ . fold ( Zero :: zero ( ) , |x : FixedU128 , y : FixedU128 | x + y) ;
98+ let threshold = self . secure_threshold [ vault] ;
99+ let reward_stake = ( vault_collateral / threshold) . truncate_to_inner ( ) . unwrap ( ) ;
100+ ( vault, reward_stake)
101+ } )
102+ . collect ( ) ;
103+
104+ let capacity_stakes: Vec < _ > = vault_stakes
105+ . iter ( )
106+ . map ( |( vault, stake) | ( vault. collateral_currency ( ) , stake) )
107+ . into_group_map ( )
108+ . into_iter ( )
109+ . map ( |( currency, vault_stakes) | {
110+ let currency_capacity: u128 = vault_stakes. into_iter ( ) . sum ( ) ;
111+ let exchange_rate = self . exchange_rate [ & currency] ;
112+ let capacity_stake = ( FixedU128 :: from ( currency_capacity) / exchange_rate)
113+ . truncate_to_inner ( )
114+ . unwrap ( ) ;
115+ ( currency, capacity_stake)
116+ } )
117+ . collect ( ) ;
118+
119+ log:: error!( "Capacity_stakes: {capacity_stakes:?}" ) ;
120+
121+ let total_capacity: u128 = capacity_stakes. iter ( ) . map ( |( _, capacity) | capacity) . sum ( ) ;
122+ for ( currency, capacity_stake) in capacity_stakes {
123+ let currency_reward = ( reward * FixedU128 :: from ( capacity_stake) ) / FixedU128 :: from ( total_capacity) ;
124+ let currency_reward = currency_reward. trunc ( ) ;
125+ // reward for this currency = reward * (capacity_stake / total_capacity)
126+ let vaults: Vec < _ > = vault_stakes
127+ . iter ( )
128+ . filter ( |( vault, _) | vault. collateral_currency ( ) == currency)
129+ . collect ( ) ;
130+ let total_vault_stake: u128 = vaults. iter ( ) . map ( |( _, stake) | * * stake) . sum ( ) ;
131+ for vault_stake in vaults. iter ( ) {
132+ let nominators: Vec < _ > = self
133+ . nominations ( )
134+ . iter ( )
135+ . cloned ( )
136+ . filter ( |( ( vault, _nominator) , _stake) | & vault == vault_stake. 0 )
137+ . map ( |( ( _vault, nominator) , stake) | ( nominator, stake) )
138+ . collect ( ) ;
139+ let total_nomination = nominators
140+ . iter ( )
141+ . map ( |( _, nomination) | * nomination)
142+ . fold ( Zero :: zero ( ) , |x : FixedU128 , y : FixedU128 | x + y) ;
143+ let vault_reward =
144+ ( currency_reward * FixedU128 :: from ( * vault_stake. 1 ) ) / FixedU128 :: from ( total_vault_stake) ;
145+ let vault_reward = vault_reward. trunc ( ) ;
146+ log:: error!( "vault_reward: {}" , vault_reward. truncate_to_inner( ) . unwrap( ) ) ;
147+
148+ let commission = self . commission . get ( vault_stake. 0 ) . cloned ( ) . unwrap_or_default ( ) ;
149+
150+ let vault = vault_stake. 0 . clone ( ) ;
151+ let ( vault_commission, old_vault_reward) =
152+ self . rewards . get ( & vault. account_id ) . cloned ( ) . unwrap_or_default ( ) ;
153+ self . rewards . insert (
154+ vault. account_id . clone ( ) ,
155+ ( vault_commission + vault_reward * commission, old_vault_reward) ,
156+ ) ;
157+
158+ for ( nominator_id, nomination) in nominators {
159+ let nominator_reward = ( vault_reward - vault_reward * commission) * nomination / total_nomination;
160+
161+ let ( nominator_commission, old_nominator_reward) =
162+ self . rewards . get ( & nominator_id) . cloned ( ) . unwrap_or_default ( ) ;
163+ self . rewards . insert (
164+ nominator_id. clone ( ) ,
165+ ( nominator_commission, old_nominator_reward + nominator_reward) ,
166+ ) ;
167+ }
168+ }
99169 }
170+
100171 self
101172 }
102173
@@ -120,10 +191,12 @@ impl IdealRewardPool {
120191 . iter ( )
121192 . filter ( |( ( vault, nominator) , _stake) | nominator == account && vault. collateral_currency ( ) == currency_id)
122193 . map ( |( _key, value) | * value)
123- . sum ( )
194+ . fold ( Zero :: zero ( ) , |x : FixedU128 , y : FixedU128 | x + y)
195+ . truncate_to_inner ( )
196+ . unwrap ( )
124197 }
125198
126- pub fn nominations ( & self ) -> Vec < ( StakeId , u128 ) > {
199+ pub fn nominations ( & self ) -> Vec < ( StakeId , FixedU128 ) > {
127200 self . collateral
128201 . iter ( )
129202 . map ( |( key, value) | ( key. clone ( ) , value. clone ( ) ) )
0 commit comments