diff --git a/Cargo.lock b/Cargo.lock index 8289ed5..9b03de7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -185,7 +185,7 @@ dependencies = [ [[package]] name = "astroport-on-osmosis" -version = "1.1.1" +version = "1.1.2" dependencies = [ "astroport 3.12.1", "cosmwasm-schema", @@ -225,7 +225,7 @@ dependencies = [ [[package]] name = "astroport-pcl-osmo" -version = "1.0.2" +version = "1.0.3" dependencies = [ "anyhow", "astroport 3.12.1", @@ -505,9 +505,9 @@ dependencies = [ [[package]] name = "cosmwasm-crypto" -version = "1.5.3" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9934c79e58d9676edfd592557dee765d2a6ef54c09d5aa2edb06156b00148966" +checksum = "dd50718a2b6830ce9eb5d465de5a018a12e71729d66b70807ce97e6dd14f931d" dependencies = [ "digest 0.10.7", "ecdsa", @@ -519,9 +519,9 @@ dependencies = [ [[package]] name = "cosmwasm-derive" -version = "1.5.3" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc5e72e330bd3bdab11c52b5ecbdeb6a8697a004c57964caeb5d876f0b088b3c" +checksum = "242e98e7a231c122e08f300d9db3262d1007b51758a8732cd6210b3e9faa4f3a" dependencies = [ "syn 1.0.109", ] @@ -552,9 +552,9 @@ dependencies = [ [[package]] name = "cosmwasm-std" -version = "1.5.3" +version = "1.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef8666e572a3a2519010dde88c04d16e9339ae751b56b2bb35081fe3f7d6be74" +checksum = "78c1556156fdf892a55cced6115968b961eaaadd6f724a2c2cb7d1e168e32dd3" dependencies = [ "base64", "bech32", diff --git a/contracts/factory/tests/querier.rs b/contracts/factory/tests/querier.rs index 0f22377..a455076 100644 --- a/contracts/factory/tests/querier.rs +++ b/contracts/factory/tests/querier.rs @@ -30,6 +30,12 @@ pub struct MockedStargateQuerier<'a> { pair_infos: HashMap<&'a str, PairInfo>, } +impl<'a> Default for MockedStargateQuerier<'a> { + fn default() -> Self { + Self::new() + } +} + impl<'a> MockedStargateQuerier<'a> { pub fn new() -> Self { Self { diff --git a/contracts/maker/src/utils.rs b/contracts/maker/src/utils.rs index 079f66a..9ac4ce1 100644 --- a/contracts/maker/src/utils.rs +++ b/contracts/maker/src/utils.rs @@ -45,7 +45,7 @@ pub fn query_out_amount( for step in steps { let step_price = query_spot_price(querier, step.pool_id, &denom_in, &step.token_out_denom)?; price = price.checked_mul(step_price)?; - denom_in = step.token_out_denom.clone(); + denom_in.clone_from(&step.token_out_denom); } let out_amount = coin_in diff --git a/contracts/maker/tests/common/osmosis_ext.rs b/contracts/maker/tests/common/osmosis_ext.rs index 033b010..dffe2af 100644 --- a/contracts/maker/tests/common/osmosis_ext.rs +++ b/contracts/maker/tests/common/osmosis_ext.rs @@ -329,7 +329,7 @@ impl Stargate for OsmosisStargate { let contract_address = self.cw_pools.borrow()[&inner.pool_id].clone(); let querier = QuerierWrapper::::new(querier); let spot_price: SpotPriceResponse = querier.query_wasm_smart( - &contract_address, + contract_address, &QueryMsg::SpotPrice { quote_asset_denom: inner.quote_asset_denom.to_string(), base_asset_denom: inner.quote_asset_denom.to_string(), diff --git a/contracts/pair_concentrated/Cargo.toml b/contracts/pair_concentrated/Cargo.toml index df0c88d..de76deb 100644 --- a/contracts/pair_concentrated/Cargo.toml +++ b/contracts/pair_concentrated/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "astroport-pcl-osmo" -version = "1.0.2" +version = "1.0.3" authors = ["Astroport"] edition = "2021" description = "Astroport passive concentrated pair contract for Osmosis" diff --git a/contracts/pair_concentrated/src/contract.rs b/contracts/pair_concentrated/src/contract.rs index f7d98e4..8302579 100644 --- a/contracts/pair_concentrated/src/contract.rs +++ b/contracts/pair_concentrated/src/contract.rs @@ -881,7 +881,7 @@ pub fn migrate(deps: DepsMut, _env: Env, _msg: Empty) -> Result match contract_version.version.as_ref() { - "1.0.0" | "1.0.1" => {} + "1.0.0" | "1.0.1" | "1.0.2" => {} _ => return Err(ContractError::MigrationError {}), }, _ => return Err(ContractError::MigrationError {}), diff --git a/contracts/pair_concentrated/src/queries.rs b/contracts/pair_concentrated/src/queries.rs index b531056..4306fa3 100644 --- a/contracts/pair_concentrated/src/queries.rs +++ b/contracts/pair_concentrated/src/queries.rs @@ -1,6 +1,6 @@ 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::observation::query_observation; use astroport::pair::{ ConfigResponse, PoolResponse, ReverseSimulationResponse, SimulationResponse, }; @@ -15,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, StdError, StdResult, Uint128, - Uint64, + ensure, to_json_binary, Binary, Decimal, Decimal256, DecimalRangeExceeded, Deps, Env, StdError, + StdResult, Uint128, Uint64, }; use itertools::Itertools; @@ -194,8 +194,30 @@ pub fn query(deps: Deps, env: Env, msg: QueryMsg) -> StdResult { // Calculate average from buy and sell prices let spot_price = (get_spot_price(0)? + get_spot_price(1)?) / TWO; + // Denormalize the price + let quote_precision = precisions + .get_precision(&AssetInfo::native("e_asset_denom)) + .map_err(|err| StdError::generic_err(err.to_string()))?; + let base_precision = precisions + .get_precision(&AssetInfo::native(&base_asset_denom)) + .map_err(|err| StdError::generic_err(err.to_string()))?; + let denorm_price = spot_price + * Decimal256::from_ratio( + 10u128.pow(quote_precision.into()), + 10u128.pow(base_precision.into()), + ); + + ensure!( + spot_price.is_zero() || !denorm_price.is_zero(), + StdError::generic_err(format!( + "Normalized price {spot_price} became zero after denormalization" + )) + ); + to_json_binary(&SpotPriceResponse { - spot_price: try_dec256_into_dec(spot_price)?, + spot_price: denorm_price + .try_into() + .map_err(|err: DecimalRangeExceeded| StdError::generic_err(err.to_string()))?, }) } // Osmosis confirmed we can safely set 0% here. diff --git a/contracts/pair_concentrated/tests/common/helper.rs b/contracts/pair_concentrated/tests/common/helper.rs index 64377dd..93e3579 100644 --- a/contracts/pair_concentrated/tests/common/helper.rs +++ b/contracts/pair_concentrated/tests/common/helper.rs @@ -109,7 +109,7 @@ pub fn init_native_coins(test_coins: &[TestCoin]) -> Vec { .iter() .filter_map(|test_coin| match test_coin { TestCoin::Native(name) => { - let init_balance = INIT_BALANCE * 10u128.pow(NATIVE_TOKEN_PRECISION as u32); + let init_balance = u128::MAX / 2; Some(coin(init_balance, name)) } _ => None, @@ -271,6 +271,7 @@ impl Helper { ("uusd".to_owned(), 6), ("rc".to_owned(), 6), ("foo".to_owned(), 5), + ("eth".to_owned(), 18), ], }, &[], diff --git a/contracts/pair_concentrated/tests/pair_concentrated_integration.rs b/contracts/pair_concentrated/tests/pair_concentrated_integration.rs index b28057a..c55ebf7 100644 --- a/contracts/pair_concentrated/tests/pair_concentrated_integration.rs +++ b/contracts/pair_concentrated/tests/pair_concentrated_integration.rs @@ -861,8 +861,7 @@ fn check_prices() { let helper = Helper::new(&owner, test_coins, common_pcl_params()).unwrap(); let err = helper.query_prices().unwrap_err(); - assert_eq!(StdError::generic_err("Querier contract error: Generic error: Not implemented.Use { \"observe\" : { \"seconds_ago\" : ... } } instead.") - , err); + assert!(err.to_string().contains("Not implemented.Use")); } #[test] @@ -1554,6 +1553,97 @@ fn test_osmosis_specific_queries() { ); } +#[test] +fn test_spot_price_diff_decimals() { + let owner = Addr::unchecked("owner"); + + let test_coins = vec![TestCoin::native("uusd"), TestCoin::native("eth")]; + + let mut helper = Helper::new( + &owner, + test_coins.clone(), + ConcentratedPoolParams { + price_scale: Decimal::from_ratio(3000u16, 1u8), + ..common_pcl_params() + }, + ) + .unwrap(); + + let provide_assets = [ + helper.assets[&test_coins[0]].with_balance(3_000_000 * 1e6 as u128), + helper.assets[&test_coins[1]].with_balance(1_000 * 1e18 as u128), + ]; + helper.give_me_money(&provide_assets, &owner); + helper.provide_liquidity(&owner, &provide_assets).unwrap(); + + let resp = helper + .app + .wrap() + .query_wasm_smart::( + &helper.pair_addr, + &QueryMsg::SpotPrice { + quote_asset_denom: helper.assets[&test_coins[0]].to_string(), + base_asset_denom: helper.assets[&test_coins[1]].to_string(), + }, + ) + .unwrap(); + assert_eq!(resp.spot_price.to_string(), "0.000000003000010176"); + + // query inverted price + let price = helper + .app + .wrap() + .query_wasm_smart::( + &helper.pair_addr, + &QueryMsg::SpotPrice { + quote_asset_denom: helper.assets[&test_coins[1]].to_string(), + base_asset_denom: helper.assets[&test_coins[0]].to_string(), + }, + ) + .unwrap(); + assert_eq!(price.spot_price.to_string(), "333334464.080626"); +} + +#[test] +fn test_truncated_spot_price() { + let owner = Addr::unchecked("owner"); + + let test_coins = vec![TestCoin::native("uusd"), TestCoin::native("eth")]; + + let mut helper = Helper::new( + &owner, + test_coins.clone(), + ConcentratedPoolParams { + price_scale: Decimal::from_ratio(1u128, 10000u128), + ..common_pcl_params() + }, + ) + .unwrap(); + + let provide_assets = [ + helper.assets[&test_coins[0]].with_balance(1e2 as u128), + helper.assets[&test_coins[1]].with_balance(1_000 * 1e18 as u128), + ]; + helper.give_me_money(&provide_assets, &owner); + helper.provide_liquidity(&owner, &provide_assets).unwrap(); + + let err = helper + .app + .wrap() + .query_wasm_smart::( + &helper.pair_addr, + &QueryMsg::SpotPrice { + quote_asset_denom: helper.assets[&test_coins[0]].to_string(), + base_asset_denom: helper.assets[&test_coins[1]].to_string(), + }, + ) + .unwrap_err(); + assert_eq!( + err.to_string(), + "Generic error: Querier contract error: Generic error: Normalized price 0.000000100003868184 became zero after denormalization" + ); +} + #[test] fn check_reverse_swaps() { let owner = Addr::unchecked("owner"); diff --git a/e2e_tests/src/helper.rs b/e2e_tests/src/helper.rs index cecf0f8..b19bfcf 100644 --- a/e2e_tests/src/helper.rs +++ b/e2e_tests/src/helper.rs @@ -162,7 +162,7 @@ impl<'a> TestAppWrapper<'a> { &[], ) .unwrap(); - helper.coin_registry = coin_registry_address.clone(); + helper.coin_registry.clone_from(&coin_registry_address); helper.astro_denom = helper.register_and_mint("astro", 1_000_000_000_000, 6, None); diff --git a/packages/astroport_on_osmosis/Cargo.toml b/packages/astroport_on_osmosis/Cargo.toml index bcbac08..ec865e8 100644 --- a/packages/astroport_on_osmosis/Cargo.toml +++ b/packages/astroport_on_osmosis/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "astroport-on-osmosis" -version = "1.1.1" +version = "1.1.2" authors = ["Astroport"] edition = "2021" description = "External API of Astroport contracts on Osmosis"