Skip to content

Commit

Permalink
Managed vault - add share price to VaultInfo query (#429)
Browse files Browse the repository at this point in the history
* Add share price.

* Add tests.

* Update comment for share price.
  • Loading branch information
piobab authored Aug 9, 2024
1 parent 61b6d0e commit c106b90
Show file tree
Hide file tree
Showing 6 changed files with 75 additions and 11 deletions.
16 changes: 15 additions & 1 deletion contracts/vault/src/msg.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use cosmwasm_schema::cw_serde;
use cosmwasm_std::Uint128;
use cosmwasm_std::{Decimal, Uint128};
use cw_vault_standard::{VaultStandardExecuteMsg, VaultStandardQueryMsg};

use crate::performance_fee::PerformanceFeeConfig;
Expand Down Expand Up @@ -98,6 +98,20 @@ pub struct VaultInfoResponseExt {

/// Performance fee configuration
pub performance_fee_config: PerformanceFeeConfig,

/// Total base tokens in the vault
pub total_base_tokens: Uint128,

/// Total vault tokens minted
pub total_vault_tokens: Uint128,

/// Current share price, representing the value of one vault token in terms of the base token.
/// It is calculated as the ratio of total base tokens in the vault to the total supply of vault tokens.
/// Denominated as a decimal value:
/// `share_price = total_base_tokens / total_vault_tokens`
/// This share price allows users to determine how many base tokens can be redeemed per vault token:
/// `base_tokens = vault_share * vault_tokens`
pub share_price: Option<Decimal>,
}

/// Unlock state for a single user
Expand Down
25 changes: 22 additions & 3 deletions contracts/vault/src/query.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use cosmwasm_std::{Addr, Deps, Order, Uint128};
use cosmwasm_std::{Addr, Decimal, Deps, Order, Uint128};
use cw_paginate::{paginate_map_query, PaginationResponse, DEFAULT_LIMIT, MAX_LIMIT};
use cw_storage_plus::Bound;

Expand All @@ -14,16 +14,35 @@ use crate::{
};

pub fn query_vault_info(deps: Deps) -> ContractResult<VaultInfoResponseExt> {
let vault_token = VAULT_TOKEN.load(deps.storage)?;
let total_vault_tokens = vault_token.query_total_supply(deps)?;

// If vault account is not set, we don't calculate share price.
// It means that the vault is not binded to any account yet.
let vault_account_id_opt = VAULT_ACC_ID.may_load(deps.storage)?;
let mut total_base_tokens = Uint128::zero();
let mut share_price = None;
if vault_account_id_opt.is_some() {
total_base_tokens = total_base_tokens_in_account(deps)?;
share_price = if total_vault_tokens.is_zero() {
None
} else {
Some(Decimal::checked_from_ratio(total_base_tokens, total_vault_tokens)?)
};
}
Ok(VaultInfoResponseExt {
base_token: BASE_TOKEN.load(deps.storage)?,
vault_token: VAULT_TOKEN.load(deps.storage)?.to_string(),
vault_token: vault_token.to_string(),
title: TITLE.may_load(deps.storage)?,
subtitle: SUBTITLE.may_load(deps.storage)?,
description: DESCRIPTION.may_load(deps.storage)?,
credit_manager: CREDIT_MANAGER.load(deps.storage)?,
vault_account_id: VAULT_ACC_ID.may_load(deps.storage)?,
vault_account_id: vault_account_id_opt,
cooldown_period: COOLDOWN_PERIOD.load(deps.storage)?,
performance_fee_config: PERFORMANCE_FEE_CONFIG.load(deps.storage)?,
total_base_tokens,
total_vault_tokens,
share_price,
})
}

Expand Down
7 changes: 5 additions & 2 deletions contracts/vault/tests/tests/test_binding.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use cosmwasm_std::{coin, Addr, Decimal};
use cosmwasm_std::{coin, Addr, Decimal, Uint128};
use mars_types::health::AccountKind;
use mars_vault::{
error::ContractError, msg::VaultInfoResponseExt, performance_fee::PerformanceFeeConfig,
Expand Down Expand Up @@ -56,7 +56,10 @@ fn only_credit_manager_can_bind_account() {
performance_fee_config: PerformanceFeeConfig {
fee_rate: Decimal::zero(),
withdrawal_interval: 0
}
},
total_base_tokens: Uint128::zero(),
total_vault_tokens: Uint128::zero(),
share_price: None,
}
)
}
Expand Down
22 changes: 20 additions & 2 deletions contracts/vault/tests/tests/test_deposit.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use cosmwasm_std::{coin, Addr, Uint128};
use cosmwasm_std::{coin, Addr, Decimal, Uint128};
use cw_utils::PaymentError;
use mars_types::health::AccountKind;
use mars_vault::error::ContractError;
Expand All @@ -7,7 +7,11 @@ use super::{
helpers::{AccountToFund, MockEnv},
vault_helpers::{assert_vault_err, execute_deposit},
};
use crate::tests::{helpers::deploy_managed_vault, vault_helpers::query_vault_info};
use crate::tests::{
helpers::deploy_managed_vault,
test_redeem::uusdc_info,
vault_helpers::{query_total_assets, query_total_vault_token_supply, query_vault_info},
};

