balancer_maths_rust/common/
utils.rs1use crate::common::errors::PoolError;
4use crate::common::maths::{div_down_fixed, div_up_fixed, mul_down_fixed, mul_up_fixed};
5use crate::common::types::PoolState;
6use num_bigint::BigInt;
7use num_traits::Zero;
8
9pub const MAX_UINT256: &str =
11 "115792089237316195423570985008687907853269984665640564039457584007913129639935";
12
13pub fn find_case_insensitive_index_in_list(strings: &[String], target: &str) -> Option<usize> {
15 let lowercase_target = target.to_lowercase();
16
17 for (index, string) in strings.iter().enumerate() {
18 if string.to_lowercase() == lowercase_target {
19 return Some(index);
20 }
21 }
22
23 None
24}
25
26pub fn to_scaled_18_apply_rate_round_down(
28 amount: &BigInt,
29 scaling_factor: &BigInt,
30 rate: &BigInt,
31) -> Result<BigInt, PoolError> {
32 mul_down_fixed(&(amount * scaling_factor), rate)
33}
34
35pub fn to_scaled_18_apply_rate_round_up(
37 amount: &BigInt,
38 scaling_factor: &BigInt,
39 rate: &BigInt,
40) -> Result<BigInt, PoolError> {
41 mul_up_fixed(&(amount * scaling_factor), rate)
42}
43
44pub fn to_raw_undo_rate_round_down(
49 amount: &BigInt,
50 scaling_factor: &BigInt,
51 token_rate: &BigInt,
52) -> Result<BigInt, PoolError> {
53 let denominator = scaling_factor * token_rate;
56 let result = div_down_fixed(amount, &denominator)?;
57 Ok(result)
58}
59
60pub fn to_raw_undo_rate_round_up(
65 amount: &BigInt,
66 scaling_factor: &BigInt,
67 token_rate: &BigInt,
68) -> Result<BigInt, PoolError> {
69 div_up_fixed(amount, &(scaling_factor * token_rate))
72}
73
74pub fn is_same_address(address_one: &str, address_two: &str) -> bool {
76 address_one.to_lowercase() == address_two.to_lowercase()
77}
78
79pub fn copy_to_scaled18_apply_rate_round_down_array(
81 amounts: &[BigInt],
82 scaling_factors: &[BigInt],
83 token_rates: &[BigInt],
84) -> Result<Vec<BigInt>, PoolError> {
85 let mut scaled_amounts = Vec::with_capacity(amounts.len());
86
87 for (i, amount) in amounts.iter().enumerate() {
88 let scaled_amount =
89 to_scaled_18_apply_rate_round_down(amount, &scaling_factors[i], &token_rates[i])?;
90 scaled_amounts.push(scaled_amount);
91 }
92
93 Ok(scaled_amounts)
94}
95
96pub fn copy_to_scaled18_apply_rate_round_up_array(
98 amounts: &[BigInt],
99 scaling_factors: &[BigInt],
100 token_rates: &[BigInt],
101) -> Result<Vec<BigInt>, PoolError> {
102 let mut scaled_amounts = Vec::with_capacity(amounts.len());
103
104 for (i, amount) in amounts.iter().enumerate() {
105 let scaled_amount =
106 to_scaled_18_apply_rate_round_up(amount, &scaling_factors[i], &token_rates[i])?;
107 scaled_amounts.push(scaled_amount);
108 }
109
110 Ok(scaled_amounts)
111}
112
113pub fn compute_and_charge_aggregate_swap_fees(
115 swap_fee_amount_scaled18: &BigInt,
116 aggregate_swap_fee_percentage: &BigInt,
117 decimal_scaling_factors: &[BigInt],
118 token_rates: &[BigInt],
119 index: usize,
120) -> Result<BigInt, PoolError> {
121 if swap_fee_amount_scaled18 > &BigInt::zero() && aggregate_swap_fee_percentage > &BigInt::zero()
122 {
123 let total_swap_fee_amount_raw = to_raw_undo_rate_round_down(
127 swap_fee_amount_scaled18,
128 &decimal_scaling_factors[index],
129 &token_rates[index],
130 )?;
131
132 Ok(mul_down_fixed(
133 &total_swap_fee_amount_raw,
134 aggregate_swap_fee_percentage,
135 )?)
136 } else {
137 Ok(BigInt::zero())
138 }
139}
140
141pub fn get_single_input_index(max_amounts_in: &[BigInt]) -> Result<usize, PoolError> {
143 let length = max_amounts_in.len();
144 let mut input_index = length;
145
146 for (i, amount) in max_amounts_in.iter().enumerate() {
147 if amount != &BigInt::zero() {
148 if input_index != length {
149 return Err(PoolError::Custom(
150 "Multiple non-zero inputs for single token add".to_string(),
151 ));
152 }
153 input_index = i;
154 }
155 }
156
157 if input_index >= length {
158 return Err(PoolError::Custom(
159 "All zero inputs for single token add".to_string(),
160 ));
161 }
162
163 Ok(input_index)
164}
165
166pub fn require_unbalanced_liquidity_enabled(pool_state: &PoolState) -> Result<(), PoolError> {
168 if !pool_state.base().supports_unbalanced_liquidity {
169 return Err(PoolError::Custom(
170 "DoesNotSupportUnbalancedLiquidity".to_string(),
171 ));
172 }
173 Ok(())
174}