use std::str::FromStr;
use cosmwasm_std::Decimal;
use mars_params::{
error::ContractError::Validation,
msg::AssetParamsUpdate,
types::hls::{HlsAssetType, HlsParamsUnchecked},
};
use mars_utils::error::ValidationError::{InvalidDenom, InvalidParam};
use crate::helpers::{assert_err, default_asset_params, MockEnv};
pub mod helpers;
#[test]
fn denom_must_be_native() {
let mut mock = MockEnv::new().build().unwrap();
let denom = "AA".to_string();
let res = mock.update_asset_params(
&mock.query_owner(),
AssetParamsUpdate::AddOrUpdate {
params: default_asset_params(&denom),
},
);
assert_err(
res,
Validation(InvalidDenom {
reason: "Invalid denom length".to_string(),
}),
);
}
#[test]
fn max_ltv_less_than_one() {
let mut mock = MockEnv::new().build().unwrap();
let mut params = default_asset_params("denom_xyz");
params.max_loan_to_value = Decimal::from_str("1.1235").unwrap();
let res = mock.update_asset_params(
&mock.query_owner(),
AssetParamsUpdate::AddOrUpdate {
params,
},
);
assert_err(
res,
Validation(InvalidParam {
param_name: "max_loan_to_value".to_string(),
invalid_value: "1.1235".to_string(),
predicate: "< 1".to_string(),
}),
);
}
#[test]
fn liquidation_threshold_less_than_or_equal_to_one() {
let mut mock = MockEnv::new().build().unwrap();
let mut params = default_asset_params("denom_xyz");
params.liquidation_threshold = Decimal::from_str("1.1235").unwrap();
let res = mock.update_asset_params(
&mock.query_owner(),
AssetParamsUpdate::AddOrUpdate {
params,
},
);
assert_err(
res,
Validation(InvalidParam {
param_name: "liquidation_threshold".to_string(),
invalid_value: "1.1235".to_string(),
predicate: "<= 1".to_string(),
}),
);
}
#[test]
fn liq_threshold_gt_max_ltv() {
let mut mock = MockEnv::new().build().unwrap();
let mut params = default_asset_params("denom_xyz");
params.liquidation_threshold = Decimal::from_str("0.5").unwrap();
params.max_loan_to_value = Decimal::from_str("0.6").unwrap();
let res = mock.update_asset_params(
&mock.query_owner(),
AssetParamsUpdate::AddOrUpdate {
params,
},
);
assert_err(
res,
Validation(InvalidParam {
param_name: "liquidation_threshold".to_string(),
invalid_value: "0.5".to_string(),
predicate: "> 0.6 (max LTV)".to_string(),
}),
);
}
#[test]
fn hls_max_ltv_less_than_one() {
let mut mock = MockEnv::new().build().unwrap();
let mut params = default_asset_params("denom_xyz");
params.credit_manager.hls = Some(HlsParamsUnchecked {
max_loan_to_value: Decimal::from_str("1.1235").unwrap(),
liquidation_threshold: Decimal::from_str("0.5").unwrap(),
correlations: vec![],
});
let res = mock.update_asset_params(
&mock.query_owner(),
AssetParamsUpdate::AddOrUpdate {
params,
},
);
assert_err(
res,
Validation(InvalidParam {
param_name: "hls_max_loan_to_value".to_string(),
invalid_value: "1.1235".to_string(),
predicate: "< 1".to_string(),
}),
);
}
#[test]
fn hls_liquidation_threshold_less_than_or_equal_to_one() {
let mut mock = MockEnv::new().build().unwrap();
let mut params = default_asset_params("denom_xyz");
params.credit_manager.hls = Some(HlsParamsUnchecked {
max_loan_to_value: Decimal::from_str("0.6").unwrap(),
liquidation_threshold: Decimal::from_str("1.1235").unwrap(),
correlations: vec![],
});
let res = mock.update_asset_params(
&mock.query_owner(),
AssetParamsUpdate::AddOrUpdate {
params,
},
);
assert_err(
res,
Validation(InvalidParam {
param_name: "hls_liquidation_threshold".to_string(),
invalid_value: "1.1235".to_string(),
predicate: "<= 1".to_string(),
}),
);
}
#[test]
fn hls_liq_threshold_gt_hls_max_ltv() {
let mut mock = MockEnv::new().build().unwrap();
let mut params = default_asset_params("denom_xyz");
params.credit_manager.hls = Some(HlsParamsUnchecked {
max_loan_to_value: Decimal::from_str("0.6").unwrap(),
liquidation_threshold: Decimal::from_str("0.5").unwrap(),
correlations: vec![],
});
let res = mock.update_asset_params(
&mock.query_owner(),
AssetParamsUpdate::AddOrUpdate {
params,
},
);
assert_err(
res,
Validation(InvalidParam {
param_name: "hls_liquidation_threshold".to_string(),
invalid_value: "0.5".to_string(),
predicate: "> 0.6 (hls max LTV)".to_string(),
}),
);
}
#[test]
fn correlations_must_be_valid_denoms() {
let mut mock = MockEnv::new().build().unwrap();
let mut params = default_asset_params("denom_xyz");
params.credit_manager.hls = Some(HlsParamsUnchecked {
max_loan_to_value: Decimal::from_str("0.5").unwrap(),
liquidation_threshold: Decimal::from_str("0.7").unwrap(),
correlations: vec![HlsAssetType::Coin {
denom: "AA".to_string(),
}],
});
let res = mock.update_asset_params(
&mock.query_owner(),
AssetParamsUpdate::AddOrUpdate {
params,
},
);
assert_err(
res,
Validation(InvalidDenom {
reason: "Invalid denom length".to_string(),
}),
);
}
#[test]
fn protocol_liquidation_fee_less_than_one() {
let mut mock = MockEnv::new().build().unwrap();
let mut params = default_asset_params("denom_xyz");
params.protocol_liquidation_fee = Decimal::from_str("1").unwrap();
let res = mock.update_asset_params(
&mock.query_owner(),
AssetParamsUpdate::AddOrUpdate {
params,
},
);
assert_err(
res,
Validation(InvalidParam {
param_name: "protocol_liquidation_fee".to_string(),
invalid_value: "1".to_string(),
predicate: "< 1".to_string(),
}),
);
}
#[test]
fn liquidation_bonus_param_b_out_of_range() {
let mut mock = MockEnv::new().build().unwrap();
let mut params = default_asset_params("denom_xyz");
params.liquidation_bonus.starting_lb = Decimal::from_str("0.101").unwrap();
let res = mock.update_asset_params(
&mock.query_owner(),
AssetParamsUpdate::AddOrUpdate {
params,
},
);
assert_err(
res,
Validation(InvalidParam {
param_name: "starting_lb".to_string(),
invalid_value: "0.101".to_string(),
predicate: "[0, 0.1]".to_string(),
}),
);
}
#[test]
fn liquidation_bonus_param_slope_out_of_range() {
let mut mock = MockEnv::new().build().unwrap();
let mut params = default_asset_params("denom_xyz");
params.liquidation_bonus.slope = Decimal::from_str("0.99").unwrap();
let res = mock.update_asset_params(
&mock.query_owner(),
AssetParamsUpdate::AddOrUpdate {
params: params.clone(),
},
);
assert_err(
res,
Validation(InvalidParam {
param_name: "slope".to_string(),
invalid_value: "0.99".to_string(),
predicate: "[1, 5]".to_string(),
}),
);
params.liquidation_bonus.slope = Decimal::from_str("5.01").unwrap();
let res = mock.update_asset_params(
&mock.query_owner(),
AssetParamsUpdate::AddOrUpdate {
params,
},
);
assert_err(
res,
Validation(InvalidParam {
param_name: "slope".to_string(),
invalid_value: "5.01".to_string(),
predicate: "[1, 5]".to_string(),
}),
);
}
#[test]
fn liquidation_bonus_param_min_lb_out_of_range() {
let mut mock = MockEnv::new().build().unwrap();
let mut params = default_asset_params("denom_xyz");
params.liquidation_bonus.min_lb = Decimal::from_str("0.101").unwrap();
let res = mock.update_asset_params(
&mock.query_owner(),
AssetParamsUpdate::AddOrUpdate {
params,
},
);
assert_err(
res,
Validation(InvalidParam {
param_name: "min_lb".to_string(),
invalid_value: "0.101".to_string(),
predicate: "[0, 0.1]".to_string(),
}),
);
}
#[test]
fn liquidation_bonus_param_max_lb_out_of_range() {
let mut mock = MockEnv::new().build().unwrap();
let mut params = default_asset_params("denom_xyz");
params.liquidation_bonus.max_lb = Decimal::from_str("0.0499").unwrap();
let res = mock.update_asset_params(
&mock.query_owner(),
AssetParamsUpdate::AddOrUpdate {
params: params.clone(),
},
);
assert_err(
res,
Validation(InvalidParam {
param_name: "max_lb".to_string(),
invalid_value: "0.0499".to_string(),
predicate: "[0.05, 0.3]".to_string(),
}),
);
params.liquidation_bonus.max_lb = Decimal::from_str("0.31").unwrap();
let res = mock.update_asset_params(
&mock.query_owner(),
AssetParamsUpdate::AddOrUpdate {
params,
},
);
assert_err(
res,
Validation(InvalidParam {
param_name: "max_lb".to_string(),
invalid_value: "0.31".to_string(),
predicate: "[0.05, 0.3]".to_string(),
}),
);
}
#[test]
fn liquidation_bonus_param_max_lb_gt_min_lb() {
let mut mock = MockEnv::new().build().unwrap();
let mut params = default_asset_params("denom_xyz");
params.liquidation_bonus.min_lb = Decimal::from_str("0.08").unwrap();
params.liquidation_bonus.max_lb = Decimal::from_str("0.07").unwrap();
let res = mock.update_asset_params(
&mock.query_owner(),
AssetParamsUpdate::AddOrUpdate {
params,
},
);
assert_err(
res,
Validation(InvalidParam {
param_name: "max_lb".to_string(),
invalid_value: "0.07".to_string(),
predicate: "> 0.08 (min LB)".to_string(),
}),
);
}