From a881bda7b901771c3fde8b4bb6b7bf9865fab19a Mon Sep 17 00:00:00 2001 From: mdjakovic0920 Date: Wed, 15 Jan 2025 15:55:18 +0000 Subject: [PATCH 1/6] fix: resolve query error caused by float types --- .../math/andromeda-curve/src/contract.rs | 53 ++++++++++++++----- .../math/andromeda-curve/src/testing/mock.rs | 2 +- .../math/andromeda-curve/src/testing/tests.rs | 48 +++++++++++------ packages/andromeda-math/src/curve.rs | 2 +- 4 files changed, 75 insertions(+), 30 deletions(-) diff --git a/contracts/math/andromeda-curve/src/contract.rs b/contracts/math/andromeda-curve/src/contract.rs index 2664b2379..379d52704 100644 --- a/contracts/math/andromeda-curve/src/contract.rs +++ b/contracts/math/andromeda-curve/src/contract.rs @@ -15,7 +15,8 @@ use andromeda_std::{ }; use cosmwasm_std::{ - entry_point, Binary, Deps, DepsMut, Env, MessageInfo, Reply, Response, StdError, Storage, + entry_point, Binary, Decimal, Deps, DepsMut, Env, MessageInfo, Reply, Response, StdError, + Storage, }; use cw_utils::nonpayable; @@ -170,7 +171,7 @@ pub fn query_curve_config(storage: &dyn Storage) -> Result Result { let curve_config = CURVE_CONFIG.load(storage)?; @@ -181,18 +182,44 @@ pub fn query_plot_y_from_x( multiple_variable_value, constant_value, } => { - let curve_id_f64 = match curve_type { - CurveType::Growth => 1_f64, - CurveType::Decay => -1_f64, + let base_value_decimal = Decimal::percent(base_value * 100); + let constant_value_decimal = + Decimal::percent(constant_value.unwrap_or(DEFAULT_CONSTANT_VALUE) * 100); + let multiple_variable_value_decimal = Decimal::percent( + multiple_variable_value.unwrap_or(DEFAULT_MULTIPLE_VARIABLE_VALUE) * 100, + ); + + let exponent_value = multiple_variable_value_decimal + .checked_mul(Decimal::from_atomics(x_value, 18).map_err(|e| { + ContractError::CustomError { + msg: format!("Failed to create decimal for the exponent_value: {:?}", e), + } + })?) + .map_err(|_| ContractError::Overflow {})? + .atomics(); + + let exponent_u32 = + u32::try_from(exponent_value.u128()).map_err(|_| ContractError::CustomError { + msg: "Failed to convert exponent to u32.".to_string(), + })?; + + // The argument of the checked_pow() must be u32, can not be other types + let res = constant_value_decimal + .checked_mul( + base_value_decimal + .checked_pow(exponent_u32) + .map_err(|_| ContractError::Overflow {})?, + ) + .map_err(|_| ContractError::Overflow {})?; + + let res_by_curve_type = match curve_type { + CurveType::Growth => res, + CurveType::Decay => Decimal::one() + .checked_div(res) + .map_err(|_| ContractError::Underflow {})?, }; - let base_value_f64 = base_value as f64; - let constant_value_f64 = constant_value.unwrap_or(DEFAULT_CONSTANT_VALUE) as f64; - let multiple_variable_value_f64 = - multiple_variable_value.unwrap_or(DEFAULT_MULTIPLE_VARIABLE_VALUE) as f64; - - (constant_value_f64 - * base_value_f64.powf(curve_id_f64 * multiple_variable_value_f64 * x_value)) - .to_string() + + res_by_curve_type.to_string() } }; diff --git a/contracts/math/andromeda-curve/src/testing/mock.rs b/contracts/math/andromeda-curve/src/testing/mock.rs index 6f00dd32d..214734f15 100644 --- a/contracts/math/andromeda-curve/src/testing/mock.rs +++ b/contracts/math/andromeda-curve/src/testing/mock.rs @@ -78,7 +78,7 @@ pub fn query_curve_config(deps: Deps) -> Result Result { let res = query(deps, mock_env(), QueryMsg::GetPlotYFromX { x_value }); match res { diff --git a/contracts/math/andromeda-curve/src/testing/tests.rs b/contracts/math/andromeda-curve/src/testing/tests.rs index 0165f511a..3aa29f0db 100644 --- a/contracts/math/andromeda-curve/src/testing/tests.rs +++ b/contracts/math/andromeda-curve/src/testing/tests.rs @@ -154,10 +154,10 @@ fn test_query_curve_config_base_is_0() { ); } -#[test_case(2_f64, "4".to_string() ; "exp(2, 2)")] -#[test_case(3_f64, "8".to_string() ; "exp(2, 3)")] -#[test_case(4_f64, "16".to_string() ; "exp(2, 4)")] -fn test_query_plot_y_from_x_base_2_growth(input_x: f64, expected_y: String) { +#[test_case(2, "4".to_string() ; "exp(2, 2)")] +#[test_case(3, "8".to_string() ; "exp(2, 3)")] +#[test_case(4, "16".to_string() ; "exp(2, 4)")] +fn test_query_plot_y_from_x_base_2_growth(input_x: u64, expected_y: String) { let (deps, _info) = proper_initialization( CurveConfig::ExpConfig { curve_type: CurveType::Growth, @@ -169,13 +169,13 @@ fn test_query_plot_y_from_x_base_2_growth(input_x: f64, expected_y: String) { ); let res = query_plot_y_from_x(deps.as_ref(), input_x).unwrap().y_value; - assert_eq!(res, expected_y); + assert_eq!(res.to_string(), expected_y); } -#[test_case(2_f64, "9".to_string() ; "exp(3, 2)")] -#[test_case(3_f64, "27".to_string() ; "exp(3, 3)")] -#[test_case(4_f64, "81".to_string() ; "exp(3, 4)")] -fn test_query_plot_y_from_x_base_3_growth(input_x: f64, expected_y: String) { +#[test_case(2, "9".to_string() ; "exp(3, 2)")] +#[test_case(3, "27".to_string() ; "exp(3, 3)")] +#[test_case(4, "81".to_string() ; "exp(3, 4)")] +fn test_query_plot_y_from_x_base_3_growth(input_x: u64, expected_y: String) { let (deps, _info) = proper_initialization( CurveConfig::ExpConfig { curve_type: CurveType::Growth, @@ -187,13 +187,31 @@ fn test_query_plot_y_from_x_base_3_growth(input_x: f64, expected_y: String) { ); let res = query_plot_y_from_x(deps.as_ref(), input_x).unwrap().y_value; - assert_eq!(res, expected_y); + assert_eq!(res.to_string(), expected_y); } -#[test_case(2_f64, "0.25".to_string() ; "exp(1/2, 2)")] -#[test_case(3_f64, "0.125".to_string() ; "exp(1/2, 3)")] -#[test_case(4_f64, "0.0625".to_string() ; "exp(1/2, 4)")] -fn test_query_plot_y_from_x_base_2_decay(input_x: f64, expected_y: String) { +#[test_case(2, "32".to_string() ; "exp(4, 2)")] +#[test_case(3, "128".to_string() ; "exp(4, 3)")] +#[test_case(4, "512".to_string() ; "exp(4, 4)")] +fn test_query_plot_y_from_x_base_4_growth_constant_2(input_x: u64, expected_y: String) { + let (deps, _info) = proper_initialization( + CurveConfig::ExpConfig { + curve_type: CurveType::Growth, + base_value: 4, + multiple_variable_value: None, + constant_value: Some(2), + }, + None, + ); + + let res = query_plot_y_from_x(deps.as_ref(), input_x).unwrap().y_value; + assert_eq!(res.to_string(), expected_y); +} + +#[test_case(2, "0.25".to_string() ; "exp(1/2, 2)")] +#[test_case(3, "0.125".to_string() ; "exp(1/2, 3)")] +#[test_case(4, "0.0625".to_string() ; "exp(1/2, 4)")] +fn test_query_plot_y_from_x_base_2_decay(input_x: u64, expected_y: String) { let (deps, _info) = proper_initialization( CurveConfig::ExpConfig { curve_type: CurveType::Decay, @@ -205,5 +223,5 @@ fn test_query_plot_y_from_x_base_2_decay(input_x: f64, expected_y: String) { ); let res = query_plot_y_from_x(deps.as_ref(), input_x).unwrap().y_value; - assert_eq!(res, expected_y); + assert_eq!(res.to_string(), expected_y); } diff --git a/packages/andromeda-math/src/curve.rs b/packages/andromeda-math/src/curve.rs index 74e48caf5..f1d44eb9f 100644 --- a/packages/andromeda-math/src/curve.rs +++ b/packages/andromeda-math/src/curve.rs @@ -60,7 +60,7 @@ pub enum QueryMsg { #[returns(GetCurveConfigResponse)] GetCurveConfig {}, #[returns(GetPlotYFromXResponse)] - GetPlotYFromX { x_value: f64 }, + GetPlotYFromX { x_value: u64 }, } #[cw_serde] From 1dd3a0e13ba5ffeb9eb30b51be60d250803fcd5e Mon Sep 17 00:00:00 2001 From: mdjakovic0920 Date: Wed, 15 Jan 2025 15:59:23 +0000 Subject: [PATCH 2/6] updated the changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e2d07c1b5..68710f23b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -39,6 +39,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fixed wrong return attribute for SubDir Query [(#756)](https://github.com/andromedaprotocol/andromeda-core/pull/756) - fix: Prevent bypassing splitter lock via config [(#757)](https://github.com/andromedaprotocol/andromeda-core/pull/757) - Fixed Curve ADO to be able to update curve config after reset [(#762)](https://github.com/andromedaprotocol/andromeda-core/pull/762) +- Fixed Curve ADO's query error caused by Float data type [(#767)](https://github.com/andromedaprotocol/andromeda-core/pull/767) ## Release 3 From ae13b313c9dbbb41aed5513894e99a801a180a0f Mon Sep 17 00:00:00 2001 From: mdjakovic0920 Date: Wed, 15 Jan 2025 16:12:31 +0000 Subject: [PATCH 3/6] fix: changed the data type --- contracts/math/andromeda-curve/src/mock.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/math/andromeda-curve/src/mock.rs b/contracts/math/andromeda-curve/src/mock.rs index 059d32c91..eb2cce887 100644 --- a/contracts/math/andromeda-curve/src/mock.rs +++ b/contracts/math/andromeda-curve/src/mock.rs @@ -80,7 +80,7 @@ impl MockCurve { res } - pub fn query_plot_y_from_x(&self, app: &mut MockApp, x_value: f64) -> GetPlotYFromXResponse { + pub fn query_plot_y_from_x(&self, app: &mut MockApp, x_value: u64) -> GetPlotYFromXResponse { let msg = QueryMsg::GetPlotYFromX { x_value }; let res: GetPlotYFromXResponse = self.query(app, msg); res From 166fc9c2cebcffe5a73fde7950873b8059f7c2eb Mon Sep 17 00:00:00 2001 From: mdjakovic0920 Date: Wed, 15 Jan 2025 16:16:04 +0000 Subject: [PATCH 4/6] feat: added overflow error --- contracts/math/andromeda-curve/src/contract.rs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/contracts/math/andromeda-curve/src/contract.rs b/contracts/math/andromeda-curve/src/contract.rs index 379d52704..b38b8b7dc 100644 --- a/contracts/math/andromeda-curve/src/contract.rs +++ b/contracts/math/andromeda-curve/src/contract.rs @@ -198,10 +198,15 @@ pub fn query_plot_y_from_x( .map_err(|_| ContractError::Overflow {})? .atomics(); - let exponent_u32 = + let exponent_u32 = if exponent_value.u128() > u128::from(u32::MAX) { + return Err(ContractError::CustomError { + msg: "Exponent value exceeds u32::MAX.".to_string(), + }); + } else { u32::try_from(exponent_value.u128()).map_err(|_| ContractError::CustomError { msg: "Failed to convert exponent to u32.".to_string(), - })?; + })? + }; // The argument of the checked_pow() must be u32, can not be other types let res = constant_value_decimal From 56678e52c371747dca95e747684bd83c9b0ba706 Mon Sep 17 00:00:00 2001 From: Connor Barr Date: Wed, 15 Jan 2025 18:15:32 +0000 Subject: [PATCH 5/6] feat: x_value Decimal input --- contracts/math/andromeda-curve/src/contract.rs | 8 ++------ contracts/math/andromeda-curve/src/testing/mock.rs | 4 ++-- contracts/math/andromeda-curve/src/testing/tests.rs | 6 +++++- packages/andromeda-math/src/curve.rs | 4 ++-- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/contracts/math/andromeda-curve/src/contract.rs b/contracts/math/andromeda-curve/src/contract.rs index b38b8b7dc..c5471e0c8 100644 --- a/contracts/math/andromeda-curve/src/contract.rs +++ b/contracts/math/andromeda-curve/src/contract.rs @@ -171,7 +171,7 @@ pub fn query_curve_config(storage: &dyn Storage) -> Result Result { let curve_config = CURVE_CONFIG.load(storage)?; @@ -190,11 +190,7 @@ pub fn query_plot_y_from_x( ); let exponent_value = multiple_variable_value_decimal - .checked_mul(Decimal::from_atomics(x_value, 18).map_err(|e| { - ContractError::CustomError { - msg: format!("Failed to create decimal for the exponent_value: {:?}", e), - } - })?) + .checked_mul(x_value) .map_err(|_| ContractError::Overflow {})? .atomics(); diff --git a/contracts/math/andromeda-curve/src/testing/mock.rs b/contracts/math/andromeda-curve/src/testing/mock.rs index 214734f15..76d0028bc 100644 --- a/contracts/math/andromeda-curve/src/testing/mock.rs +++ b/contracts/math/andromeda-curve/src/testing/mock.rs @@ -10,7 +10,7 @@ use andromeda_std::{ use cosmwasm_std::{ from_json, testing::{mock_env, mock_info, MockApi, MockStorage}, - Deps, DepsMut, MessageInfo, OwnedDeps, Response, + Decimal, Deps, DepsMut, MessageInfo, OwnedDeps, Response, }; use crate::contract::{execute, instantiate, query}; @@ -78,7 +78,7 @@ pub fn query_curve_config(deps: Deps) -> Result Result { let res = query(deps, mock_env(), QueryMsg::GetPlotYFromX { x_value }); match res { diff --git a/contracts/math/andromeda-curve/src/testing/tests.rs b/contracts/math/andromeda-curve/src/testing/tests.rs index 3aa29f0db..6b54b0199 100644 --- a/contracts/math/andromeda-curve/src/testing/tests.rs +++ b/contracts/math/andromeda-curve/src/testing/tests.rs @@ -4,7 +4,7 @@ use super::mock::{ }; use andromeda_math::curve::{CurveConfig, CurveType}; use andromeda_std::{amp::AndrAddr, error::ContractError}; -use cosmwasm_std::StdError; +use cosmwasm_std::{Decimal, StdError}; use test_case::test_case; #[test] @@ -158,6 +158,7 @@ fn test_query_curve_config_base_is_0() { #[test_case(3, "8".to_string() ; "exp(2, 3)")] #[test_case(4, "16".to_string() ; "exp(2, 4)")] fn test_query_plot_y_from_x_base_2_growth(input_x: u64, expected_y: String) { + let input_x = Decimal::from_atomics(input_x, 18).unwrap(); let (deps, _info) = proper_initialization( CurveConfig::ExpConfig { curve_type: CurveType::Growth, @@ -176,6 +177,7 @@ fn test_query_plot_y_from_x_base_2_growth(input_x: u64, expected_y: String) { #[test_case(3, "27".to_string() ; "exp(3, 3)")] #[test_case(4, "81".to_string() ; "exp(3, 4)")] fn test_query_plot_y_from_x_base_3_growth(input_x: u64, expected_y: String) { + let input_x = Decimal::from_atomics(input_x, 18).unwrap(); let (deps, _info) = proper_initialization( CurveConfig::ExpConfig { curve_type: CurveType::Growth, @@ -194,6 +196,7 @@ fn test_query_plot_y_from_x_base_3_growth(input_x: u64, expected_y: String) { #[test_case(3, "128".to_string() ; "exp(4, 3)")] #[test_case(4, "512".to_string() ; "exp(4, 4)")] fn test_query_plot_y_from_x_base_4_growth_constant_2(input_x: u64, expected_y: String) { + let input_x = Decimal::from_atomics(input_x, 18).unwrap(); let (deps, _info) = proper_initialization( CurveConfig::ExpConfig { curve_type: CurveType::Growth, @@ -212,6 +215,7 @@ fn test_query_plot_y_from_x_base_4_growth_constant_2(input_x: u64, expected_y: S #[test_case(3, "0.125".to_string() ; "exp(1/2, 3)")] #[test_case(4, "0.0625".to_string() ; "exp(1/2, 4)")] fn test_query_plot_y_from_x_base_2_decay(input_x: u64, expected_y: String) { + let input_x = Decimal::from_atomics(input_x, 18).unwrap(); let (deps, _info) = proper_initialization( CurveConfig::ExpConfig { curve_type: CurveType::Decay, diff --git a/packages/andromeda-math/src/curve.rs b/packages/andromeda-math/src/curve.rs index f1d44eb9f..0e48c044c 100644 --- a/packages/andromeda-math/src/curve.rs +++ b/packages/andromeda-math/src/curve.rs @@ -1,6 +1,6 @@ use andromeda_std::{amp::AndrAddr, andr_exec, andr_instantiate, andr_query, error::ContractError}; use cosmwasm_schema::{cw_serde, QueryResponses}; -use cosmwasm_std::ensure; +use cosmwasm_std::{ensure, Decimal}; #[andr_instantiate] #[cw_serde] @@ -60,7 +60,7 @@ pub enum QueryMsg { #[returns(GetCurveConfigResponse)] GetCurveConfig {}, #[returns(GetPlotYFromXResponse)] - GetPlotYFromX { x_value: u64 }, + GetPlotYFromX { x_value: Decimal }, } #[cw_serde] From 7a0b8b9819e5b0b67115efb307bbc36eaf7b6364 Mon Sep 17 00:00:00 2001 From: Connor Barr Date: Thu, 16 Jan 2025 13:10:25 +0000 Subject: [PATCH 6/6] fix: revert Decimal changes from previous commit --- contracts/math/andromeda-curve/src/contract.rs | 8 ++++++-- contracts/math/andromeda-curve/src/testing/mock.rs | 4 ++-- contracts/math/andromeda-curve/src/testing/tests.rs | 6 +----- packages/andromeda-math/src/curve.rs | 4 ++-- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/contracts/math/andromeda-curve/src/contract.rs b/contracts/math/andromeda-curve/src/contract.rs index c5471e0c8..b38b8b7dc 100644 --- a/contracts/math/andromeda-curve/src/contract.rs +++ b/contracts/math/andromeda-curve/src/contract.rs @@ -171,7 +171,7 @@ pub fn query_curve_config(storage: &dyn Storage) -> Result Result { let curve_config = CURVE_CONFIG.load(storage)?; @@ -190,7 +190,11 @@ pub fn query_plot_y_from_x( ); let exponent_value = multiple_variable_value_decimal - .checked_mul(x_value) + .checked_mul(Decimal::from_atomics(x_value, 18).map_err(|e| { + ContractError::CustomError { + msg: format!("Failed to create decimal for the exponent_value: {:?}", e), + } + })?) .map_err(|_| ContractError::Overflow {})? .atomics(); diff --git a/contracts/math/andromeda-curve/src/testing/mock.rs b/contracts/math/andromeda-curve/src/testing/mock.rs index 76d0028bc..214734f15 100644 --- a/contracts/math/andromeda-curve/src/testing/mock.rs +++ b/contracts/math/andromeda-curve/src/testing/mock.rs @@ -10,7 +10,7 @@ use andromeda_std::{ use cosmwasm_std::{ from_json, testing::{mock_env, mock_info, MockApi, MockStorage}, - Decimal, Deps, DepsMut, MessageInfo, OwnedDeps, Response, + Deps, DepsMut, MessageInfo, OwnedDeps, Response, }; use crate::contract::{execute, instantiate, query}; @@ -78,7 +78,7 @@ pub fn query_curve_config(deps: Deps) -> Result Result { let res = query(deps, mock_env(), QueryMsg::GetPlotYFromX { x_value }); match res { diff --git a/contracts/math/andromeda-curve/src/testing/tests.rs b/contracts/math/andromeda-curve/src/testing/tests.rs index 6b54b0199..3aa29f0db 100644 --- a/contracts/math/andromeda-curve/src/testing/tests.rs +++ b/contracts/math/andromeda-curve/src/testing/tests.rs @@ -4,7 +4,7 @@ use super::mock::{ }; use andromeda_math::curve::{CurveConfig, CurveType}; use andromeda_std::{amp::AndrAddr, error::ContractError}; -use cosmwasm_std::{Decimal, StdError}; +use cosmwasm_std::StdError; use test_case::test_case; #[test] @@ -158,7 +158,6 @@ fn test_query_curve_config_base_is_0() { #[test_case(3, "8".to_string() ; "exp(2, 3)")] #[test_case(4, "16".to_string() ; "exp(2, 4)")] fn test_query_plot_y_from_x_base_2_growth(input_x: u64, expected_y: String) { - let input_x = Decimal::from_atomics(input_x, 18).unwrap(); let (deps, _info) = proper_initialization( CurveConfig::ExpConfig { curve_type: CurveType::Growth, @@ -177,7 +176,6 @@ fn test_query_plot_y_from_x_base_2_growth(input_x: u64, expected_y: String) { #[test_case(3, "27".to_string() ; "exp(3, 3)")] #[test_case(4, "81".to_string() ; "exp(3, 4)")] fn test_query_plot_y_from_x_base_3_growth(input_x: u64, expected_y: String) { - let input_x = Decimal::from_atomics(input_x, 18).unwrap(); let (deps, _info) = proper_initialization( CurveConfig::ExpConfig { curve_type: CurveType::Growth, @@ -196,7 +194,6 @@ fn test_query_plot_y_from_x_base_3_growth(input_x: u64, expected_y: String) { #[test_case(3, "128".to_string() ; "exp(4, 3)")] #[test_case(4, "512".to_string() ; "exp(4, 4)")] fn test_query_plot_y_from_x_base_4_growth_constant_2(input_x: u64, expected_y: String) { - let input_x = Decimal::from_atomics(input_x, 18).unwrap(); let (deps, _info) = proper_initialization( CurveConfig::ExpConfig { curve_type: CurveType::Growth, @@ -215,7 +212,6 @@ fn test_query_plot_y_from_x_base_4_growth_constant_2(input_x: u64, expected_y: S #[test_case(3, "0.125".to_string() ; "exp(1/2, 3)")] #[test_case(4, "0.0625".to_string() ; "exp(1/2, 4)")] fn test_query_plot_y_from_x_base_2_decay(input_x: u64, expected_y: String) { - let input_x = Decimal::from_atomics(input_x, 18).unwrap(); let (deps, _info) = proper_initialization( CurveConfig::ExpConfig { curve_type: CurveType::Decay, diff --git a/packages/andromeda-math/src/curve.rs b/packages/andromeda-math/src/curve.rs index 0e48c044c..f1d44eb9f 100644 --- a/packages/andromeda-math/src/curve.rs +++ b/packages/andromeda-math/src/curve.rs @@ -1,6 +1,6 @@ use andromeda_std::{amp::AndrAddr, andr_exec, andr_instantiate, andr_query, error::ContractError}; use cosmwasm_schema::{cw_serde, QueryResponses}; -use cosmwasm_std::{ensure, Decimal}; +use cosmwasm_std::ensure; #[andr_instantiate] #[cw_serde] @@ -60,7 +60,7 @@ pub enum QueryMsg { #[returns(GetCurveConfigResponse)] GetCurveConfig {}, #[returns(GetPlotYFromXResponse)] - GetPlotYFromX { x_value: Decimal }, + GetPlotYFromX { x_value: u64 }, } #[cw_serde]