use std::fmt::Display;
use anchor_lang::prelude::*;
use fix::prelude::*;
use crate::error::CoreError::StabilityValidation;
use crate::stability_mode::StabilityMode::{Depeg, Mode1, Mode2, Normal};
#[derive(
Copy, Clone, Debug, AnchorSerialize, AnchorDeserialize, PartialEq, PartialOrd,
)]
pub enum StabilityMode {
Normal,
Mode1,
Mode2,
Depeg,
}
impl Display for StabilityMode {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Normal => f.write_str("Normal"),
Mode1 => f.write_str("Mode1"),
Mode2 => f.write_str("Mode2"),
Depeg => f.write_str("Depeg"),
}
}
}
#[derive(Copy, Clone)]
pub struct StabilityController {
pub stability_threshold_1: UFix64<N2>,
pub stability_threshold_2: UFix64<N2>,
pub min_stability_threshold: UFix64<N2>,
}
impl StabilityController {
pub fn new(
stability_threshold_1: UFix64<N2>,
stability_threshold_2: UFix64<N2>,
) -> Result<StabilityController> {
let min_stability_threshold = stability_threshold_2
.checked_sub(&UFix64::new(10))
.filter(|t| *t > UFix64::one())
.ok_or(StabilityValidation)?;
let controller = StabilityController {
stability_threshold_1,
stability_threshold_2,
min_stability_threshold,
};
controller.validate()?;
Ok(controller)
}
pub fn stability_mode(
&self,
collateral_ratio: UFix64<N9>,
) -> Result<StabilityMode> {
Ok(
if collateral_ratio >= self.stability_threshold_1.convert() {
Normal
} else if collateral_ratio >= self.stability_threshold_2.convert() {
Mode1
} else if collateral_ratio >= UFix64::one() {
Mode2
} else {
Depeg
},
)
}
#[must_use]
pub fn prev_stability_threshold(
&self,
mode: StabilityMode,
) -> Option<UFix64<N2>> {
match mode {
Normal => None,
Mode1 => Some(self.stability_threshold_1),
Mode2 => Some(self.stability_threshold_2),
Depeg => Some(UFix64::one()),
}
}
#[must_use]
pub fn next_stability_threshold(
&self,
mode: StabilityMode,
) -> Option<UFix64<N2>> {
match mode {
Normal => Some(self.stability_threshold_1),
Mode1 => Some(self.stability_threshold_2),
Mode2 => Some(UFix64::one()),
Depeg => None,
}
}
#[must_use]
pub fn min_stability_threshold(&self) -> UFix64<N2> {
self.min_stability_threshold
}
pub fn validate(&self) -> Result<()> {
let t1 = self.stability_threshold_1;
let t2 = self.stability_threshold_2;
let one = UFix64::one();
if t1 > t2 && t1 > one && t2 > one {
Ok(())
} else {
Err(StabilityValidation.into())
}
}
}
#[cfg(test)]
mod tests {
#[test]
fn stability_mode_ord() {
use super::StabilityMode::*;
assert!(Normal < Mode1);
assert!(Mode1 < Mode2);
assert!(Mode2 < Depeg);
}
}