Skip to content

Commit

Permalink
wip - error in calc_y with Decimal256 fixed
Browse files Browse the repository at this point in the history
  • Loading branch information
gangov committed Aug 8, 2024
1 parent f276955 commit a4c3822
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 75 deletions.
77 changes: 19 additions & 58 deletions contracts/pool_stable/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use soroban_sdk::{

use crate::{
error::ContractError,
math::{calc_y, compute_current_amp, compute_d, scale_value, AMP_PRECISION},
math::{calc_y, compute_current_amp, compute_d, AMP_PRECISION},
stake_contract,
storage::{
get_amp, get_config, get_greatest_precision, get_precisions, save_amp, save_config,
Expand Down Expand Up @@ -343,17 +343,11 @@ impl StableLiquidityPoolTrait for StableLiquidityPool {
&env,
amp as u128,
&[
Decimal256::raw(U256::from_u128(
&env,
scale_value(new_balance_a, token_a_decimals, DECIMAL_PRECISION),
)),
Decimal256::raw(U256::from_u128(
&env,
scale_value(new_balance_b, token_b_decimals, DECIMAL_PRECISION),
)),
Decimal256::from_atomics(&env, new_balance_a, token_a_decimals as i32),
Decimal256::from_atomics(&env, new_balance_b, token_b_decimals as i32),
],
)
.to_u128_with_precision(greatest_precision as i32);
.to_u128_with_precision(DECIMAL_PRECISION as i32);

let total_shares = utils::get_total_shares(&env);
let shares = if total_shares == 0 {
Expand All @@ -373,25 +367,19 @@ impl StableLiquidityPoolTrait for StableLiquidityPool {
&env,
amp as u128,
&[
Decimal256::raw(U256::from_u128(
Decimal256::from_atomics(
&env,
scale_value(
convert_i128_to_u128(old_balance_a),
token_a_decimals,
DECIMAL_PRECISION,
),
)),
Decimal256::raw(U256::from_u128(
convert_i128_to_u128(old_balance_a),
token_a_decimals as i32,
),
Decimal256::from_atomics(
&env,
scale_value(
convert_i128_to_u128(old_balance_b),
token_b_decimals,
DECIMAL_PRECISION,
),
)),
convert_i128_to_u128(old_balance_b),
token_b_decimals as i32,
),
],
)
.to_u128_with_precision(greatest_precision as i32);
.to_u128_with_precision(DECIMAL_PRECISION as i32);

// Calculate the proportion of the change in invariant
let invariant_delta = new_invariant - initial_invariant;
Expand Down Expand Up @@ -852,7 +840,6 @@ fn do_swap(
panic_with_error!(&env, ContractError::UserDeclinesPoolFee);
}
}

if offer_asset != config.token_a && offer_asset != config.token_b {
log!(
&env,
Expand Down Expand Up @@ -1037,23 +1024,10 @@ pub fn compute_swap(
let new_ask_pool = calc_y(
env,
amp as u128,
Decimal256::raw(U256::from_u128(
env,
scale_value(
offer_pool + offer_amount,
greatest_precision,
DECIMAL_PRECISION,
),
)),
Decimal256::from_atomics(env, offer_pool + offer_amount, greatest_precision as i32),
&[
Decimal256::raw(U256::from_u128(
env,
scale_value(offer_pool, offer_pool_precision, DECIMAL_PRECISION),
)),
Decimal256::raw(U256::from_u128(
env,
scale_value(ask_pool, ask_pool_precision, DECIMAL_PRECISION),
)),
Decimal256::from_atomics(env, offer_pool, offer_pool_precision as i32),
Decimal256::from_atomics(env, ask_pool, ask_pool_precision as i32),
],
greatest_precision,
);
Expand Down Expand Up @@ -1116,23 +1090,10 @@ pub fn compute_offer_amount(
let new_offer_pool = calc_y(
env,
amp as u128,
Decimal256::raw(U256::from_u128(
env,
scale_value(
ask_pool - before_commission,
greatest_precision,
DECIMAL_PRECISION,
),
)),
Decimal256::from_atomics(env, ask_pool - before_commission, greatest_precision as i32),
&[
Decimal256::raw(U256::from_u128(
env,
scale_value(offer_pool, offer_pool_precision, DECIMAL_PRECISION),
)),
Decimal256::raw(U256::from_u128(
env,
scale_value(ask_pool, ask_pool_precision, DECIMAL_PRECISION),
)),
Decimal256::from_atomics(env, offer_pool, offer_pool_precision as i32),
Decimal256::from_atomics(env, ask_pool, ask_pool_precision as i32),
],
greatest_precision,
);
Expand Down
27 changes: 12 additions & 15 deletions contracts/pool_stable/src/math.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,6 @@ pub const AMP_PRECISION: u64 = 100;
/// The maximum number of calculation steps for Newton's method.
const ITERATIONS: u8 = 64;

pub fn scale_value(atomics: u128, decimal_places: u32, target_decimal_places: u32) -> u128 {
const TEN: u128 = 10;
if decimal_places < target_decimal_places {
let factor = TEN.pow(target_decimal_places - decimal_places);
atomics
.checked_mul(factor)
.expect("Multiplication overflow")
} else {
let factor = TEN.pow(decimal_places - target_decimal_places);
atomics.checked_div(factor).expect("Division overflow")
}
}

fn abs_diff(a: &Decimal256, b: &Decimal256) -> Decimal256 {
if a < b {
b.clone() - a.clone()
Expand Down Expand Up @@ -148,6 +135,7 @@ pub(crate) fn calc_y(
xp: &[Decimal256],
target_precision: u32,
) -> u128 {
soroban_sdk::testutils::arbitrary::std::dbg!("START CALC_Y");
let n_coins = Decimal256::raw(U256::from_u128(env, 2000000000000000000));
let tol = Decimal256::raw(U256::from_u128(env, 1000000000000));

Expand Down Expand Up @@ -175,14 +163,23 @@ pub(crate) fn calc_y(
let mut y = d.clone();
for _ in 0..ITERATIONS {
y_prev = y.clone();
y = y.clone().pow(env, 2) + c.div(env, y.mul(env, &n_coins) + b.clone() - d.clone());

y = (y.clone().pow(env, 2) + c.clone())
.div(env, y.mul(env, &n_coins) + b.clone() - d.clone());

soroban_sdk::testutils::arbitrary::std::dbg!(
y.clone().to_u128_with_precision(DECIMAL_PRECISION as i32),
y_prev
.clone()
.to_u128_with_precision(DECIMAL_PRECISION as i32),
tol.to_u128_with_precision(DECIMAL_PRECISION as i32),
);
if abs_diff(&y, &y_prev) <= tol {
let divisor = 10u128.pow(DECIMAL_PRECISION - target_precision);
return y.to_u128_with_precision(target_precision as i32) / divisor;
}
}

soroban_sdk::testutils::arbitrary::std::dbg!();
// Should definitely converge in 64 iterations.
log!(&env, "Pool Stable: calc_y: y is not converging");
panic_with_error!(&env, ContractError::CalcYErr);
Expand Down
5 changes: 3 additions & 2 deletions contracts/pool_stable/src/tests/swap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,10 +190,11 @@ fn swap_with_high_fee() {
&None::<u64>,
&None::<u128>,
);

soroban_sdk::testutils::arbitrary::std::dbg!("PROVIDED");
let spread = 1_000; // 10% maximum spread allowed

// let's swap 100_000 units of Token 1 in 1:1 pool with 10% protocol fee
soroban_sdk::testutils::arbitrary::std::dbg!("try to swap");
pool.swap(
&user1,
&token1.address,
Expand All @@ -203,7 +204,7 @@ fn swap_with_high_fee() {
&None::<u64>,
&None,
);

soroban_sdk::testutils::arbitrary::std::dbg!("swapped");
// This is Stable swap LP with constant product formula
let output_amount = 98_582i128; // rounding
let result = pool.query_pool_info();
Expand Down

0 comments on commit a4c3822

Please sign in to comment.