[go: nahoru, domu]

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

Improve tests of swap_pricing_utils library. #543

Open
wants to merge 8 commits into
base: main
Choose a base branch
from
Open
2 changes: 0 additions & 2 deletions src/pricing/swap_pricing_utils.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
// *************************************************************************
// Core lib imports.
use starknet::ContractAddress;
use result::ResultTrait;

// Local imports.
use satoru::data::data_store::{IDataStoreDispatcher, IDataStoreDispatcherTrait};
Expand All @@ -19,7 +18,6 @@ use satoru::utils::calc;
use satoru::utils::precision;
use satoru::utils::i128::{i128, i128_neg};


/// Struct used in get_price_impact_usd.
#[derive(Copy, Drop, starknet::Store, Serde)]
struct GetPriceImpactUsdParams {
Expand Down
63 changes: 28 additions & 35 deletions src/utils/precision.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,16 @@
// Core lib imports.
use alexandria_math::pow;
use integer::{
u128_to_felt252, u256_wide_mul, u512_safe_div_rem_by_u256, BoundedU256, u256_try_as_non_zero
u256_wide_mul, u512_safe_div_rem_by_u256, BoundedU256, U256TryIntoNonZero, U128IntoFelt252
};
use satoru::utils::i128::i128;
use core::traits::TryInto;
use core::option::Option;
use satoru::utils::calc::{roundup_division, roundup_magnitude_division};

const FLOAT_PRECISION: u128 = 100_000_000_000_000_000_000; // 10^20
const FLOAT_PRECISION_SQRT: u128 = 10_000_000_000; // 10^10

const WEI_PRECISION: u128 = 1_000_000_000_000_000_000; // 10^18
const BASIS_POINTS_DIVISOR: u128 = 10000;
const BASIS_POINTS_DIVISOR: u128 = 10_000;

const FLOAT_TO_WEI_DIVISOR: u128 = 1_000_000_000_000; // 10^12

Expand All @@ -26,7 +24,7 @@ const FLOAT_TO_WEI_DIVISOR: u128 = 1_000_000_000_000; // 10^12
/// # Returns
/// The result of applying the factor to the value.
fn apply_factor_u128(value: u128, factor: u128) -> u128 {
return mul_div(value, factor, FLOAT_PRECISION);
mul_div(value, factor, FLOAT_PRECISION)
}

/// Applies the given factor to the given value and returns the result.
Expand All @@ -36,7 +34,7 @@ fn apply_factor_u128(value: u128, factor: u128) -> u128 {
/// # Returns
/// The result of applying the factor to the value.
fn apply_factor_i128(value: u128, factor: i128) -> i128 {
return mul_div_inum(value, factor, FLOAT_PRECISION);
mul_div_inum(value, factor, FLOAT_PRECISION)
}

/// Applies the given factor to the given value and returns the result.
Expand All @@ -46,7 +44,7 @@ fn apply_factor_i128(value: u128, factor: i128) -> i128 {
/// # Returns
/// The result of applying the factor to the value.
fn apply_factor_roundup_magnitude(value: u128, factor: i128, roundup_magnitude: bool) -> i128 {
return mul_div_inum_roundup(value, factor, FLOAT_PRECISION, roundup_magnitude);
mul_div_inum_roundup(value, factor, FLOAT_PRECISION, roundup_magnitude)
}

/// Apply multiplication then division to value.
Expand All @@ -55,13 +53,10 @@ fn apply_factor_roundup_magnitude(value: u128, factor: i128, roundup_magnitude:
/// * `numerator` - The numerator that multiplies value.
/// * `divisor` - The denominator that divides value.
fn mul_div(value: u128, numerator: u128, denominator: u128) -> u128 {
let value = u256 { low: value, high: 0 };
let numerator = u256 { low: numerator, high: 0 };
let denominator = u256 { low: denominator, high: 0 };
let product = u256_wide_mul(value, numerator);
let (q, _) = u512_safe_div_rem_by_u256(
product, u256_try_as_non_zero(denominator).expect('MulDivByZero')
);
let product = u256_wide_mul(value.into(), numerator.into());
let denominator: u256 = denominator.into();
let non_zero_denominator = denominator.try_into().expect('MulDivByZero');
let (q, _) = u512_safe_div_rem_by_u256(product, non_zero_denominator);
assert(q.limb1 == 0 && q.limb2 == 0 && q.limb3 == 0, 'MulDivOverflow');
q.limb0
}
Expand All @@ -72,7 +67,7 @@ fn mul_div(value: u128, numerator: u128, denominator: u128) -> u128 {
/// * `numerator` - The numerator that multiplies value.
/// * `divisor` - The denominator that divides value.
fn mul_div_ival(value: i128, numerator: u128, denominator: u128) -> i128 {
return mul_div_inum(numerator, value, denominator);
mul_div_inum(numerator, value, denominator)
}

/// Apply multiplication then division to value.
Expand All @@ -89,12 +84,12 @@ fn mul_div_inum(value: u128, numerator: i128, denominator: u128) -> i128 {
let felt252_numerator: felt252 = numerator_abs.into();
let u128_numerator = felt252_numerator.try_into().expect('felt252 into u128 failed');
let result: u128 = mul_div(value, u128_numerator, denominator);
let felt252_result: felt252 = u128_to_felt252(result);
let felt252_result: felt252 = result.into();
let i128_result: i128 = felt252_result.try_into().expect('felt252 into i128 failed');
if numerator > Zeroable::zero() {
return i128_result;
i128_result
} else {
return -i128_result;
-i128_result
}
}

Expand All @@ -114,12 +109,12 @@ fn mul_div_inum_roundup(
let felt252_numerator: felt252 = numerator_abs.into();
let u128_numerator = felt252_numerator.try_into().expect('felt252 into u128 failed');
let result: u128 = mul_div_roundup(value, u128_numerator, denominator, roundup_magnitude);
let felt252_result: felt252 = u128_to_felt252(result);
let felt252_result: felt252 = result.into();
let i128_result: i128 = felt252_result.try_into().expect('felt252 into i128 failed');
if numerator > Zeroable::zero() {
return i128_result;
i128_result
} else {
return -i128_result;
-i128_result
}
}

Expand All @@ -131,13 +126,10 @@ fn mul_div_inum_roundup(
fn mul_div_roundup(
value: u128, numerator: u128, denominator: u128, roundup_magnitude: bool
) -> u128 {
let value = u256 { low: value, high: 0 };
let numerator = u256 { low: numerator, high: 0 };
let denominator = u256 { low: denominator, high: 0 };
let product = u256_wide_mul(value, numerator);
let (q, r) = u512_safe_div_rem_by_u256(
product, u256_try_as_non_zero(denominator).expect('MulDivByZero')
);
let product = u256_wide_mul(value.into(), numerator.into());
let denominator: u256 = denominator.into();
let non_zero_denominator = denominator.try_into().expect('MulDivByZero');
let (q, r) = u512_safe_div_rem_by_u256(product, non_zero_denominator);
if roundup_magnitude && r > 0 {
let result = u256 { low: q.limb0, high: q.limb1 };
assert(
Expand Down Expand Up @@ -182,9 +174,10 @@ fn to_factor_roundup(value: u128, divisor: u128, roundup_magnitude: bool) -> u12
}

if (roundup_magnitude) {
return mul_div_roundup(value, FLOAT_PRECISION, divisor, roundup_magnitude);
mul_div_roundup(value, FLOAT_PRECISION, divisor, roundup_magnitude)
} else {
mul_div(value, FLOAT_PRECISION, divisor)
}
return mul_div(value, FLOAT_PRECISION, divisor);
}

/// Compute factor from value and divisor.
Expand All @@ -194,7 +187,7 @@ fn to_factor_roundup(value: u128, divisor: u128, roundup_magnitude: bool) -> u12
/// # Returns
/// The factor between value and divisor.
fn to_factor(value: u128, divisor: u128) -> u128 {
return to_factor_roundup(value, divisor, false);
to_factor_roundup(value, divisor, false)
}

/// Compute factor from integer value and divisor.
Expand All @@ -212,7 +205,7 @@ fn to_factor_ival(value: i128, divisor: u128) -> i128 {
let felt252_value: felt252 = value_abs.into();
let u128_value = felt252_value.try_into().expect('felt252 into u128 failed');
let result: u128 = to_factor(u128_value, divisor);
let felt252_result: felt252 = u128_to_felt252(result);
let felt252_result: felt252 = result.into();
let i128_result: i128 = felt252_result.try_into().expect('felt252 into i128 failed');
if value > Zeroable::zero() {
i128_result
Expand All @@ -227,7 +220,7 @@ fn to_factor_ival(value: i128, divisor: u128) -> i128 {
/// # Returns
/// The wei value.
fn float_to_wei(value: u128) -> u128 {
return value / FLOAT_TO_WEI_DIVISOR;
value / FLOAT_TO_WEI_DIVISOR
}

/// Converts the given value from wei to float.
Expand All @@ -236,7 +229,7 @@ fn float_to_wei(value: u128) -> u128 {
/// # Returns
/// The float value.
fn wei_to_float(value: u128) -> u128 {
return value * FLOAT_TO_WEI_DIVISOR;
value * FLOAT_TO_WEI_DIVISOR
}

/// Converts the given value basis point to float.
Expand All @@ -245,5 +238,5 @@ fn wei_to_float(value: u128) -> u128 {
/// # Returns
/// The float value.
fn basis_points_to_float(basis_point: u128) -> u128 {
return basis_point * FLOAT_PRECISION / BASIS_POINTS_DIVISOR;
basis_point * FLOAT_PRECISION / BASIS_POINTS_DIVISOR
}
55 changes: 47 additions & 8 deletions tests/pricing/test_swap_pricing_utils.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,17 @@ use satoru::data::data_store::IDataStoreDispatcherTrait;
use satoru::data::keys;
use satoru::pricing::swap_pricing_utils::{
GetPriceImpactUsdParams, get_price_impact_usd_, get_price_impact_usd, get_next_pool_amount_usd,
get_swap_fees
get_swap_fees, PoolParams
};
use satoru::market::market::Market;
use satoru::utils::calc;
use satoru::tests_lib::{setup, teardown};
use satoru::utils::precision;
use satoru::utils::precision::{FLOAT_PRECISION};
use satoru::utils::i128::{i128, i128_new};

#[test]
fn given_normal_conditions_when_swap_pricing_utils_functions_then_works() {
fn given_normal_conditions_when_get_price_impact_usd_then_works() {
// *********************************************************************************************
// * SETUP *
// *********************************************************************************************
Expand Down Expand Up @@ -49,6 +51,43 @@ fn given_normal_conditions_when_swap_pricing_utils_functions_then_works() {
teardown(data_store.contract_address);
}

#[test]
fn given_normal_conditions_when_get_price_impact_usd_inner_then_works() {
// *********************************************************************************************
// * SETUP *
// *********************************************************************************************
let (_, _, data_store) = setup();

let market_token = 'market_token'.try_into().unwrap();
let index_token = 'index_token'.try_into().unwrap();
let long_token = 'long_token'.try_into().unwrap();
let short_token = 'short_token'.try_into().unwrap();

data_store.set_u128(keys::pool_amount_key(market_token, long_token), 1000);
data_store.set_u128(keys::pool_amount_key(market_token, short_token), 1000);

// *********************************************************************************************
// * TEST LOGIC *
// *********************************************************************************************

let market = Market { market_token, index_token, long_token, short_token };

let params = PoolParams {
pool_usd_for_token_a: 1000,
pool_usd_for_token_b: 1000,
next_pool_usd_for_token_a: 1001,
next_pool_usd_for_token_b: 999,
};

let impact = get_price_impact_usd_(data_store, market, params);
assert(impact == Zeroable::zero(), 'fail');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you think it's feasible to also add a testcase with a non zero result ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok i'll try, i think it wasn't super trivial

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, let me know


// *********************************************************************************************
// * TEARDOWN *
// *********************************************************************************************
teardown(data_store.contract_address);
}

#[test]
fn given_normal_conditions_when_get_next_pool_amount_usd_then_works() {
// *********************************************************************************************
Expand Down Expand Up @@ -114,16 +153,16 @@ fn given_normal_conditions_when_get_swap_fees_then_works() {
// * TEST LOGIC *
// *********************************************************************************************

let amount = 1000;
let amount = 1000 * FLOAT_PRECISION;
let fees = get_swap_fees(
data_store, market_token, amount, for_positive_impact, ui_fee_receiver
);

assert(fees.fee_receiver_amount == 0, 'invalid');
assert(fees.fee_amount_for_pool == 0, 'invalid');
assert(fees.amount_after_fees == 0x03e8, 'invalid');
assert(fees.ui_fee_receiver_factor == 9, 'invalid');
assert(fees.ui_fee_amount == 0, 'invalid');
assert(fees.fee_receiver_amount == 0, 'invalid 1');
assert(fees.fee_amount_for_pool == 5000, 'invalid 2');
assert(fees.amount_after_fees == 1000 * FLOAT_PRECISION - 14000, 'invalid 3');
assert(fees.ui_fee_receiver_factor == 9, 'invalid 4');
assert(fees.ui_fee_amount == 9000, 'invalid 5');

// *********************************************************************************************
// * TEARDOWN *
Expand Down
Loading