@@ -8,7 +8,7 @@ use substrate_fixed::{
88} ;
99
1010use super :: BondingFunction ;
11- use crate :: { PassiveSupply , Precision } ;
11+ use crate :: { PassiveSupply , Precision , LOG_TARGET } ;
1212
1313#[ derive( Clone , Debug , Encode , Decode , PartialEq , Eq , TypeInfo , MaxEncodedLen ) ]
1414pub struct LMSRParametersInput < Parameter > {
@@ -34,13 +34,30 @@ where
3434 Parameter : FixedSigned + PartialOrd < Precision > + From < Precision > + ToFixed ,
3535 <Parameter as Fixed >:: Bits : Copy + ToFixed + AddAssign + BitOrAssign + ShlAssign ,
3636{
37- fn calculate_exp_term ( & self , supply : Parameter , x : Parameter ) -> Result < Parameter , ArithmeticError > {
38- supply
39- . checked_sub ( x)
40- . ok_or ( ArithmeticError :: Underflow ) ?
41- . checked_div ( self . m )
42- . ok_or ( ArithmeticError :: DivisionByZero )
43- . and_then ( |exponent| exp :: < Parameter , Parameter > ( exponent) . map_err ( |_| ArithmeticError :: Overflow ) )
37+ fn lse ( & self , supply : & [ Parameter ] ) -> Result < Parameter , ArithmeticError > {
38+ // Find the maximum value in the supply for numerical stability
39+ let max = supply. iter ( ) . max ( ) . ok_or_else ( || {
40+ log:: error!( target: LOG_TARGET , "Supply is empty. Found pool with no currencies." ) ;
41+ ArithmeticError :: DivisionByZero
42+ } ) ?;
43+
44+ // Compute the sum of the exponent terms, adjusted by max for stability
45+ let e_term_sum = supply. iter ( ) . try_fold ( Parameter :: from_num ( 0 ) , |acc, x| {
46+ let exponent = x
47+ . checked_sub ( * max)
48+ . ok_or ( ArithmeticError :: Underflow ) ?
49+ . checked_div ( self . m )
50+ . ok_or ( ArithmeticError :: DivisionByZero ) ?;
51+
52+ let exp_result = exp :: < Parameter , Parameter > ( exponent) . map_err ( |_| ArithmeticError :: Overflow ) ?;
53+ acc. checked_add ( exp_result) . ok_or ( ArithmeticError :: Overflow )
54+ } ) ?;
55+
56+ // Compute the logarithm of the sum and scale it by `m`, then add the max term
57+ ln :: < Parameter , Parameter > ( e_term_sum)
58+ . map_err ( |_| ArithmeticError :: Underflow )
59+ . and_then ( |log_sum| log_sum. checked_mul ( self . m ) . ok_or ( ArithmeticError :: Overflow ) )
60+ . and_then ( |scaled_log| scaled_log. checked_add ( * max) . ok_or ( ArithmeticError :: Overflow ) )
4461 }
4562}
4663
@@ -49,48 +66,25 @@ where
4966 Parameter : FixedSigned + PartialOrd < Precision > + From < Precision > + ToFixed ,
5067 <Parameter as Fixed >:: Bits : Copy + ToFixed + AddAssign + BitOrAssign + ShlAssign ,
5168{
52- // c(a, c) = (a - c) + b * ln((1 + SUM_i e^((q_i - a)/b)) / (1 + SUM_i e^((q_i - c)/b)))
5369 fn calculate_costs (
5470 & self ,
5571 low : Parameter ,
5672 high : Parameter ,
5773 passive_supply : PassiveSupply < Parameter > ,
5874 ) -> Result < Parameter , ArithmeticError > {
59- let e_term_numerator = passive_supply
60- . iter ( )
61- . map ( |x| self . calculate_exp_term ( * x, high) )
62- . collect :: < Result < Vec < Parameter > , ArithmeticError > > ( ) ?;
63-
64- let term1 = e_term_numerator. iter ( ) . try_fold ( Parameter :: from_num ( 0 ) , |acc, x| {
65- acc. checked_add ( * x) . ok_or ( ArithmeticError :: Overflow )
66- } ) ?;
67-
68- let numerator = Parameter :: from_num ( 1 )
69- . checked_add ( term1)
70- . ok_or ( ArithmeticError :: Overflow ) ?;
71-
72- let e_term_denominator = passive_supply
73- . iter ( )
74- . map ( |x| self . calculate_exp_term ( * x, low) )
75- . collect :: < Result < Vec < Parameter > , ArithmeticError > > ( ) ?;
76-
77- let term2 = e_term_denominator. iter ( ) . try_fold ( Parameter :: from_num ( 0 ) , |acc, x| {
78- acc. checked_add ( * x) . ok_or ( ArithmeticError :: Overflow )
79- } ) ?;
80-
81- let denominator = Parameter :: from_num ( 1 )
82- . checked_add ( term2)
83- . ok_or ( ArithmeticError :: Overflow ) ?;
84-
85- let log_value = numerator
86- . checked_div ( denominator)
87- . ok_or ( ArithmeticError :: DivisionByZero )
88- . and_then ( |x| ln :: < Parameter , Parameter > ( x) . map_err ( |_| ArithmeticError :: Overflow ) ) ?;
89-
90- let high_low_diff = high. checked_sub ( low) . ok_or ( ArithmeticError :: Underflow ) ?;
75+ // Clone passive_supply and add low and high to create modified supplies
76+ let mut low_total_supply = passive_supply. clone ( ) ;
77+ low_total_supply. push ( low) ;
78+ let mut high_total_supply = passive_supply;
79+ high_total_supply. push ( high) ;
9180
92- let m_log_value = self . m . checked_mul ( log_value) . ok_or ( ArithmeticError :: Overflow ) ?;
81+ // Compute LSE for both modified supplies
82+ let lower_bound_value = self . lse ( & low_total_supply) ?;
83+ let high_bound_value = self . lse ( & high_total_supply) ?;
9384
94- high_low_diff. checked_add ( m_log_value) . ok_or ( ArithmeticError :: Overflow )
85+ // Return the difference between high and low LSE values
86+ high_bound_value
87+ . checked_sub ( lower_bound_value)
88+ . ok_or ( ArithmeticError :: Underflow )
9589 }
9690}
0 commit comments