diff --git a/contracts/red-bank/src/contract.rs b/contracts/red-bank/src/contract.rs index f0e5de7f9..532868c1e 100644 --- a/contracts/red-bank/src/contract.rs +++ b/contracts/red-bank/src/contract.rs @@ -59,9 +59,19 @@ pub fn execute( amount, recipient, account_id, + liquidation_related, } => { cw_utils::nonpayable(&info)?; - withdraw::withdraw(deps, env, info, denom, amount, recipient, account_id) + withdraw::withdraw( + deps, + env, + info, + denom, + amount, + recipient, + account_id, + liquidation_related.unwrap_or(false), + ) } ExecuteMsg::Borrow { denom, diff --git a/contracts/red-bank/src/health.rs b/contracts/red-bank/src/health.rs index c22854353..280fa1c7b 100644 --- a/contracts/red-bank/src/health.rs +++ b/contracts/red-bank/src/health.rs @@ -45,9 +45,17 @@ pub fn assert_below_liq_threshold_after_withdraw( params_addr: &Addr, denom: &str, withdraw_amount: Uint128, + is_liquidation: bool, ) -> Result { - let mut positions = - get_user_positions_map(deps, env, user_addr, account_id, oracle_addr, params_addr, false)?; + let mut positions = get_user_positions_map( + deps, + env, + user_addr, + account_id, + oracle_addr, + params_addr, + is_liquidation, + )?; // Update position to compute health factor after withdraw match positions.get_mut(denom) { Some(p) => { diff --git a/contracts/red-bank/src/withdraw.rs b/contracts/red-bank/src/withdraw.rs index a25cf747d..8e7318886 100644 --- a/contracts/red-bank/src/withdraw.rs +++ b/contracts/red-bank/src/withdraw.rs @@ -19,6 +19,7 @@ pub fn withdraw( amount: Option, recipient: Option, account_id: Option, + liquidation_related: bool, ) -> Result { let withdrawer = User(&info.sender); let acc_id = account_id.clone().unwrap_or("".to_string()); @@ -63,12 +64,17 @@ pub fn withdraw( MarsAddressType::Incentives, MarsAddressType::RewardsCollector, MarsAddressType::Params, + MarsAddressType::CreditManager, ], )?; let rewards_collector_addr = &addresses[&MarsAddressType::RewardsCollector]; let incentives_addr = &addresses[&MarsAddressType::Incentives]; let oracle_addr = &addresses[&MarsAddressType::Oracle]; let params_addr = &addresses[&MarsAddressType::Params]; + let credit_manager_addr = &addresses[&MarsAddressType::CreditManager]; + + // if withdraw is part of the liquidation in credit manager we need to use correct pricing for the assets + let liquidation_related = info.sender == credit_manager_addr && liquidation_related; // if asset is used as collateral and user is borrowing we need to validate health factor after withdraw, // otherwise no reasons to block the withdraw @@ -83,6 +89,7 @@ pub fn withdraw( params_addr, &denom, withdraw_amount, + liquidation_related, )? { return Err(ContractError::InvalidHealthFactorAfterWithdraw {}); diff --git a/contracts/red-bank/tests/tests/helpers/mod.rs b/contracts/red-bank/tests/tests/helpers/mod.rs index 944b10908..512cd91e2 100644 --- a/contracts/red-bank/tests/tests/helpers/mod.rs +++ b/contracts/red-bank/tests/tests/helpers/mod.rs @@ -1,6 +1,6 @@ #![allow(dead_code)] -use std::collections::HashMap; +use std::{collections::HashMap, fmt::Display, str::FromStr}; use anyhow::Result as AnyResult; use cosmwasm_schema::serde; @@ -21,8 +21,9 @@ use mars_red_bank::{ state::{COLLATERALS, DEBTS, MARKETS}, }; use mars_red_bank_types::red_bank::{ - Collateral, CreateOrUpdateConfig, Debt, InstantiateMsg, Market, QueryMsg, - UserCollateralResponse, UserDebtResponse, UserHealthStatus, UserPositionResponse, + Collateral, CreateOrUpdateConfig, Debt, InitOrUpdateAssetParams, InstantiateMsg, + InterestRateModel, Market, QueryMsg, UserCollateralResponse, UserDebtResponse, + UserHealthStatus, UserPositionResponse, }; use mars_testing::{mock_dependencies, mock_env, mock_info, MarsMockQuerier, MockEnvParams}; @@ -372,3 +373,61 @@ pub fn assert_err(res: AnyResult, err: ContractError) { } } } + +pub fn assert_err_with_str(res: AnyResult, expected: impl Display) { + match res { + Ok(_) => panic!("Result was not an error"), + Err(generic_err) => { + let contract_err: ContractError = generic_err.downcast().unwrap(); + let msg = contract_err.to_string(); + println!("error: {}", msg); // print error for debugging + assert!(msg.contains(&format!("{expected}"))) + } + } +} + +pub fn osmo_asset_params() -> (InitOrUpdateAssetParams, AssetParams) { + default_asset_params_with("uosmo", Decimal::percent(70), Decimal::percent(78)) +} + +pub fn usdc_asset_params() -> (InitOrUpdateAssetParams, AssetParams) { + default_asset_params_with("uusdc", Decimal::percent(90), Decimal::percent(96)) +} + +pub fn default_asset_params_with( + denom: &str, + max_loan_to_value: Decimal, + liquidation_threshold: Decimal, +) -> (InitOrUpdateAssetParams, AssetParams) { + let market_params = InitOrUpdateAssetParams { + reserve_factor: Some(Decimal::percent(20)), + interest_rate_model: Some(InterestRateModel { + optimal_utilization_rate: Decimal::percent(10), + base: Decimal::percent(30), + slope_1: Decimal::percent(25), + slope_2: Decimal::percent(30), + }), + }; + let asset_params = AssetParams { + denom: denom.to_string(), + credit_manager: CmSettings { + whitelisted: false, + hls: None, + }, + red_bank: RedBankSettings { + deposit_enabled: true, + borrow_enabled: true, + }, + max_loan_to_value, + liquidation_threshold, + liquidation_bonus: LiquidationBonus { + starting_lb: Decimal::percent(1), + slope: Decimal::from_str("2.0").unwrap(), + min_lb: Decimal::percent(2), + max_lb: Decimal::percent(10), + }, + protocol_liquidation_fee: Decimal::percent(2), + deposit_cap: Uint128::MAX, + }; + (market_params, asset_params) +} diff --git a/contracts/red-bank/tests/tests/test_credit_accounts.rs b/contracts/red-bank/tests/tests/test_credit_accounts.rs index d8ef269ea..8a5b42d70 100644 --- a/contracts/red-bank/tests/tests/test_credit_accounts.rs +++ b/contracts/red-bank/tests/tests/test_credit_accounts.rs @@ -1,12 +1,10 @@ -use std::str::FromStr; - use cosmwasm_std::{coin, Addr, Decimal, Uint128}; -use mars_params::types::asset::{AssetParams, CmSettings, LiquidationBonus, RedBankSettings}; use mars_red_bank::error::ContractError; -use mars_red_bank_types::red_bank::{InitOrUpdateAssetParams, InterestRateModel, UserHealthStatus}; +use mars_red_bank_types::red_bank::UserHealthStatus; use mars_testing::integration::mock_env::MockEnvBuilder; use super::helpers::assert_err; +use crate::tests::helpers::{osmo_asset_params, usdc_asset_params}; #[test] fn deposit_and_withdraw_for_credit_account_works() { @@ -109,6 +107,7 @@ fn deposit_and_withdraw_for_credit_account_works() { "uosmo", None, Some(account_id.clone()), + None, ) .unwrap(); @@ -125,49 +124,3 @@ fn deposit_and_withdraw_for_credit_account_works() { assert!(cm_position.total_collateralized_debt.is_zero()); assert_eq!(cm_position.health_status, UserHealthStatus::NotBorrowing); } - -fn osmo_asset_params() -> (InitOrUpdateAssetParams, AssetParams) { - default_asset_params_with("uosmo", Decimal::percent(70), Decimal::percent(78)) -} - -fn usdc_asset_params() -> (InitOrUpdateAssetParams, AssetParams) { - default_asset_params_with("uusdc", Decimal::percent(90), Decimal::percent(96)) -} - -fn default_asset_params_with( - denom: &str, - max_loan_to_value: Decimal, - liquidation_threshold: Decimal, -) -> (InitOrUpdateAssetParams, AssetParams) { - let market_params = InitOrUpdateAssetParams { - reserve_factor: Some(Decimal::percent(20)), - interest_rate_model: Some(InterestRateModel { - optimal_utilization_rate: Decimal::percent(10), - base: Decimal::percent(30), - slope_1: Decimal::percent(25), - slope_2: Decimal::percent(30), - }), - }; - let asset_params = AssetParams { - denom: denom.to_string(), - credit_manager: CmSettings { - whitelisted: false, - hls: None, - }, - red_bank: RedBankSettings { - deposit_enabled: true, - borrow_enabled: true, - }, - max_loan_to_value, - liquidation_threshold, - liquidation_bonus: LiquidationBonus { - starting_lb: Decimal::percent(1), - slope: Decimal::from_str("2.0").unwrap(), - min_lb: Decimal::percent(2), - max_lb: Decimal::percent(10), - }, - protocol_liquidation_fee: Decimal::percent(2), - deposit_cap: Uint128::MAX, - }; - (market_params, asset_params) -} diff --git a/contracts/red-bank/tests/tests/test_payment.rs b/contracts/red-bank/tests/tests/test_payment.rs index 454283f29..551b6cfbb 100644 --- a/contracts/red-bank/tests/tests/test_payment.rs +++ b/contracts/red-bank/tests/tests/test_payment.rs @@ -30,6 +30,7 @@ fn rejecting_unexpected_payments() { amount: None, recipient: None, account_id: None, + liquidation_related: None, }, ) .unwrap_err(); diff --git a/contracts/red-bank/tests/tests/test_withdraw.rs b/contracts/red-bank/tests/tests/test_withdraw.rs index 30180c77a..2d6584396 100644 --- a/contracts/red-bank/tests/tests/test_withdraw.rs +++ b/contracts/red-bank/tests/tests/test_withdraw.rs @@ -1,3 +1,5 @@ +use std::str::FromStr; + use cosmwasm_std::{ attr, coin, coins, testing::{mock_env, mock_info, MockApi, MockStorage}, @@ -18,12 +20,15 @@ use mars_red_bank_types::{ incentives, red_bank::{Collateral, Debt, ExecuteMsg, Market}, }; -use mars_testing::{mock_env_at_block_time, MarsMockQuerier}; +use mars_testing::{ + integration::mock_env::MockEnvBuilder, mock_env_at_block_time, MarsMockQuerier, +}; use super::helpers::{ has_collateral_position, set_collateral, th_build_interests_updated_event, th_default_asset_params, th_get_expected_indices_and_rates, th_setup, TestUtilizationDeltaInfo, }; +use crate::tests::helpers::{assert_err_with_str, osmo_asset_params, usdc_asset_params}; struct TestSuite { deps: OwnedDeps, @@ -82,6 +87,7 @@ fn withdrawing_more_than_balance() { amount: Some(Uint128::from(2000u128)), recipient: None, account_id: None, + liquidation_related: None, }, ) .unwrap_err(); @@ -126,6 +132,7 @@ fn withdrawing_partially() { amount: Some(withdraw_amount), recipient: None, account_id: None, + liquidation_related: None, }, ) .unwrap(); @@ -263,6 +270,7 @@ fn withdrawing_completely() { amount: None, recipient: None, account_id: None, + liquidation_related: None, }, ) .unwrap(); @@ -373,6 +381,7 @@ fn withdrawing_to_another_user() { amount: None, recipient: Some(recipient_addr.to_string()), account_id: None, + liquidation_related: None, }, ) .unwrap(); @@ -670,6 +679,7 @@ fn withdrawing_if_health_factor_not_met() { amount: Some(withdraw_amount), recipient: None, account_id: None, + liquidation_related: None, }, ) .unwrap_err(); @@ -707,6 +717,7 @@ fn withdrawing_if_health_factor_met() { amount: Some(withdraw_amount), recipient: None, account_id: None, + liquidation_related: None, }, ) .unwrap(); @@ -750,3 +761,181 @@ fn withdrawing_if_health_factor_met() { let market = MARKETS.load(deps.as_ref().storage, denoms[2]).unwrap(); assert_eq!(market.collateral_total_scaled, expected_collateral_total_amount_scaled_after); } + +// Withdraw should be blocked if circuit breakers are activated in oracle contract except for the +// case where the withdrawer is the credit manager contract and the withdraw is for liquidation. +#[test] +fn withdraw_for_credit_manager_works_during_liquidation() { + let owner = Addr::unchecked("owner"); + let mut mock_env = MockEnvBuilder::new(None, owner.clone()).build(); + + let red_bank = mock_env.red_bank.clone(); + let params = mock_env.params.clone(); + let oracle = mock_env.oracle.clone(); + let pyth = mock_env.pyth.clone(); + let credit_manager = mock_env.credit_manager.clone(); + + let funded_amt = 1_000_000_000_000u128; + let provider = Addr::unchecked("provider"); // provides collateral to be borrowed by others + let account_id = "111".to_string(); + + // setup red-bank + let (market_params, asset_params) = osmo_asset_params(); + red_bank.init_asset(&mut mock_env, &asset_params.denom, market_params); + params.init_params(&mut mock_env, asset_params); + let (market_params, asset_params) = usdc_asset_params(); + red_bank.init_asset(&mut mock_env, &asset_params.denom, market_params); + params.init_params(&mut mock_env, asset_params); + + // setup oracle + oracle.set_price_source_fixed(&mut mock_env, "uosmo", Decimal::one()); + oracle.set_price_source_fixed(&mut mock_env, "uusdc", Decimal::from_ratio(2u128, 1u128)); + + // fund accounts + mock_env.fund_accounts(&[&provider, &credit_manager], funded_amt, &["uosmo", "uusdc"]); + + // provider deposits collaterals + red_bank.deposit(&mut mock_env, &provider, coin(1000000000, "uusdc")).unwrap(); + + // credit manager deposits + let cm_osmo_deposit_amt = 100000000u128; + red_bank + .deposit_with_acc_id( + &mut mock_env, + &credit_manager, + coin(cm_osmo_deposit_amt, "uosmo"), + Some(account_id.clone()), + ) + .unwrap(); + + // update credit line for credit manager + red_bank + .update_uncollateralized_loan_limit( + &mut mock_env, + &owner, + &credit_manager, + "uusdc", + Uint128::MAX, + ) + .unwrap(); + + // credit manager should be able to borrow + let cm_usdc_borrow_amt = 100000000u128; + red_bank.borrow(&mut mock_env, &credit_manager, "uusdc", cm_usdc_borrow_amt).unwrap(); + + // check collaterals for credit manager account id before withdraw + let cm_collaterals = red_bank.query_user_collaterals_with_acc_id( + &mut mock_env, + &credit_manager, + Some(account_id.clone()), + ); + assert_eq!(cm_collaterals.len(), 1); + let cm_osmo_collateral = cm_collaterals.get("uosmo").unwrap(); + assert_eq!(cm_osmo_collateral.amount.u128(), cm_osmo_deposit_amt); + + // activate circuit breakers using pyth mocked invalid price + oracle.set_price_source_fixed(&mut mock_env, "usd", Decimal::from_str("1000000").unwrap()); + oracle.set_price_source_pyth( + &mut mock_env, + "uusdc", + pyth.to_string(), + Decimal::percent(10u64), + Decimal::percent(15u64), + ); + + // try to withdraw total collateral for account id, should fail because of circuit breakers + let res = red_bank.withdraw_with_acc_id( + &mut mock_env, + &credit_manager, + "uosmo", + None, + Some(account_id.clone()), + None, + ); + assert_err_with_str( + res, + "Invalid price: price confidence deviation 0.748898678414096916 exceeds max allowed 0.1", + ); + + // withdraw total collateral for account id during liquidation, should pass + red_bank + .withdraw_with_acc_id( + &mut mock_env, + &credit_manager, + "uosmo", + None, + Some(account_id.clone()), + Some(true), + ) + .unwrap(); + + // check collaterals for credit manager account id after withdraw + let cm_collaterals = red_bank.query_user_collaterals_with_acc_id( + &mut mock_env, + &credit_manager, + Some(account_id), + ); + assert!(cm_collaterals.is_empty()); +} + +// Withdraw for a red bank user (without account id) should be blocked if circuit breakers are activated in oracle contract. +#[test] +fn withdraw_if_oracle_circuit_breakers_activated() { + let owner = Addr::unchecked("owner"); + let mut mock_env = MockEnvBuilder::new(None, owner).build(); + + let red_bank = mock_env.red_bank.clone(); + let params = mock_env.params.clone(); + let oracle = mock_env.oracle.clone(); + let pyth = mock_env.pyth.clone(); + + let funded_amt = 1_000_000_000_000u128; + let provider = Addr::unchecked("provider"); // provides collateral to be borrowed by others + let user = Addr::unchecked("user"); + + // setup red-bank + let (market_params, asset_params) = osmo_asset_params(); + red_bank.init_asset(&mut mock_env, &asset_params.denom, market_params); + params.init_params(&mut mock_env, asset_params); + let (market_params, asset_params) = usdc_asset_params(); + red_bank.init_asset(&mut mock_env, &asset_params.denom, market_params); + params.init_params(&mut mock_env, asset_params); + + // setup oracle + oracle.set_price_source_fixed(&mut mock_env, "uosmo", Decimal::one()); + oracle.set_price_source_fixed(&mut mock_env, "uusdc", Decimal::from_ratio(2u128, 1u128)); + + // fund accounts + mock_env.fund_accounts(&[&provider, &user], funded_amt, &["uosmo", "uusdc"]); + + // provider deposits collaterals + red_bank.deposit(&mut mock_env, &provider, coin(1000000000, "uusdc")).unwrap(); + + // user deposits + let cm_osmo_deposit_amt = 100000000u128; + red_bank.deposit(&mut mock_env, &user, coin(cm_osmo_deposit_amt, "uosmo")).unwrap(); + + // user borrows + let cm_usdc_borrow_amt = 100u128; + red_bank.borrow(&mut mock_env, &user, "uusdc", cm_usdc_borrow_amt).unwrap(); + + // activate circuit breakers using pyth mocked invalid price + oracle.set_price_source_fixed(&mut mock_env, "usd", Decimal::from_str("1000000").unwrap()); + oracle.set_price_source_pyth( + &mut mock_env, + "uusdc", + pyth.to_string(), + Decimal::percent(10u64), + Decimal::percent(15u64), + ); + + // try to withdraw with different `liquidation_related` value, should fail because of circuit breakers + let expected_msg = + "Invalid price: price confidence deviation 0.748898678414096916 exceeds max allowed 0.1"; + let res = red_bank.withdraw_with_acc_id(&mut mock_env, &user, "uosmo", None, None, None); + assert_err_with_str(res, expected_msg); + let res = red_bank.withdraw_with_acc_id(&mut mock_env, &user, "uosmo", None, None, Some(false)); + assert_err_with_str(res, expected_msg); + let res = red_bank.withdraw_with_acc_id(&mut mock_env, &user, "uosmo", None, None, Some(true)); + assert_err_with_str(res, expected_msg); +} diff --git a/contracts/rewards-collector/base/src/contract.rs b/contracts/rewards-collector/base/src/contract.rs index 7615ab34a..40c2d26ec 100644 --- a/contracts/rewards-collector/base/src/contract.rs +++ b/contracts/rewards-collector/base/src/contract.rs @@ -188,6 +188,7 @@ where amount, recipient: None, account_id: None, + liquidation_related: None, })?, funds: vec![], }); diff --git a/contracts/rewards-collector/osmosis/tests/tests/test_withdraw.rs b/contracts/rewards-collector/osmosis/tests/tests/test_withdraw.rs index df085fdcd..40138bd30 100644 --- a/contracts/rewards-collector/osmosis/tests/tests/test_withdraw.rs +++ b/contracts/rewards-collector/osmosis/tests/tests/test_withdraw.rs @@ -34,7 +34,8 @@ fn withdrawing_from_red_bank() { denom: "uatom".to_string(), amount: Some(Uint128::new(42069)), recipient: None, - account_id: None + account_id: None, + liquidation_related: None }) .unwrap(), funds: vec![] diff --git a/integration-tests/tests/test_incentives.rs b/integration-tests/tests/test_incentives.rs index 8fc9859c6..ee0a30985 100644 --- a/integration-tests/tests/test_incentives.rs +++ b/integration-tests/tests/test_incentives.rs @@ -188,6 +188,7 @@ fn rewards_claim_for_credit_account() { "uusdc", Some(Uint128::from(withdraw_amt_acc_id_1)), Some(acc_id_1.clone()), + None, ) .unwrap(); red_bank @@ -197,6 +198,7 @@ fn rewards_claim_for_credit_account() { "uusdc", Some(Uint128::from(withdraw_amt_acc_id_2)), Some(acc_id_2.clone()), + None, ) .unwrap(); let user_collateral = red_bank.query_user_collateral(&mut mock_env, &credit_manager, "uusdc"); diff --git a/packages/testing/src/integration/mock_env.rs b/packages/testing/src/integration/mock_env.rs index 642ff1091..52003578e 100644 --- a/packages/testing/src/integration/mock_env.rs +++ b/packages/testing/src/integration/mock_env.rs @@ -397,7 +397,7 @@ impl RedBank { denom: &str, amount: Option, ) -> AnyResult { - self.withdraw_with_acc_id(env, sender, denom, amount, None) + self.withdraw_with_acc_id(env, sender, denom, amount, None, None) } pub fn withdraw_with_acc_id( @@ -407,6 +407,7 @@ impl RedBank { denom: &str, amount: Option, account_id: Option, + liquidation_related: Option, ) -> AnyResult { env.app.execute_contract( sender.clone(), @@ -416,6 +417,7 @@ impl RedBank { amount, recipient: None, account_id, + liquidation_related, }, &[], ) diff --git a/packages/types/src/red_bank/msg.rs b/packages/types/src/red_bank/msg.rs index e18551ae5..f4cc862ab 100644 --- a/packages/types/src/red_bank/msg.rs +++ b/packages/types/src/red_bank/msg.rs @@ -68,6 +68,9 @@ pub enum ExecuteMsg { recipient: Option, /// Credit account id (Rover) account_id: Option, + // Withdraw action related to liquidation process initiated in credit manager. + // This flag is used to identify different way for pricing assets during liquidation. + liquidation_related: Option, }, /// Borrow native coins. If borrow allowed, amount is added to caller's debt diff --git a/schemas/mars-red-bank/mars-red-bank.json b/schemas/mars-red-bank/mars-red-bank.json index f36ad40b2..5f8b24d6c 100644 --- a/schemas/mars-red-bank/mars-red-bank.json +++ b/schemas/mars-red-bank/mars-red-bank.json @@ -238,6 +238,12 @@ "description": "Asset to withdraw", "type": "string" }, + "liquidation_related": { + "type": [ + "boolean", + "null" + ] + }, "recipient": { "description": "The address where the withdrawn amount is sent", "type": [ diff --git a/scripts/types/generated/mars-red-bank/MarsRedBank.client.ts b/scripts/types/generated/mars-red-bank/MarsRedBank.client.ts index cf6e4d333..3c34abe51 100644 --- a/scripts/types/generated/mars-red-bank/MarsRedBank.client.ts +++ b/scripts/types/generated/mars-red-bank/MarsRedBank.client.ts @@ -423,11 +423,13 @@ export interface MarsRedBankInterface extends MarsRedBankReadOnlyInterface { accountId, amount, denom, + liquidationRelated, recipient, }: { accountId?: string amount?: Uint128 denom: string + liquidationRelated?: boolean recipient?: string }, fee?: number | StdFee | 'auto', @@ -657,11 +659,13 @@ export class MarsRedBankClient extends MarsRedBankQueryClient implements MarsRed accountId, amount, denom, + liquidationRelated, recipient, }: { accountId?: string amount?: Uint128 denom: string + liquidationRelated?: boolean recipient?: string }, fee: number | StdFee | 'auto' = 'auto', @@ -676,6 +680,7 @@ export class MarsRedBankClient extends MarsRedBankQueryClient implements MarsRed account_id: accountId, amount, denom, + liquidation_related: liquidationRelated, recipient, }, }, diff --git a/scripts/types/generated/mars-red-bank/MarsRedBank.react-query.ts b/scripts/types/generated/mars-red-bank/MarsRedBank.react-query.ts index 4579f2509..fa1f1ccae 100644 --- a/scripts/types/generated/mars-red-bank/MarsRedBank.react-query.ts +++ b/scripts/types/generated/mars-red-bank/MarsRedBank.react-query.ts @@ -580,6 +580,7 @@ export interface MarsRedBankWithdrawMutation { accountId?: string amount?: Uint128 denom: string + liquidationRelated?: boolean recipient?: string } args?: { diff --git a/scripts/types/generated/mars-red-bank/MarsRedBank.types.ts b/scripts/types/generated/mars-red-bank/MarsRedBank.types.ts index 6c177061b..b19096d67 100644 --- a/scripts/types/generated/mars-red-bank/MarsRedBank.types.ts +++ b/scripts/types/generated/mars-red-bank/MarsRedBank.types.ts @@ -50,6 +50,7 @@ export type ExecuteMsg = account_id?: string | null amount?: Uint128 | null denom: string + liquidation_related?: boolean | null recipient?: string | null } }