From 8914bd748f3687f92f1b0a9575d3372dbe167089 Mon Sep 17 00:00:00 2001 From: piobab Date: Thu, 22 Feb 2024 10:20:24 +0100 Subject: [PATCH] Fix inflated collateral (#354) (#361) --- Cargo.lock | 2 +- .../tests/prop_tests.proptest-regressions | 15 ------------- contracts/red-bank/Cargo.toml | 2 +- contracts/red-bank/src/contract.rs | 9 ++++++-- contracts/red-bank/src/error.rs | 5 ++++- contracts/red-bank/src/execute.rs | 10 +++++++-- contracts/red-bank/src/interest_rates.rs | 7 ++++++- contracts/red-bank/src/lib.rs | 1 + contracts/red-bank/src/migrations/mod.rs | 1 + contracts/red-bank/src/migrations/v1_2_1.rs | 21 +++++++++++++++++++ .../mars-oracle-wasm/mars-oracle-wasm.json | 2 +- schemas/mars-red-bank/mars-red-bank.json | 2 +- 12 files changed, 52 insertions(+), 25 deletions(-) delete mode 100644 contracts/oracle/wasm/tests/prop_tests.proptest-regressions create mode 100644 contracts/red-bank/src/migrations/mod.rs create mode 100644 contracts/red-bank/src/migrations/v1_2_1.rs diff --git a/Cargo.lock b/Cargo.lock index c953939d..6a2aef3c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2078,7 +2078,7 @@ dependencies = [ [[package]] name = "mars-red-bank" -version = "1.2.0" +version = "1.2.1" dependencies = [ "cosmwasm-schema", "cosmwasm-std", diff --git a/contracts/oracle/wasm/tests/prop_tests.proptest-regressions b/contracts/oracle/wasm/tests/prop_tests.proptest-regressions deleted file mode 100644 index d9c4eea3..00000000 --- a/contracts/oracle/wasm/tests/prop_tests.proptest-regressions +++ /dev/null @@ -1,15 +0,0 @@ -# Seeds for failure cases proptest has generated in the past. It is -# automatically read and these particular cases re-run before any -# novel cases are generated. -# -# It is recommended to check this file in to source control so that -# everyone who runs the test benefits from these saved cases. -cc dfaa3bc082c4bd0e6e6785f7cc41bccf5ff8454817e3541e03f9610b16fd891c # shrinks to pair_type = Xyk, pair_denoms = ["uatom", "uatom"], base_denom_index = 0, route_prices = [("uatom", Decimal(0))], register_routes = false -cc ff448d0e7a8b4e91c6c668325d60ed494de44be55fda33ecc379cba616e20f85 # shrinks to pair_type = Xyk, (pair_denoms, route_prices) = (["uosmo", "stake"], [("stake", Decimal(0)), ("stake", Decimal(0.000000004585472013))]) -cc 5ca64eeb9f8cb0df4166ea7782ec07d91492eee50da8160b1342f6e8f4f33cfe # shrinks to pair_type = Xyk, (pair_denoms, route_prices) = (["stake", "uatom"], [("uatom", Decimal(0.637403151169969837)), ("stake", Decimal(0.495188105830810358))]) -cc 122d1c7329103011810193f8f25f5908c783eed3271f56b7c00f14e11422aeba # shrinks to pair_type = Xyk, (pair_denoms, route_prices) = (["uosmo", "stake"], [("stake", Decimal(132373101975.866291703926105585)), ("uatom", Decimal(552431738294.751627746132883125))]) -cc 6d24c61ba6a263d4d4f0e29f8e2a6c16db3518d2d271202f2a17ac595339cb4f # shrinks to pair_type = Xyk, (pair_denoms, route_prices) = (["stake", "uion"], [("uion", Decimal(7040706654.440918446759799961)), ("uatom", Decimal(1483941554.657027178575457782)), ("uosmo", Decimal(1833715528.085063919419402131))]) -cc ba1ad666b045dcc03e1fd28f4d45f10c4f54611eac4b65c7eafbc37507572997 # shrinks to pair_type = Stable, (pair_denoms, route_prices) = (["uosmo", "uatom"], []), initial_liq = [1, 1], (window_size, tolerance) = (2, 0) -cc 9ad2ce2c26a6c085aa252fee5b122324fcfda2fcd470fbe206174da2389f47ab # shrinks to pair_type = Xyk, (pair_denoms, route_prices) = (["uatom", "uosmo"], []), initial_liq = [10822962050445088126871, 10822962036372087568463], (window_size, tolerance) = (6, 0) -cc b4ff0f2eb1a0d677fc1972633f2c2a381e68eb54965501ff58605b81f0093732 # shrinks to pair_type = Xyk, (pair_denoms, route_prices) = (["stake", "uatom"], []), initial_liq = [240051541009477748141810, 6721157557512798311], (window_size, tolerance) = (860495, 38535) -cc 72e53f8b940ea84ad9709479facdc45af95a67f0b6447bbc316ac5ea02152f57 # shrinks to pair_type = Stable, (pair_denoms, route_prices) = (["uosmo", "uatom"], []), initial_liq = [54095484775203625044646, 512553686986456532], (window_size, tolerance) = (82800, 12299) diff --git a/contracts/red-bank/Cargo.toml b/contracts/red-bank/Cargo.toml index 1d56efd1..253d50dc 100644 --- a/contracts/red-bank/Cargo.toml +++ b/contracts/red-bank/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "mars-red-bank" description = "A smart contract that manages asset deposit, borrowing, and liquidations" -version = { workspace = true } +version = "1.2.1" authors = { workspace = true } edition = { workspace = true } license = { workspace = true } diff --git a/contracts/red-bank/src/contract.rs b/contracts/red-bank/src/contract.rs index a5daa94b..ba2ff3a8 100644 --- a/contracts/red-bank/src/contract.rs +++ b/contracts/red-bank/src/contract.rs @@ -1,9 +1,9 @@ use cosmwasm_std::{ - entry_point, to_json_binary, Binary, Deps, DepsMut, Env, MessageInfo, Response, + entry_point, to_json_binary, Binary, Deps, DepsMut, Empty, Env, MessageInfo, Response, }; use mars_red_bank_types::red_bank::{ExecuteMsg, InstantiateMsg, QueryMsg}; -use crate::{error::ContractError, execute, query}; +use crate::{error::ContractError, execute, migrations, query}; #[entry_point] pub fn instantiate( @@ -202,3 +202,8 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> Result Result { + migrations::v1_2_1::migrate(deps) +} diff --git a/contracts/red-bank/src/error.rs b/contracts/red-bank/src/error.rs index a65dd259..504ed77a 100644 --- a/contracts/red-bank/src/error.rs +++ b/contracts/red-bank/src/error.rs @@ -29,6 +29,9 @@ pub enum ContractError { #[error("{0}")] Health(#[from] HealthError), + #[error("{0}")] + Version(#[from] cw2::VersionError), + #[error("Price not found for asset: {denom:?}")] PriceNotFound { denom: String, @@ -64,7 +67,7 @@ pub enum ContractError { #[error("Cannot have 0 as liquidity index")] InvalidLiquidityIndex {}, - #[error("Borrow amount must be greater than 0 and less or equal available collateral (asset: {denom:?})")] + #[error("Borrow amount must be greater than 0 and less or equal available liquidity (asset: {denom:?})")] InvalidBorrowAmount { denom: String, }, diff --git a/contracts/red-bank/src/execute.rs b/contracts/red-bank/src/execute.rs index 9507d5ec..9c19b5f1 100644 --- a/contracts/red-bank/src/execute.rs +++ b/contracts/red-bank/src/execute.rs @@ -583,9 +583,15 @@ pub fn borrow( &borrow_market, env.block.time.seconds(), )?; + let debt_balance_before = get_underlying_debt_amount( + borrow_market.debt_total_scaled, + &borrow_market, + env.block.time.seconds(), + )?; - // Cannot borrow zero amount or more than available collateral - if borrow_amount.is_zero() || borrow_amount > collateral_balance_before { + // Cannot borrow zero amount or more than available liquidity + let available_liquidity = collateral_balance_before.checked_sub(debt_balance_before)?; + if borrow_amount.is_zero() || borrow_amount > available_liquidity { return Err(ContractError::InvalidBorrowAmount { denom, }); diff --git a/contracts/red-bank/src/interest_rates.rs b/contracts/red-bank/src/interest_rates.rs index ce01a6a4..98145832 100644 --- a/contracts/red-bank/src/interest_rates.rs +++ b/contracts/red-bank/src/interest_rates.rs @@ -287,12 +287,17 @@ pub fn update_interest_rates( let total_debt = get_underlying_debt_amount(market.debt_total_scaled, market, current_timestamp)?; - let current_utilization_rate = if !total_collateral.is_zero() { + let mut current_utilization_rate = if !total_collateral.is_zero() { Decimal::from_ratio(total_debt, total_collateral) } else { Decimal::zero() }; + // Limit utilization_rate to 100%. + // With the current code it should hopefully never happen that it gets calculated to more than 100%, + // but better be safe than sorry. + current_utilization_rate = current_utilization_rate.min(Decimal::one()); + market.update_interest_rates(current_utilization_rate)?; Ok(response.add_event(build_interests_updated_event(&market.denom, market))) diff --git a/contracts/red-bank/src/lib.rs b/contracts/red-bank/src/lib.rs index d3d5c1ef..048584af 100644 --- a/contracts/red-bank/src/lib.rs +++ b/contracts/red-bank/src/lib.rs @@ -4,6 +4,7 @@ pub mod error; pub mod execute; pub mod health; pub mod interest_rates; +pub mod migrations; pub mod query; pub mod state; pub mod user; diff --git a/contracts/red-bank/src/migrations/mod.rs b/contracts/red-bank/src/migrations/mod.rs new file mode 100644 index 00000000..08bf05e8 --- /dev/null +++ b/contracts/red-bank/src/migrations/mod.rs @@ -0,0 +1 @@ +pub mod v1_2_1; diff --git a/contracts/red-bank/src/migrations/v1_2_1.rs b/contracts/red-bank/src/migrations/v1_2_1.rs new file mode 100644 index 00000000..37ca4fa3 --- /dev/null +++ b/contracts/red-bank/src/migrations/v1_2_1.rs @@ -0,0 +1,21 @@ +use cosmwasm_std::{DepsMut, Response}; +use cw2::{assert_contract_version, set_contract_version}; + +use crate::{ + error::ContractError, + execute::{CONTRACT_NAME, CONTRACT_VERSION}, +}; + +const FROM_VERSION: &str = "1.2.0"; + +pub fn migrate(deps: DepsMut) -> Result { + // make sure we're migrating the correct contract and from the correct version + assert_contract_version(deps.storage, &format!("crates.io:{CONTRACT_NAME}"), FROM_VERSION)?; + + set_contract_version(deps.storage, format!("crates.io:{CONTRACT_NAME}"), CONTRACT_VERSION)?; + + Ok(Response::new() + .add_attribute("action", "migrate") + .add_attribute("from_version", FROM_VERSION) + .add_attribute("to_version", CONTRACT_VERSION)) +} diff --git a/schemas/mars-oracle-wasm/mars-oracle-wasm.json b/schemas/mars-oracle-wasm/mars-oracle-wasm.json index fb7bfaf9..999f38dc 100644 --- a/schemas/mars-oracle-wasm/mars-oracle-wasm.json +++ b/schemas/mars-oracle-wasm/mars-oracle-wasm.json @@ -1,6 +1,6 @@ { "contract_name": "mars-oracle-wasm", - "contract_version": "1.2.0", + "contract_version": "1.2.1", "idl_version": "1.0.0", "instantiate": { "$schema": "http://json-schema.org/draft-07/schema#", diff --git a/schemas/mars-red-bank/mars-red-bank.json b/schemas/mars-red-bank/mars-red-bank.json index 5f07b26c..c515c0ee 100644 --- a/schemas/mars-red-bank/mars-red-bank.json +++ b/schemas/mars-red-bank/mars-red-bank.json @@ -1,6 +1,6 @@ { "contract_name": "mars-red-bank", - "contract_version": "1.2.0", + "contract_version": "1.2.1", "idl_version": "1.0.0", "instantiate": { "$schema": "http://json-schema.org/draft-07/schema#",