Skip to main content

balancer_maths_rust/pools/quantamm/
quantamm_math.rs

1use crate::common::errors::PoolError;
2use crate::common::maths::mul_down_fixed;
3use alloy_primitives::{uint, I256, U256};
4
5pub const ONE: U256 = uint!(1000000000000000000_U256); // 1e18
6pub const ONE_SIGNED: I256 = I256::from_raw(uint!(1000000000000000000_U256)); // 1e18
7
8/// Calculate the current block weight based on time interpolation
9///
10/// # Arguments
11/// * `weight` - The base weight
12/// * `multiplier` - The weight multiplier
13/// * `time_since_last_update` - The time since the last weight update
14///
15/// # Returns
16/// The interpolated weight
17pub fn calculate_block_normalised_weight(
18    weight: &I256,
19    multiplier: &I256,
20    time_since_last_update: &U256,
21) -> Result<U256, PoolError> {
22    // multiplier is always below 1, we multiply by 1e18 for rounding
23    let multiplier_scaled18 = *multiplier * ONE_SIGNED;
24
25    if multiplier > &I256::ZERO {
26        Ok(weight.into_raw()
27            + mul_down_fixed(&multiplier_scaled18.into_raw(), time_since_last_update)?)
28    } else {
29        Ok(weight.into_raw()
30            - mul_down_fixed(&(-multiplier_scaled18.into_raw()), time_since_last_update)?)
31    }
32}
33
34/// Extract weights and multipliers from the first four tokens
35///
36/// # Arguments
37/// * `tokens` - List of token addresses
38/// * `first_four_weights_and_multipliers` - Packed weights and multipliers for first four tokens
39///
40/// # Returns
41/// Tuple of (weights, multipliers) for first four tokens
42pub fn get_first_four_weights_and_multipliers(
43    tokens: &[String],
44    first_four_weights_and_multipliers: &[I256],
45) -> (Vec<I256>, Vec<I256>) {
46    let less_than_4_tokens_offset = tokens.len().min(4);
47
48    let mut weights = vec![I256::ZERO; less_than_4_tokens_offset];
49    let mut multipliers = vec![I256::ZERO; less_than_4_tokens_offset];
50
51    // Convert I256 to U256 for weights
52    weights[..less_than_4_tokens_offset]
53        .copy_from_slice(&first_four_weights_and_multipliers[..less_than_4_tokens_offset]);
54
55    // Convert I256 to U256 for multipliers
56    multipliers[..less_than_4_tokens_offset].copy_from_slice(
57        &first_four_weights_and_multipliers
58            [less_than_4_tokens_offset..(less_than_4_tokens_offset + less_than_4_tokens_offset)],
59    );
60
61    (weights, multipliers)
62}
63
64/// Extract weights and multipliers from the remaining tokens
65///
66/// # Arguments
67/// * `tokens` - List of token addresses
68/// * `second_four_weights_and_multipliers` - Packed weights and multipliers for remaining tokens
69///
70/// # Returns
71/// Tuple of (weights, multipliers) for remaining tokens
72pub fn get_second_four_weights_and_multipliers(
73    tokens: &[String],
74    second_four_weights_and_multipliers: &[I256],
75) -> (Vec<I256>, Vec<I256>) {
76    if tokens.len() <= 4 {
77        return (Vec::new(), Vec::new());
78    }
79
80    let more_than_4_tokens_offset = tokens.len() - 4;
81
82    let mut weights = vec![I256::ZERO; more_than_4_tokens_offset];
83    let mut multipliers = vec![I256::ZERO; more_than_4_tokens_offset];
84
85    // Convert I256 to U256 for weights
86    weights[..more_than_4_tokens_offset]
87        .copy_from_slice(&second_four_weights_and_multipliers[..more_than_4_tokens_offset]);
88
89    // Convert I256 to U256 for multipliers
90    multipliers[..more_than_4_tokens_offset].copy_from_slice(
91        &second_four_weights_and_multipliers
92            [more_than_4_tokens_offset..(more_than_4_tokens_offset + more_than_4_tokens_offset)],
93    );
94
95    (weights, multipliers)
96}