#[test]
fn deposit_invalid_funds() {
Expand Down Expand Up @@ -105,6 +109,7 @@ fn deposit_succeded() {
let user = Addr::unchecked("user");
let user_funded_amt = Uint128::new(1_000_000_000);
let mut mock = MockEnv::new()
.set_params(&[uusdc_info()])
.fund_account(AccountToFund {
addr: fund_manager.clone(),
funds: vec![coin(1_000_000_000, "untrn")],
Expand Down Expand Up @@ -165,4 +170,17 @@ fn deposit_succeded() {
let assets_res = res.deposits.first().unwrap();
assert_eq!(assets_res.amount, deposited_amt);
assert_eq!(assets_res.denom, "uusdc".to_string());

// check total base/vault tokens and share price
let vault_info_res = query_vault_info(&mock, &managed_vault_addr);
let total_base_tokens = query_total_assets(&mock, &managed_vault_addr);
let total_vault_tokens = query_total_vault_token_supply(&mock, &managed_vault_addr);
assert_eq!(total_base_tokens, deposited_amt);
assert_eq!(total_vault_tokens, user_vault_token_balance);
assert_eq!(vault_info_res.total_base_tokens, total_base_tokens);
assert_eq!(vault_info_res.total_vault_tokens, total_vault_tokens);
assert_eq!(
vault_info_res.share_price,
Some(Decimal::from_ratio(total_base_tokens, total_vault_tokens))
);
}
12 changes: 9 additions & 3 deletions contracts/vault/tests/tests/test_instantiate.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::str::FromStr;

use anyhow::Result as AnyResult;
use cosmwasm_std::{coin, Addr, Decimal};
use cosmwasm_std::{coin, Addr, Decimal, Uint128};
use cw_multi_test::Executor;
use mars_utils::error::ValidationError;
use mars_vault::{
Expand Down Expand Up @@ -42,7 +42,10 @@ fn instantiate_with_empty_metadata() {
performance_fee_config: PerformanceFeeConfig {
fee_rate: Decimal::zero(),
withdrawal_interval: 0
}
},
total_base_tokens: Uint128::zero(),
total_vault_tokens: Uint128::zero(),
share_price: None,
}
)
}
Expand Down Expand Up @@ -99,7 +102,10 @@ fn instantiate_with_metadata() {
performance_fee_config: PerformanceFeeConfig {
fee_rate: Decimal::from_str("0.000046287042457349").unwrap(),
withdrawal_interval: 1563,
}
},
total_base_tokens: Uint128::zero(),
total_vault_tokens: Uint128::zero(),
share_price: None,
}
)
}
Expand Down
4 changes: 4 additions & 0 deletions contracts/vault/tests/tests/vault_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,10 @@ pub fn query_vault_info(mock_env: &MockEnv, vault: &Addr) -> VaultInfoResponseEx
.unwrap()
}

pub fn query_total_assets(mock_env: &MockEnv, vault: &Addr) -> Uint128 {
mock_env.app.wrap().query_wasm_smart(vault.to_string(), &QueryMsg::TotalAssets {}).unwrap()
}

pub fn query_total_vault_token_supply(mock_env: &MockEnv, vault: &Addr) -> Uint128 {
mock_env
.app
Expand Down

0 comments on commit c106b90

Please sign in to comment.