Skip to content

Commit

Permalink
feat(pcl): rework spot price query (#15)
Browse files Browse the repository at this point in the history
* feat(pcl): rework spot price query

* bump version
  • Loading branch information
epanchee authored Apr 25, 2024
1 parent ac96949 commit d98f9dd
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 33 deletions.
2 changes: 1 addition & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion contracts/maker/tests/maker_integration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,7 @@ fn test_collect() {
},
)
.unwrap();
assert_eq!(estimated_astro_out.u128(), 997399);
assert_eq!(estimated_astro_out.u128(), 1000002);
}

#[test]
Expand Down
2 changes: 1 addition & 1 deletion contracts/pair_concentrated/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "astroport-pcl-osmo"
version = "1.0.1"
version = "1.0.2"
authors = ["Astroport"]
edition = "2021"
description = "Astroport passive concentrated pair contract for Osmosis"
Expand Down
2 changes: 2 additions & 0 deletions contracts/pair_concentrated/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -887,6 +887,8 @@ pub fn migrate(deps: DepsMut, _env: Env, _msg: Empty) -> Result<Response, Contra
_ => return Err(ContractError::MigrationError {}),
};

set_contract_version(deps.storage, CONTRACT_NAME, CONTRACT_VERSION)?;

Ok(Response::new()
.add_attribute("previous_contract_name", &contract_version.contract)
.add_attribute("previous_contract_version", &contract_version.version)
Expand Down
90 changes: 64 additions & 26 deletions contracts/pair_concentrated/src/queries.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
use astroport::asset::{native_asset_info, Asset, AssetInfo, AssetInfoExt};
use astroport::asset::{native_asset_info, Asset, AssetInfo, AssetInfoExt, Decimal256Ext};
use astroport::cosmwasm_ext::{DecimalToInteger, IntegerToDecimal};
use astroport::observation::{query_observation, try_dec256_into_dec};
use astroport::pair::{
ConfigResponse, PoolResponse, ReverseSimulationResponse, SimulationResponse,
};
use astroport::pair_concentrated::ConcentratedPoolConfig;
use astroport::querier::{query_factory_config, query_fee_info};
use astroport_pcl_common::consts::{OFFER_PERCENT, TWO};
use astroport_pcl_common::state::Precisions;
use astroport_pcl_common::utils::{
before_swap_check, compute_offer_amount, compute_swap, get_share_in_assets,
Expand All @@ -14,8 +15,8 @@ use astroport_pcl_common::{calc_d, get_xcp};
#[cfg(not(feature = "library"))]
use cosmwasm_std::entry_point;
use cosmwasm_std::{
ensure, to_json_binary, Binary, Decimal, Decimal256, Deps, Env, Fraction, StdError, StdResult,
Uint128, Uint64,
ensure, to_json_binary, Binary, Decimal, Decimal256, Deps, Env, StdError, StdResult, Uint128,
Uint64,
};
use itertools::Itertools;

Expand Down Expand Up @@ -122,15 +123,27 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult<Binary> {
base_asset_denom,
} => {
let config = CONFIG.load(deps.storage)?;
let pool_denoms = config
let pools = config
.pair_info
.asset_infos
.into_iter()
.map(|asset_info| match asset_info {
.query_pools(&deps.querier, &env.contract.address)?;
let pool_denoms = pools
.iter()
.map(|asset| match &asset.info {
AssetInfo::NativeToken { denom } => denom,
AssetInfo::Token { .. } => unreachable!("Token assets are not supported"),
})
.cloned()
.collect_vec();
let precisions = Precisions::new(deps.storage)?;
let reserves = pools
.iter()
.map(|asset| {
let precision = precisions
.get_precision(&asset.info)
.map_err(|err| StdError::generic_err(err.to_string()))?;
Decimal256::with_precision(asset.amount, precision)
})
.collect::<StdResult<Vec<_>>>()?;

ensure!(
pool_denoms.contains(&quote_asset_denom) && pool_denoms.contains(&base_asset_denom),
Expand All @@ -140,25 +153,50 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult<Binary> {
))
);

let spot_price = query_observation(deps, env, OBSERVATIONS, 0)
.map(|observation| {
if pool_denoms[0] == quote_asset_denom && pool_denoms[1] == base_asset_denom {
observation.price
} else {
observation.price.inv().unwrap_or_default()
}
})
.or_else(|_| -> StdResult<_> {
let price_scale =
try_dec256_into_dec(config.pool_state.price_state.price_scale)?;
if pool_denoms[0] == quote_asset_denom && pool_denoms[1] == base_asset_denom {
Ok(price_scale)
} else {
Ok(price_scale.inv().unwrap_or_default())
}
})?;

to_json_binary(&SpotPriceResponse { spot_price })
let maker_fee_share = query_fee_info(
&deps.querier,
&config.factory_addr,
config.pair_info.pair_type.clone(),
)
.map(|fee_info| {
if fee_info.fee_address.is_some() {
fee_info.maker_fee_rate
} else {
Decimal::zero()
}
})?;

let get_spot_price = |offer_ind: usize| -> StdResult<Decimal256> {
let mut offer_amount = reserves[offer_ind] * OFFER_PERCENT;
if offer_amount.is_zero() {
offer_amount = Decimal256::raw(1u128);
}

let swap_result = compute_swap(
&reserves,
offer_amount,
1 ^ offer_ind,
&config,
&env,
maker_fee_share.into(),
Decimal256::zero(),
)?;

let price = if pool_denoms[offer_ind] == quote_asset_denom {
offer_amount / swap_result.dy
} else {
swap_result.dy / offer_amount
};

Ok(price)
};

// Calculate average from buy and sell prices
let spot_price = (get_spot_price(0)? + get_spot_price(1)?) / TWO;

to_json_binary(&SpotPriceResponse {
spot_price: try_dec256_into_dec(spot_price)?,
})
}
// Osmosis confirmed we can safely set 0% here.
// Osmosis team: it was needed due to Osmosis legacy multi hop osmo swap fee reduction where
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ use astroport::pair_concentrated::{
};
use astroport_pcl_common::consts::{AMP_MAX, AMP_MIN, MA_HALF_TIME_LIMITS};
use astroport_pcl_common::error::PclError;
use cosmwasm_std::{Addr, Decimal, Fraction, StdError, Uint128};
use cosmwasm_std::{Addr, Decimal, StdError, Uint128};
use cw_multi_test::{next_block, Executor};
use itertools::Itertools;

Expand Down Expand Up @@ -1517,8 +1517,7 @@ fn test_osmosis_specific_queries() {
},
)
.unwrap();
let astro_resp = helper.observe_price(0).unwrap();
assert_eq!(osm_resp.spot_price, astro_resp);
assert_eq!(osm_resp.spot_price.to_string(), "1.00118745790560783");

// query inverted price
let osm_resp = helper
Expand All @@ -1532,7 +1531,7 @@ fn test_osmosis_specific_queries() {
},
)
.unwrap();
assert_eq!(osm_resp.spot_price, astro_resp.inv().unwrap());
assert_eq!(osm_resp.spot_price.to_string(), "0.998824162472793607");

let err = helper
.app
Expand Down

0 comments on commit d98f9dd

Please sign in to comment.