Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Range test variants and precision #569

Open
wants to merge 25 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
a7f456a
extended default_init capability by adding tokens provided arg
magiodev Feb 14, 2024
cc579e5
spot price check on test_init_contract
magiodev Feb 14, 2024
9cc697a
more enhancement on generic default_ionit function
magiodev Feb 14, 2024
e1ab0a0
range dym test
magiodev Feb 14, 2024
7118cb3
reproducing dym denominator
magiodev Feb 14, 2024
3d608d5
upscale and downscale if needed based on scale_factor threshold
magiodev Feb 14, 2024
2e1bc4d
remove debugs
magiodev Feb 14, 2024
dd24da6
unit tests scale_if_needed
magiodev Feb 14, 2024
9ed4ea2
generalize test case, include wide position on init
magiodev Feb 14, 2024
c214e33
correct test function name
magiodev Feb 14, 2024
6bb2d50
fmt
magiodev Feb 14, 2024
c218532
fix test tube
magiodev Feb 15, 2024
55d9285
resolve warnings
magiodev Feb 15, 2024
74650d5
Fix/simplify range swap (#571)
LaurensKubat Feb 15, 2024
94f4af4
resolve warnings
magiodev Feb 15, 2024
cd929b7
addressing Laus comment
magiodev Feb 15, 2024
69e2847
make scale_if_needed arguments immutable
LaurensKubat Feb 15, 2024
714c923
downgrade osmosis-std and osmosis-test-tube
LaurensKubat Feb 15, 2024
c43c9f0
bump actions go version and test-tube
LaurensKubat Feb 15, 2024
4a0d406
go 1.21.7 ci
magiodev Feb 15, 2024
3168bb0
different go versions ci
magiodev Feb 15, 2024
7e9921b
revert changes outside smart contracts
magiodev Feb 15, 2024
4310d7e
downgrade osmosis-std and test-tube
LaurensKubat Feb 15, 2024
0e3f4f1
remove migrate logic
magiodev Feb 16, 2024
1908662
Merge remote-tracking branch 'origin/feat/range_test_variants' into f…
magiodev Feb 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
140 changes: 129 additions & 11 deletions smart-contracts/contracts/cl-vault/src/helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,18 +160,51 @@ pub fn get_twap_price(
// ))
// }

const SCALE_FACTOR: u128 = 10u128.pow(12);

fn scale_if_needed(
cur_price_sqrt: Decimal256,
upper_price_sqrt: Decimal256,
lower_price_sqrt: Decimal256,
current_price: Decimal256,
) -> (bool, Decimal256, Decimal256, Decimal256, Decimal256) {
let scale_up_threshold = Decimal256::from_ratio(1u128, SCALE_FACTOR);
let product = cur_price_sqrt * upper_price_sqrt * lower_price_sqrt;

if product <= scale_up_threshold {
let scale_factor = Decimal256::from_atomics(SCALE_FACTOR, 0).unwrap();

// Scale the square root prices and current price
let scaled_cur_price_sqrt = cur_price_sqrt.checked_mul(scale_factor).unwrap();
let scaled_upper_price_sqrt = upper_price_sqrt.checked_mul(scale_factor).unwrap();
let scaled_lower_price_sqrt = lower_price_sqrt.checked_mul(scale_factor).unwrap();
let scaled_current_price = current_price.checked_mul(scale_factor).unwrap();

return (
magiodev marked this conversation as resolved.
Show resolved Hide resolved
true,
scaled_cur_price_sqrt,
scaled_upper_price_sqrt,
scaled_lower_price_sqrt,
scaled_current_price,
);
}

(
false,
cur_price_sqrt,
upper_price_sqrt,
lower_price_sqrt,
current_price,
)
}

// this math is straight from the readme
pub fn get_single_sided_deposit_0_to_1_swap_amount(
token0_balance: Uint128,
lower_tick: i64,
current_tick: i64,
upper_tick: i64,
) -> Result<Uint128, ContractError> {
// TODO error here if this condition holds
// if current_tick < lower_tick {
// return ;
// }

let lower_price = tick_to_price(lower_tick)?;
let current_price = tick_to_price(current_tick)?;
let upper_price = tick_to_price(upper_tick)?;
Expand All @@ -180,10 +213,13 @@ pub fn get_single_sided_deposit_0_to_1_swap_amount(
let lower_price_sqrt = lower_price.sqrt();
let upper_price_sqrt = upper_price.sqrt();

// let pool_metadata_constant: Decimal256 = cur_price_sqrt
// .checked_mul(lower_price_sqrt)?
// .checked_mul(cur_price_sqrt.checked_sub(lower_price_sqrt)?)?
// .checked_div(upper_price_sqrt.checked_sub(cur_price_sqrt)?)?;
let (is_scale_needed, cur_price_sqrt, upper_price_sqrt, lower_price_sqrt, current_price) =
scale_if_needed(
cur_price_sqrt,
upper_price_sqrt,
lower_price_sqrt,
current_price,
);

let pool_metadata_constant: Decimal256 = (upper_price_sqrt
.checked_mul(cur_price_sqrt)?
Expand All @@ -193,7 +229,16 @@ pub fn get_single_sided_deposit_0_to_1_swap_amount(
let spot_price_over_pool_metadata_constant =
current_price.checked_div(pool_metadata_constant)?;

let denominator = Decimal256::one().checked_add(spot_price_over_pool_metadata_constant)?;
// Adjust spot_price_over_pool_metadata_constant back to its original scale if scaling was applied
let adjusted_spot_price_over_pool_metadata_constant = if is_scale_needed {
let underscale_factor = Decimal256::from_atomics(SCALE_FACTOR, 0).unwrap();
spot_price_over_pool_metadata_constant.checked_div(underscale_factor)?
} else {
spot_price_over_pool_metadata_constant
};

let denominator =
Decimal256::one().checked_add(adjusted_spot_price_over_pool_metadata_constant)?;

let swap_amount: Uint128 = Uint256::from(token0_balance)
.multiply_ratio(denominator.denominator(), denominator.numerator())
Expand All @@ -216,6 +261,14 @@ pub fn get_single_sided_deposit_1_to_0_swap_amount(
let lower_price_sqrt = lower_price.sqrt();
let upper_price_sqrt = upper_price.sqrt();

let (is_scale_needed, cur_price_sqrt, upper_price_sqrt, lower_price_sqrt, current_price) =
scale_if_needed(
cur_price_sqrt,
upper_price_sqrt,
lower_price_sqrt,
current_price,
);

let pool_metadata_constant: Decimal256 = (upper_price_sqrt
.checked_mul(cur_price_sqrt)?
.checked_mul(cur_price_sqrt.checked_sub(lower_price_sqrt)?))?
Expand All @@ -224,7 +277,16 @@ pub fn get_single_sided_deposit_1_to_0_swap_amount(
let pool_metadata_constant_over_spot_price: Decimal256 =
pool_metadata_constant.checked_div(current_price)?;

let denominator = Decimal256::one().checked_add(pool_metadata_constant_over_spot_price)?;
// Adjust spot_price_over_pool_metadata_constant back to its original scale if scaling was applied
let adjusted_pool_metadata_over_spot_price_constant = if is_scale_needed {
let underscale_factor = Decimal256::from_atomics(SCALE_FACTOR, 0).unwrap();
pool_metadata_constant_over_spot_price.checked_div(underscale_factor)?
} else {
pool_metadata_constant_over_spot_price
};

let denominator =
Decimal256::one().checked_add(adjusted_pool_metadata_over_spot_price_constant)?;

let swap_amount: Uint128 = Uint256::from(token1_balance)
.multiply_ratio(denominator.denominator(), denominator.numerator())
Expand Down Expand Up @@ -463,6 +525,62 @@ mod tests {

use super::*;

#[test]
fn test_scale_if_needed_variants() {
// Adjusted small and large values for testing
let small_value = Decimal256::from_ratio(1u128, 10u128.pow(5)); // 1e-5 to ensure product is below 1e-12
let large_value = Decimal256::from_ratio(1u128, 10u128.pow(3)); // 1e-3 or larger to ensure product is above 1e-12

// Scenario 1: All Values Below Threshold
let (needs_scaling_below, _, _, _, _) =
scale_if_needed(small_value, small_value, small_value, small_value);
assert_eq!(
needs_scaling_below, true,
"Scaling should be needed for all values below threshold"
);

// Scenario 2: All Values Above Threshold
let (needs_scaling_above, _, _, _, _) =
scale_if_needed(large_value, large_value, large_value, large_value);
assert_eq!(
needs_scaling_above, false,
"Scaling should not be needed for all values above threshold"
);

// Scenario 3: Mixed Values - Some below, some above threshold
let (needs_scaling_mixed, _, _, _, _) =
scale_if_needed(small_value, large_value, small_value, large_value);
assert_eq!(
needs_scaling_mixed, true,
"Scaling should be needed for mixed values with any below threshold"
);

// Scenario 4: Boundary Condition - Exactly at Threshold
// Assuming the threshold can be represented exactly, otherwise adjust the threshold or values accordingly
let threshold_value = Decimal256::from_ratio(1u128, SCALE_FACTOR); // Adjust based on actual threshold
let (needs_scaling_boundary, _, _, _, _) = scale_if_needed(
threshold_value,
threshold_value,
threshold_value,
threshold_value,
);
// The expected result here depends on how you define "less than" in scale_if_needed
// If using <, this should be false. If using <=, adjust the assertion accordingly.
assert_eq!(
needs_scaling_boundary, true,
"Scaling should be needed exactly at threshold"
);

// Scenario 5: Zero and Near-Zero Values - Ensure handling of zero properly
let zero_value = Decimal256::zero();
let (needs_scaling_zero, _, _, _, _) =
scale_if_needed(zero_value, zero_value, zero_value, zero_value);
assert_eq!(
needs_scaling_zero, true,
"Scaling should be needed for zero values"
);
}

#[test]
fn must_pay_one_or_two_works_ordered() {
let expected0 = coin(100, "uatom");
Expand Down
4 changes: 2 additions & 2 deletions smart-contracts/contracts/cl-vault/src/instantiate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ use crate::state::{
DISTRIBUTED_REWARDS, METADATA, POOL_CONFIG, POSITION, RANGE_ADMIN, REWARDS_STATUS,
STRATEGIST_REWARDS, VAULT_CONFIG, VAULT_DENOM,
};
use crate::vault::concentrated_liquidity::create_position;
use crate::vault::concentrated_liquidity::get_create_position_msg;
use crate::ContractError;

pub fn handle_instantiate(
Expand Down Expand Up @@ -86,7 +86,7 @@ pub fn handle_instantiate(
// in order to create the initial position, we need some funds to throw in there, these funds should be seen as burned
let (initial0, initial1) = must_pay_one_or_two(&info, (pool.token0, pool.token1))?;

let create_position_msg = create_position(
let create_position_msg = get_create_position_msg(
deps,
&env,
msg.initial_lower_tick,
Expand Down
17 changes: 16 additions & 1 deletion smart-contracts/contracts/cl-vault/src/test_tube/admin.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,26 @@
#[cfg(test)]
mod tests {
use osmosis_std::types::cosmos::base::v1beta1;

use crate::test_tube::initialize::initialize::default_init;

const DENOM_BASE: &str = "uatom";
const DENOM_QUOTE: &str = "uosmo";

#[test]
#[ignore]
fn range_admin_update_works() {
let (_app, _contract_address, _cl_pool_id, _admin) = default_init();
let (_app, _contract_address, _cl_pool_id, _admin) = default_init(vec![
v1beta1::Coin {
denom: DENOM_BASE.to_string(),
amount: "1000000000000".to_string(),
},
v1beta1::Coin {
denom: DENOM_QUOTE.to_string(),
amount: "1000000000000".to_string(),
},
])
.unwrap();
// change the range admin and verify that it works
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
mod tests {
use cosmwasm_std::{assert_approx_eq, Coin, Uint128};

use osmosis_std::types::cosmos::base::v1beta1;
use osmosis_test_tube::{Account, Module, Wasm};

use crate::{
Expand All @@ -17,7 +18,17 @@ mod tests {
#[test]
#[ignore]
fn single_deposit_withdraw_works() {
let (app, contract_address, _cl_pool_id, _admin) = default_init();
let (app, contract_address, _cl_pool_id, _admin) = default_init(vec![
v1beta1::Coin {
denom: DENOM_BASE.to_string(),
amount: "1000000000000".to_string(),
},
v1beta1::Coin {
denom: DENOM_QUOTE.to_string(),
amount: "1000000000000".to_string(),
},
])
.unwrap();
let wasm = Wasm::new(&app);

// Create Alice account
Expand Down Expand Up @@ -126,7 +137,17 @@ mod tests {
#[test]
#[ignore]
fn multiple_deposit_withdraw_works() {
let (app, contract_address, _cl_pool_id, _admin) = default_init();
let (app, contract_address, _cl_pool_id, _admin) = default_init(vec![
v1beta1::Coin {
denom: DENOM_BASE.to_string(),
amount: "1000000000000".to_string(),
},
v1beta1::Coin {
denom: DENOM_QUOTE.to_string(),
amount: "1000000000000".to_string(),
},
])
.unwrap();
let wasm = Wasm::new(&app);

// Create Alice account
Expand Down Expand Up @@ -254,7 +275,17 @@ mod tests {
#[test]
#[ignore]
fn multiple_deposit_withdraw_unused_funds_works() {
let (app, contract_address, _cl_pool_id, _admin) = default_init();
let (app, contract_address, _cl_pool_id, _admin) = default_init(vec![
v1beta1::Coin {
denom: DENOM_BASE.to_string(),
amount: "1000000000000".to_string(),
},
v1beta1::Coin {
denom: DENOM_QUOTE.to_string(),
amount: "1000000000000".to_string(),
},
])
.unwrap();
//let bank = Bank::new(&app);

let wasm = Wasm::new(&app);
Expand Down