@@ -40,6 +40,8 @@ type AccountIdOf<T> = <T as frame_system::Config>::AccountId;
4040type BalanceOf < T > = <<T as Config >:: MultiCurrency as MultiCurrency < AccountIdOf < T > > >:: Balance ;
4141
4242const BILLION : u128 = 1_000_000_000 ;
43+ // These time units are defined in number of blocks.
44+ const BLOCKS_PER_DAY : u32 = 60 / 12 * 60 * 24 ;
4345
4446#[ derive( Encode , Decode , Clone , Eq , PartialEq , Debug ) ]
4547pub struct BancorPool < Balance > {
@@ -63,6 +65,9 @@ pub mod pallet {
6365 #[ pallet:: constant]
6466 type InterventionPercentage : Get < Percent > ;
6567
68+ #[ pallet:: constant]
69+ type DailyReleasePercentage : Get < Percent > ;
70+
6671 /// Set default weight.
6772 type WeightInfo : WeightInfo ;
6873 }
@@ -97,6 +102,11 @@ pub mod pallet {
97102 #[ pallet:: getter( fn get_bancor_pool) ]
98103 pub type BancorPools < T > = StorageMap < _ , Blake2_128Concat , CurrencyId , BancorPool < BalanceOf < T > > > ;
99104
105+ /// Reserve for releasing Tokens to the bancor pool
106+ #[ pallet:: storage]
107+ #[ pallet:: getter( fn get_bancor_reserve) ]
108+ pub type BancorReserve < T > = StorageMap < _ , Blake2_128Concat , CurrencyId , BalanceOf < T > > ;
109+
100110 #[ pallet:: genesis_config]
101111 pub struct GenesisConfig < T : Config > {
102112 pub bancor_pools : Vec < ( CurrencyId , BalanceOf < T > ) > ,
@@ -122,7 +132,8 @@ pub mod pallet {
122132 vstoken_base_supply : * base_balance,
123133 } ;
124134
125- BancorPools :: < T > :: insert ( currency_id, pool) ;
135+ BancorPools :: < T > :: insert ( currency_id. clone ( ) , pool) ;
136+ BancorReserve :: < T > :: insert ( currency_id. clone ( ) , BalanceOf :: < T > :: from ( 0u32 ) ) ;
126137 }
127138 }
128139 }
@@ -131,7 +142,91 @@ pub mod pallet {
131142 pub struct Pallet < T > ( PhantomData < T > ) ;
132143
133144 #[ pallet:: hooks]
134- impl < T : Config > Hooks < T :: BlockNumber > for Pallet < T > { }
145+ impl < T : Config > Hooks < T :: BlockNumber > for Pallet < T > {
146+ // check whether the price of vstoken (token/vstoken) is lower than 75%. if yes, then half
147+ // of this newly released token should be used to buy vstoken, so that the price of vstoken
148+ // will increase. Meanwhile, the other half will be put on the ceiling variable to indicate
149+ // exchange availability. If not, all the newly release token should be put aside to the
150+ // ceiling to not to impact the pool price.
151+ fn on_initialize ( _: T :: BlockNumber ) -> Weight {
152+ // for each bancor pool currency_id, release 5% of reserve tokens to the pool
153+ for ( currency_id, reserve_amount) in BancorReserve :: < T > :: iter ( ) {
154+ let token_amount = reserve_amount /
155+ T :: DailyReleasePercentage :: get ( )
156+ . saturating_reciprocal_mul_floor ( BalanceOf :: < T > :: from ( BLOCKS_PER_DAY ) ) ;
157+
158+ if token_amount > Zero :: zero ( ) {
159+ // get the current price of vstoken
160+ // let (nominator, denominator) = Self::get_instant_vstoken_price(currency_id);
161+ if let Ok ( ( nominator, denominator) ) =
162+ Self :: get_instant_vstoken_price ( currency_id)
163+ {
164+ let amount_kept: BalanceOf < T > ;
165+ // if vstoken price is lower than 0.75 token
166+ if T :: InterventionPercentage :: get ( )
167+ . saturating_reciprocal_mul_floor ( nominator) <=
168+ denominator
169+ {
170+ amount_kept = token_amount / BalanceOf :: < T > :: saturated_from ( 2u128 ) ;
171+ } else {
172+ amount_kept = token_amount;
173+ }
174+
175+ let sell_amount = token_amount. saturating_sub ( amount_kept) ;
176+ // deal with ceiling variable
177+ if amount_kept != Zero :: zero ( ) {
178+ if let Err ( _) =
179+ Self :: increase_bancor_pool_ceiling ( currency_id, amount_kept)
180+ {
181+ continue ;
182+ }
183+ }
184+ // deal with exchange transaction
185+ if sell_amount != Zero :: zero ( ) {
186+ // make changes in the bancor pool
187+ if let Ok ( vstoken_amount) =
188+ Self :: calculate_price_for_vstoken ( currency_id, sell_amount)
189+ {
190+ let sell_result = Self :: revise_bancor_pool_token_buy_vstoken (
191+ currency_id,
192+ sell_amount,
193+ vstoken_amount,
194+ ) ;
195+ // if somehow not able to sell token, then add the amount to
196+ // ceiling.
197+ if let Err ( err_msg) = sell_result {
198+ match err_msg {
199+ Error :: < T > :: BancorPoolNotExist => ( ) ,
200+ _ => {
201+ if let Err ( _) = Self :: increase_bancor_pool_ceiling (
202+ currency_id,
203+ sell_amount,
204+ ) {
205+ continue ;
206+ }
207+ } ,
208+ } ;
209+ }
210+ }
211+ }
212+
213+ // deduct token_amount from BancorReserve
214+ BancorReserve :: < T > :: mutate ( currency_id, |reserve_option| {
215+ match reserve_option {
216+ Some ( reserve) => {
217+ * reserve = reserve. saturating_sub ( token_amount) ;
218+ } ,
219+ _ => ( ) ,
220+ }
221+ } ) ;
222+ }
223+ }
224+ }
225+
226+ // TODO: Estimate weight for this function
227+ 1_000
228+ }
229+ }
135230
136231 #[ pallet:: call]
137232 impl < T : Config > Pallet < T > {
@@ -141,9 +236,13 @@ pub mod pallet {
141236 currency_id : CurrencyId ,
142237 token_amount : BalanceOf < T > ,
143238 ) -> DispatchResult {
144- ensure_root ( origin) ?;
239+ let adder = ensure_signed ( origin) ?;
145240 ensure ! ( currency_id. is_token( ) , Error :: <T >:: NotSupportTokenType ) ;
146241
242+ let token_balance = T :: MultiCurrency :: free_balance ( currency_id, & adder) ;
243+ ensure ! ( token_balance >= token_amount, Error :: <T >:: NotEnoughBalance ) ;
244+
245+ T :: MultiCurrency :: withdraw ( currency_id, & adder, token_amount) ?;
147246 Self :: add_token ( currency_id, token_amount) ?;
148247
149248 Ok ( ( ) )
@@ -426,49 +525,19 @@ impl<T: Config> Pallet<T> {
426525}
427526
428527impl < T : Config > BancorHandler < BalanceOf < T > > for Pallet < T > {
429- // check whether the price of vstoken (token/vstoken) is lower than 75%. if yes, then half of
430- // this newly released token should be used to buy vstoken, so that the price of vstoken will
431- // increase. Meanwhile, the other half will be put on the ceiling variable to indicate exchange
432- // availability. If not, all the newly release token should be put aside to the ceiling to not
433- // to impact the pool price.
434528 fn add_token ( currency_id : CurrencyId , token_amount : BalanceOf < T > ) -> Result < ( ) , DispatchError > {
435- // get the current price of vstoken
436- let ( nominator, denominator) = Self :: get_instant_vstoken_price ( currency_id) ?;
437-
438- let amount_kept: BalanceOf < T > ;
439- // if vstoken price is lower than 0.75 token
440- if T :: InterventionPercentage :: get ( ) . saturating_reciprocal_mul_floor ( nominator) <=
441- denominator
442- {
443- amount_kept = token_amount / BalanceOf :: < T > :: saturated_from ( 2u128 ) ;
444- } else {
445- amount_kept = token_amount;
446- }
447-
448- let sell_amount = token_amount. saturating_sub ( amount_kept) ;
449-
450- // deal with ceiling variable
451- if amount_kept != Zero :: zero ( ) {
452- Self :: increase_bancor_pool_ceiling ( currency_id, amount_kept) ?;
453- }
454-
455- // deal with exchange transaction
456- if sell_amount != Zero :: zero ( ) {
457- // make changes in the bancor pool
458- let vstoken_amount = Self :: calculate_price_for_vstoken ( currency_id, sell_amount) ?;
459- let sell_result = Self :: revise_bancor_pool_token_buy_vstoken (
460- currency_id,
461- sell_amount,
462- vstoken_amount,
463- ) ;
464-
465- // if somehow not able to sell token, then add the amount to ceiling.
466- if let Err ( err_msg) = sell_result {
467- match err_msg {
468- Error :: < T > :: BancorPoolNotExist => Err ( Error :: < T > :: BancorPoolNotExist ) ,
469- _ => Self :: increase_bancor_pool_ceiling ( currency_id, sell_amount) ,
470- } ?;
471- }
529+ ensure ! ( token_amount >= Zero :: zero( ) , Error :: <T >:: AmountNotGreaterThanZero ) ;
530+
531+ if token_amount != Zero :: zero ( ) {
532+ BancorReserve :: < T > :: mutate ( currency_id, |reserve_option| -> Result < ( ) , Error < T > > {
533+ match reserve_option {
534+ Some ( reserve) => {
535+ * reserve = reserve. saturating_add ( token_amount) ;
536+ Ok ( ( ) )
537+ } ,
538+ _ => Err ( Error :: < T > :: BancorPoolNotExist ) ,
539+ }
540+ } ) ?;
472541 }
473542
474543 Ok ( ( ) )
0 commit comments