1use cosmwasm_std::{Decimal, DepsMut, MessageInfo, Response};
2use mars_utils::error::ValidationError;
3
4use crate::{
5 error::{ContractError, ContractResult},
6 msg::{AssetParamsUpdate, VaultConfigUpdate},
7 state::{ASSET_PARAMS, OWNER, TARGET_HEALTH_FACTOR, VAULT_CONFIGS},
8};
9
10pub const CONTRACT_NAME: &str = env!("CARGO_PKG_NAME");
11pub const CONTRACT_VERSION: &str = env!("CARGO_PKG_VERSION");
12
13pub fn update_target_health_factor(
14 deps: DepsMut,
15 info: MessageInfo,
16 target_health_factor: Decimal,
17) -> ContractResult<Response> {
18 OWNER.assert_owner(deps.storage, &info.sender)?;
19
20 assert_thf(target_health_factor)?;
21 TARGET_HEALTH_FACTOR.save(deps.storage, &target_health_factor)?;
22
23 let response = Response::new()
24 .add_attribute("action", "update_target_health_factor")
25 .add_attribute("value", target_health_factor.to_string());
26
27 Ok(response)
28}
29
30pub fn update_asset_params(
31 deps: DepsMut,
32 info: MessageInfo,
33 update: AssetParamsUpdate,
34) -> ContractResult<Response> {
35 OWNER.assert_owner(deps.storage, &info.sender)?;
36
37 let mut response = Response::new().add_attribute("action", "update_asset_param");
38
39 match update {
40 AssetParamsUpdate::AddOrUpdate {
41 params: unchecked,
42 } => {
43 let params = unchecked.check(deps.api)?;
44
45 ASSET_PARAMS.save(deps.storage, ¶ms.denom, ¶ms)?;
46 response = response
47 .add_attribute("action_type", "add_or_update")
48 .add_attribute("denom", params.denom);
49 }
50 }
51
52 Ok(response)
53}
54
55pub fn update_vault_config(
56 deps: DepsMut,
57 info: MessageInfo,
58 update: VaultConfigUpdate,
59) -> ContractResult<Response> {
60 OWNER.assert_owner(deps.storage, &info.sender)?;
61
62 let mut response = Response::new().add_attribute("action", "update_vault_config");
63
64 match update {
65 VaultConfigUpdate::AddOrUpdate {
66 config,
67 } => {
68 let checked = config.check(deps.api)?;
69 VAULT_CONFIGS.save(deps.storage, &checked.addr, &checked)?;
70 response = response
71 .add_attribute("action_type", "add_or_update")
72 .add_attribute("addr", checked.addr);
73 }
74 }
75
76 Ok(response)
77}
78
79pub fn assert_thf(thf: Decimal) -> Result<(), ContractError> {
80 if thf < Decimal::one() || thf > Decimal::from_atomics(2u128, 0u32)? {
81 return Err(ValidationError::InvalidParam {
82 param_name: "target_health_factor".to_string(),
83 invalid_value: thf.to_string(),
84 predicate: "[1, 2]".to_string(),
85 }
86 .into());
87 }
88 Ok(())
89}
90
91pub fn assert_lqt_gt_max_ltv(
93 max_ltv: Decimal,
94 liq_threshold: Decimal,
95) -> Result<(), ValidationError> {
96 if liq_threshold <= max_ltv {
97 return Err(ValidationError::InvalidParam {
98 param_name: "liquidation_threshold".to_string(),
99 invalid_value: liq_threshold.to_string(),
100 predicate: format!("> {} (max LTV)", max_ltv),
101 });
102 }
103 Ok(())
104}
105
106pub fn assert_hls_lqt_gt_max_ltv(
107 max_ltv: Decimal,
108 liq_threshold: Decimal,
109) -> Result<(), ValidationError> {
110 if liq_threshold <= max_ltv {
111 return Err(ValidationError::InvalidParam {
112 param_name: "hls_liquidation_threshold".to_string(),
113 invalid_value: liq_threshold.to_string(),
114 predicate: format!("> {} (hls max LTV)", max_ltv),
115 });
116 }
117 Ok(())
118}