use alloy_primitives::U256;
use crate::swap;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum PoolError {
NotApplicable,
IndexOutOfRange,
}
impl std::fmt::Display for PoolError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::NotApplicable => f.write_str("field not applicable to this pool variant"),
Self::IndexOutOfRange => f.write_str("index out of range"),
}
}
}
impl std::error::Error for PoolError {}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum Pool {
StableSwapV0 {
balances: Vec<U256>,
rates: Vec<U256>,
amp: U256,
fee: U256,
},
StableSwapV1 {
balances: Vec<U256>,
rates: Vec<U256>,
amp: U256,
fee: U256,
},
StableSwapV2 {
balances: Vec<U256>,
rates: Vec<U256>,
amp: U256,
fee: U256,
},
StableSwapALend {
balances: Vec<U256>,
precision_mul: Vec<U256>,
amp: U256,
fee: U256,
offpeg_fee_multiplier: U256,
},
StableSwapNG {
balances: Vec<U256>,
rates: Vec<U256>,
amp: U256,
fee: U256,
offpeg_fee_multiplier: U256,
},
StableSwapMeta {
balances: Vec<U256>,
rates: Vec<U256>,
amp: U256,
fee: U256,
},
TwoCryptoV1 {
balances: [U256; 2],
precisions: [U256; 2],
price_scale: U256,
d: U256,
ann: U256,
gamma: U256,
mid_fee: U256,
out_fee: U256,
fee_gamma: U256,
},
TwoCryptoNG {
balances: [U256; 2],
precisions: [U256; 2],
price_scale: U256,
d: U256,
ann: U256,
gamma: U256,
mid_fee: U256,
out_fee: U256,
fee_gamma: U256,
},
TwoCryptoStable {
balances: [U256; 2],
precisions: [U256; 2],
price_scale: U256,
d: U256,
ann: U256,
mid_fee: U256,
out_fee: U256,
fee_gamma: U256,
},
TriCryptoV1 {
balances: [U256; 3],
precisions: [U256; 3],
price_scale: [U256; 2],
d: U256,
ann: U256,
gamma: U256,
mid_fee: U256,
out_fee: U256,
fee_gamma: U256,
},
TriCryptoNG {
balances: [U256; 3],
precisions: [U256; 3],
price_scale: [U256; 2],
d: U256,
ann: U256,
gamma: U256,
mid_fee: U256,
out_fee: U256,
fee_gamma: U256,
},
}
impl Pool {
pub fn balances(&self) -> &[U256] {
match self {
Pool::StableSwapV0 { balances, .. }
| Pool::StableSwapV1 { balances, .. }
| Pool::StableSwapV2 { balances, .. }
| Pool::StableSwapALend { balances, .. }
| Pool::StableSwapNG { balances, .. }
| Pool::StableSwapMeta { balances, .. } => balances,
Pool::TwoCryptoV1 { balances, .. }
| Pool::TwoCryptoNG { balances, .. }
| Pool::TwoCryptoStable { balances, .. } => balances,
Pool::TriCryptoV1 { balances, .. } | Pool::TriCryptoNG { balances, .. } => balances,
}
}
pub fn get_amount_out(&self, i: usize, j: usize, dx: U256) -> Option<U256> {
match self {
Pool::StableSwapV0 {
balances,
rates,
amp,
fee,
} => swap::stableswap_v0::get_amount_out(balances, rates, *amp, *fee, i, j, dx),
Pool::StableSwapV1 {
balances,
rates,
amp,
fee,
} => swap::stableswap_v1::get_amount_out(balances, rates, *amp, *fee, i, j, dx),
Pool::StableSwapV2 {
balances,
rates,
amp,
fee,
} => swap::stableswap_v2::get_amount_out(balances, rates, *amp, *fee, i, j, dx),
Pool::StableSwapALend {
balances,
precision_mul,
amp,
fee,
offpeg_fee_multiplier,
} => swap::stableswap_alend::get_amount_out(
balances,
precision_mul,
*amp,
*fee,
*offpeg_fee_multiplier,
i,
j,
dx,
),
Pool::StableSwapNG {
balances,
rates,
amp,
fee,
offpeg_fee_multiplier,
} => swap::stableswap_ng::get_amount_out(
balances,
rates,
*amp,
*fee,
*offpeg_fee_multiplier,
i,
j,
dx,
),
Pool::StableSwapMeta {
balances,
rates,
amp,
fee,
} => swap::stableswap_meta::get_amount_out(balances, rates, *amp, *fee, i, j, dx),
Pool::TwoCryptoV1 {
balances,
precisions,
price_scale,
d,
ann,
gamma,
mid_fee,
out_fee,
fee_gamma,
} => swap::twocrypto_v1::get_amount_out(
balances,
precisions,
*price_scale,
*d,
*ann,
*gamma,
*mid_fee,
*out_fee,
*fee_gamma,
i,
j,
dx,
),
Pool::TwoCryptoNG {
balances,
precisions,
price_scale,
d,
ann,
gamma,
mid_fee,
out_fee,
fee_gamma,
} => swap::twocrypto_ng::get_amount_out(
balances,
precisions,
*price_scale,
*d,
*ann,
*gamma,
*mid_fee,
*out_fee,
*fee_gamma,
i,
j,
dx,
),
Pool::TwoCryptoStable {
balances,
precisions,
price_scale,
d,
ann,
mid_fee,
out_fee,
fee_gamma,
} => swap::twocrypto_stable::get_amount_out(
balances,
precisions,
*price_scale,
*d,
*ann,
*mid_fee,
*out_fee,
*fee_gamma,
i,
j,
dx,
),
Pool::TriCryptoV1 {
balances,
precisions,
price_scale,
d,
ann,
gamma,
mid_fee,
out_fee,
fee_gamma,
} => swap::tricrypto_v1::get_amount_out(
balances,
precisions,
price_scale,
*d,
*ann,
*gamma,
*mid_fee,
*out_fee,
*fee_gamma,
i,
j,
dx,
),
Pool::TriCryptoNG {
balances,
precisions,
price_scale,
d,
ann,
gamma,
mid_fee,
out_fee,
fee_gamma,
} => swap::tricrypto_ng::get_amount_out(
balances,
precisions,
price_scale,
*d,
*ann,
*gamma,
*mid_fee,
*out_fee,
*fee_gamma,
i,
j,
dx,
),
}
}
pub fn get_amount_in(&self, i: usize, j: usize, desired_output: U256) -> Option<U256> {
match self {
Pool::StableSwapV0 {
balances,
rates,
amp,
fee,
} => swap::stableswap_v0::get_amount_in(
balances,
rates,
*amp,
*fee,
i,
j,
desired_output,
),
Pool::StableSwapV1 {
balances,
rates,
amp,
fee,
} => swap::stableswap_v1::get_amount_in(
balances,
rates,
*amp,
*fee,
i,
j,
desired_output,
),
Pool::StableSwapV2 {
balances,
rates,
amp,
fee,
} => swap::stableswap_v2::get_amount_in(
balances,
rates,
*amp,
*fee,
i,
j,
desired_output,
),
Pool::StableSwapALend {
balances,
precision_mul,
amp,
fee,
offpeg_fee_multiplier,
} => swap::stableswap_alend::get_amount_in(
balances,
precision_mul,
*amp,
*fee,
*offpeg_fee_multiplier,
i,
j,
desired_output,
),
Pool::StableSwapNG {
balances,
rates,
amp,
fee,
offpeg_fee_multiplier,
} => swap::stableswap_ng::get_amount_in(
balances,
rates,
*amp,
*fee,
*offpeg_fee_multiplier,
i,
j,
desired_output,
),
Pool::StableSwapMeta {
balances,
rates,
amp,
fee,
} => swap::stableswap_meta::get_amount_in(
balances,
rates,
*amp,
*fee,
i,
j,
desired_output,
),
Pool::TwoCryptoV1 {
balances,
precisions,
price_scale,
d,
ann,
gamma,
mid_fee,
out_fee,
fee_gamma,
} => swap::twocrypto_v1::get_amount_in(
balances,
precisions,
*price_scale,
*d,
*ann,
*gamma,
*mid_fee,
*out_fee,
*fee_gamma,
i,
j,
desired_output,
),
Pool::TwoCryptoNG {
balances,
precisions,
price_scale,
d,
ann,
gamma,
mid_fee,
out_fee,
fee_gamma,
} => swap::twocrypto_ng::get_amount_in(
balances,
precisions,
*price_scale,
*d,
*ann,
*gamma,
*mid_fee,
*out_fee,
*fee_gamma,
i,
j,
desired_output,
),
Pool::TwoCryptoStable {
balances,
precisions,
price_scale,
d,
ann,
mid_fee,
out_fee,
fee_gamma,
} => swap::twocrypto_stable::get_amount_in(
balances,
precisions,
*price_scale,
*d,
*ann,
*mid_fee,
*out_fee,
*fee_gamma,
i,
j,
desired_output,
),
Pool::TriCryptoV1 {
balances,
precisions,
price_scale,
d,
ann,
gamma,
mid_fee,
out_fee,
fee_gamma,
} => swap::tricrypto_v1::get_amount_in(
balances,
precisions,
price_scale,
*d,
*ann,
*gamma,
*mid_fee,
*out_fee,
*fee_gamma,
i,
j,
desired_output,
),
Pool::TriCryptoNG {
balances,
precisions,
price_scale,
d,
ann,
gamma,
mid_fee,
out_fee,
fee_gamma,
} => swap::tricrypto_ng::get_amount_in(
balances,
precisions,
price_scale,
*d,
*ann,
*gamma,
*mid_fee,
*out_fee,
*fee_gamma,
i,
j,
desired_output,
),
}
}
pub fn spot_price(&self, i: usize, j: usize) -> Option<(U256, U256)> {
match self {
Pool::StableSwapV0 {
balances,
rates,
amp,
fee,
} => swap::stableswap_v0::spot_price(balances, rates, *amp, *fee, i, j),
Pool::StableSwapV1 {
balances,
rates,
amp,
fee,
} => swap::stableswap_v1::spot_price(balances, rates, *amp, *fee, i, j),
Pool::StableSwapV2 {
balances,
rates,
amp,
fee,
} => swap::stableswap_v2::spot_price(balances, rates, *amp, *fee, i, j),
Pool::StableSwapALend {
balances,
precision_mul,
amp,
fee,
offpeg_fee_multiplier,
} => swap::stableswap_alend::spot_price(
balances,
precision_mul,
*amp,
*fee,
*offpeg_fee_multiplier,
i,
j,
),
Pool::StableSwapNG {
balances,
rates,
amp,
fee,
offpeg_fee_multiplier,
} => swap::stableswap_ng::spot_price(
balances,
rates,
*amp,
*fee,
*offpeg_fee_multiplier,
i,
j,
),
Pool::StableSwapMeta {
balances,
rates,
amp,
fee,
} => swap::stableswap_meta::spot_price(balances, rates, *amp, *fee, i, j),
Pool::TwoCryptoV1 {
balances,
precisions,
price_scale,
d,
ann,
gamma,
mid_fee,
out_fee,
fee_gamma,
} => swap::twocrypto_v1::spot_price(
balances,
precisions,
*price_scale,
*d,
*ann,
*gamma,
*mid_fee,
*out_fee,
*fee_gamma,
i,
j,
),
Pool::TwoCryptoNG {
balances,
precisions,
price_scale,
d,
ann,
gamma,
mid_fee,
out_fee,
fee_gamma,
} => swap::twocrypto_ng::spot_price(
balances,
precisions,
*price_scale,
*d,
*ann,
*gamma,
*mid_fee,
*out_fee,
*fee_gamma,
i,
j,
),
Pool::TwoCryptoStable {
balances,
precisions,
price_scale,
d,
ann,
mid_fee,
out_fee,
fee_gamma,
} => swap::twocrypto_stable::spot_price(
balances,
precisions,
*price_scale,
*d,
*ann,
*mid_fee,
*out_fee,
*fee_gamma,
i,
j,
),
Pool::TriCryptoV1 {
balances,
precisions,
price_scale,
d,
ann,
gamma,
mid_fee,
out_fee,
fee_gamma,
} => swap::tricrypto_v1::spot_price(
balances,
precisions,
price_scale,
*d,
*ann,
*gamma,
*mid_fee,
*out_fee,
*fee_gamma,
i,
j,
),
Pool::TriCryptoNG {
balances,
precisions,
price_scale,
d,
ann,
gamma,
mid_fee,
out_fee,
fee_gamma,
} => swap::tricrypto_ng::spot_price(
balances,
precisions,
price_scale,
*d,
*ann,
*gamma,
*mid_fee,
*out_fee,
*fee_gamma,
i,
j,
),
}
}
pub fn amp(&self) -> U256 {
match self {
Pool::StableSwapV0 { amp, .. }
| Pool::StableSwapV1 { amp, .. }
| Pool::StableSwapV2 { amp, .. }
| Pool::StableSwapALend { amp, .. }
| Pool::StableSwapNG { amp, .. }
| Pool::StableSwapMeta { amp, .. } => *amp,
Pool::TwoCryptoV1 { ann, .. }
| Pool::TwoCryptoNG { ann, .. }
| Pool::TwoCryptoStable { ann, .. } => *ann,
Pool::TriCryptoV1 { ann, .. } | Pool::TriCryptoNG { ann, .. } => *ann,
}
}
pub fn fee(&self) -> Option<U256> {
match self {
Pool::StableSwapV0 { fee, .. }
| Pool::StableSwapV1 { fee, .. }
| Pool::StableSwapV2 { fee, .. }
| Pool::StableSwapALend { fee, .. }
| Pool::StableSwapNG { fee, .. }
| Pool::StableSwapMeta { fee, .. } => Some(*fee),
_ => None,
}
}
pub fn crypto_fees(&self) -> Option<(U256, U256, U256)> {
match self {
Pool::TwoCryptoV1 {
mid_fee,
out_fee,
fee_gamma,
..
}
| Pool::TwoCryptoNG {
mid_fee,
out_fee,
fee_gamma,
..
}
| Pool::TwoCryptoStable {
mid_fee,
out_fee,
fee_gamma,
..
}
| Pool::TriCryptoV1 {
mid_fee,
out_fee,
fee_gamma,
..
}
| Pool::TriCryptoNG {
mid_fee,
out_fee,
fee_gamma,
..
} => Some((*mid_fee, *out_fee, *fee_gamma)),
_ => None,
}
}
pub fn rates(&self) -> Option<&[U256]> {
match self {
Pool::StableSwapV0 { rates, .. }
| Pool::StableSwapV1 { rates, .. }
| Pool::StableSwapV2 { rates, .. }
| Pool::StableSwapNG { rates, .. }
| Pool::StableSwapMeta { rates, .. } => Some(rates),
_ => None,
}
}
pub fn d(&self) -> Option<U256> {
match self {
Pool::TwoCryptoV1 { d, .. }
| Pool::TwoCryptoNG { d, .. }
| Pool::TwoCryptoStable { d, .. } => Some(*d),
Pool::TriCryptoV1 { d, .. } | Pool::TriCryptoNG { d, .. } => Some(*d),
_ => None,
}
}
pub fn gamma(&self) -> Option<U256> {
match self {
Pool::TwoCryptoV1 { gamma, .. } | Pool::TwoCryptoNG { gamma, .. } => Some(*gamma),
Pool::TriCryptoV1 { gamma, .. } | Pool::TriCryptoNG { gamma, .. } => Some(*gamma),
_ => None,
}
}
pub fn precision_mul(&self) -> Option<&[U256]> {
match self {
Pool::StableSwapALend { precision_mul, .. } => Some(precision_mul),
_ => None,
}
}
pub fn precisions(&self) -> Option<&[U256]> {
match self {
Pool::TwoCryptoV1 { precisions, .. }
| Pool::TwoCryptoNG { precisions, .. }
| Pool::TwoCryptoStable { precisions, .. } => Some(precisions),
Pool::TriCryptoV1 { precisions, .. } | Pool::TriCryptoNG { precisions, .. } => {
Some(precisions)
}
_ => None,
}
}
pub fn offpeg_fee_multiplier(&self) -> Option<U256> {
match self {
Pool::StableSwapNG {
offpeg_fee_multiplier,
..
}
| Pool::StableSwapALend {
offpeg_fee_multiplier,
..
} => Some(*offpeg_fee_multiplier),
_ => None,
}
}
pub fn price_scale(&self) -> Option<&[U256]> {
match self {
Pool::TwoCryptoV1 { price_scale, .. }
| Pool::TwoCryptoNG { price_scale, .. }
| Pool::TwoCryptoStable { price_scale, .. } => std::slice::from_ref(price_scale).into(),
Pool::TriCryptoV1 { price_scale, .. } | Pool::TriCryptoNG { price_scale, .. } => {
Some(price_scale)
}
_ => None,
}
}
pub fn set_balance(&mut self, index: usize, value: U256) -> Result<(), PoolError> {
let bal = match self {
Pool::StableSwapV0 { balances, .. }
| Pool::StableSwapV1 { balances, .. }
| Pool::StableSwapV2 { balances, .. }
| Pool::StableSwapALend { balances, .. }
| Pool::StableSwapNG { balances, .. }
| Pool::StableSwapMeta { balances, .. } => balances.get_mut(index),
Pool::TwoCryptoV1 { balances, .. }
| Pool::TwoCryptoNG { balances, .. }
| Pool::TwoCryptoStable { balances, .. } => balances.get_mut(index),
Pool::TriCryptoV1 { balances, .. } | Pool::TriCryptoNG { balances, .. } => {
balances.get_mut(index)
}
};
*bal.ok_or(PoolError::IndexOutOfRange)? = value;
Ok(())
}
pub fn set_rate(&mut self, index: usize, value: U256) -> Result<(), PoolError> {
match self {
Pool::StableSwapV0 { rates, .. }
| Pool::StableSwapV1 { rates, .. }
| Pool::StableSwapV2 { rates, .. }
| Pool::StableSwapNG { rates, .. }
| Pool::StableSwapMeta { rates, .. } => {
*rates.get_mut(index).ok_or(PoolError::IndexOutOfRange)? = value;
Ok(())
}
_ => Err(PoolError::NotApplicable),
}
}
pub fn set_d(&mut self, value: U256) -> Result<(), PoolError> {
match self {
Pool::TwoCryptoV1 { d, .. }
| Pool::TwoCryptoNG { d, .. }
| Pool::TwoCryptoStable { d, .. } => {
*d = value;
Ok(())
}
Pool::TriCryptoV1 { d, .. } | Pool::TriCryptoNG { d, .. } => {
*d = value;
Ok(())
}
_ => Err(PoolError::NotApplicable),
}
}
pub fn set_price_scale(&mut self, index: usize, value: U256) -> Result<(), PoolError> {
match self {
Pool::TwoCryptoV1 { price_scale, .. }
| Pool::TwoCryptoNG { price_scale, .. }
| Pool::TwoCryptoStable { price_scale, .. } => {
if index != 0 {
return Err(PoolError::IndexOutOfRange);
}
*price_scale = value;
Ok(())
}
Pool::TriCryptoV1 { price_scale, .. } | Pool::TriCryptoNG { price_scale, .. } => {
*price_scale
.get_mut(index)
.ok_or(PoolError::IndexOutOfRange)? = value;
Ok(())
}
_ => Err(PoolError::NotApplicable),
}
}
pub fn set_amp(&mut self, value: U256) {
match self {
Pool::StableSwapV0 { amp, .. }
| Pool::StableSwapV1 { amp, .. }
| Pool::StableSwapV2 { amp, .. }
| Pool::StableSwapALend { amp, .. }
| Pool::StableSwapNG { amp, .. }
| Pool::StableSwapMeta { amp, .. } => *amp = value,
Pool::TwoCryptoV1 { ann, .. }
| Pool::TwoCryptoNG { ann, .. }
| Pool::TwoCryptoStable { ann, .. } => *ann = value,
Pool::TriCryptoV1 { ann, .. } | Pool::TriCryptoNG { ann, .. } => *ann = value,
}
}
pub fn set_gamma(&mut self, value: U256) -> Result<(), PoolError> {
match self {
Pool::TwoCryptoV1 { gamma, .. } | Pool::TwoCryptoNG { gamma, .. } => {
*gamma = value;
Ok(())
}
Pool::TriCryptoV1 { gamma, .. } | Pool::TriCryptoNG { gamma, .. } => {
*gamma = value;
Ok(())
}
_ => Err(PoolError::NotApplicable),
}
}
}