Skip to content

Commit

Permalink
Mdjakovic/update curve (backport #767) (#768)
Browse files Browse the repository at this point in the history
Co-authored-by: Mitar Djakovic <[email protected]>
  • Loading branch information
mergify[bot] and mdjakovic0920 authored Jan 16, 2025
1 parent ebc174d commit 8ada466
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 31 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
58 changes: 45 additions & 13 deletions contracts/math/andromeda-curve/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -170,7 +171,7 @@ pub fn query_curve_config(storage: &dyn Storage) -> Result<GetCurveConfigRespons

pub fn query_plot_y_from_x(
storage: &dyn Storage,
x_value: f64,
x_value: u64,
) -> Result<GetPlotYFromXResponse, ContractError> {
let curve_config = CURVE_CONFIG.load(storage)?;

Expand All @@ -181,18 +182,49 @@ 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 = 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(),
})?
};
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()

// 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 {})?,
};

res_by_curve_type.to_string()
}
};

Expand Down
2 changes: 1 addition & 1 deletion contracts/math/andromeda-curve/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion contracts/math/andromeda-curve/src/testing/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ pub fn query_curve_config(deps: Deps) -> Result<GetCurveConfigResponse, Contract

pub fn query_plot_y_from_x(
deps: Deps,
x_value: f64,
x_value: u64,
) -> Result<GetPlotYFromXResponse, ContractError> {
let res = query(deps, mock_env(), QueryMsg::GetPlotYFromX { x_value });
match res {
Expand Down
48 changes: 33 additions & 15 deletions contracts/math/andromeda-curve/src/testing/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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,
Expand All @@ -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,
Expand All @@ -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);
}
2 changes: 1 addition & 1 deletion packages/andromeda-math/src/curve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ pub enum QueryMsg {
#[returns(GetCurveConfigResponse)]
GetCurveConfig {},
#[returns(GetPlotYFromXResponse)]
GetPlotYFromX { x_value: f64 },
GetPlotYFromX { x_value: u64 },
}

#[cw_serde]
Expand Down

0 comments on commit 8ada466

Please sign in to comment.