Skip to main content

balancer_maths_rust/pools/stable/
stable_pool.rs

1use crate::common::errors::PoolError;
2use crate::common::maths::mul_up_fixed;
3use crate::common::pool_base::PoolBase;
4use crate::common::types::{Rounding, SwapKind, SwapParams};
5use crate::pools::stable::stable_data::StableMutable;
6use crate::pools::stable::stable_math::{
7    compute_balance, compute_in_given_exact_out, compute_invariant, compute_out_given_exact_in,
8    _MAX_INVARIANT_RATIO, _MIN_INVARIANT_RATIO,
9};
10use alloy_primitives::U256;
11
12/// Stable pool implementation
13pub struct StablePool {
14    pub amp: U256,
15}
16
17impl StablePool {
18    /// Create a new stable pool
19    pub fn new(pool_state: StableMutable) -> Self {
20        Self {
21            amp: pool_state.amp,
22        }
23    }
24}
25
26impl PoolBase for StablePool {
27    fn get_maximum_invariant_ratio(&self) -> U256 {
28        U256::from(_MAX_INVARIANT_RATIO)
29    }
30
31    fn get_minimum_invariant_ratio(&self) -> U256 {
32        U256::from(_MIN_INVARIANT_RATIO)
33    }
34
35    fn on_swap(&self, swap_params: &SwapParams) -> Result<U256, PoolError> {
36        let invariant = compute_invariant(&self.amp, &swap_params.balances_live_scaled_18)?;
37
38        let result = match swap_params.swap_kind {
39            SwapKind::GivenIn => compute_out_given_exact_in(
40                &self.amp,
41                &swap_params.balances_live_scaled_18,
42                swap_params.token_in_index,
43                swap_params.token_out_index,
44                &swap_params.amount_scaled_18,
45                &invariant,
46            )?,
47            SwapKind::GivenOut => compute_in_given_exact_out(
48                &self.amp,
49                &swap_params.balances_live_scaled_18,
50                swap_params.token_in_index,
51                swap_params.token_out_index,
52                &swap_params.amount_scaled_18,
53                &invariant,
54            )?,
55        };
56
57        Ok(result)
58    }
59
60    fn compute_invariant(
61        &self,
62        balances_live_scaled18: &[U256],
63        rounding: Rounding,
64    ) -> Result<U256, PoolError> {
65        let mut invariant = compute_invariant(&self.amp, balances_live_scaled18)?;
66
67        if invariant > U256::ZERO {
68            match rounding {
69                Rounding::RoundDown => {}
70                Rounding::RoundUp => {
71                    invariant += U256::ONE;
72                }
73            }
74        }
75
76        Ok(invariant)
77    }
78
79    fn compute_balance(
80        &self,
81        balances_live_scaled18: &[U256],
82        token_in_index: usize,
83        invariant_ratio: &U256,
84    ) -> Result<U256, PoolError> {
85        let invariant = self.compute_invariant(balances_live_scaled18, Rounding::RoundUp)?;
86        let scaled_invariant = mul_up_fixed(&invariant, invariant_ratio)?;
87
88        compute_balance(
89            &self.amp,
90            balances_live_scaled18,
91            &scaled_invariant,
92            token_in_index,
93        )
94    }
95}