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

Feat: Implement the functions in the swap_pricing_utils library #446

Merged
merged 20 commits into from
Sep 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/event/event_emitter.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ use satoru::price::price::Price;
use satoru::pricing::position_pricing_utils::PositionFees;
use satoru::order::order::{Order, SecondaryOrderType};
use satoru::utils::span32::{Span32, DefaultSpan32};
use satoru::utils::i128::{I128Div, I128Mul, I128Serde};
use satoru::utils::i128::{I128Div, I128Mul, I128Store, I128Serde};


//TODO: OrderCollatDeltaAmountAutoUpdtd must be renamed back to OrderCollateralDeltaAmountAutoUpdated when string will be allowed as event argument
Expand Down Expand Up @@ -672,7 +672,7 @@ mod EventEmitter {
use satoru::pricing::position_pricing_utils::PositionFees;
use satoru::order::order::{Order, SecondaryOrderType};
use satoru::utils::span32::{Span32, DefaultSpan32};
use satoru::utils::i128::{I128Div, I128Mul, I128Serde};
use satoru::utils::i128::{I128Div, I128Mul, I128Store, I128Serde};

// *************************************************************************
// STORAGE
Expand Down
6 changes: 4 additions & 2 deletions src/lib.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ mod pricing {
mod position_pricing_utils;
mod pricing_utils;
mod swap_pricing_utils;
mod error;
}

// `referral` contains referral logic.
Expand Down Expand Up @@ -312,11 +313,12 @@ mod tests {
mod price {
mod test_price;
}

mod pricing {
mod test_swap_pricing_utils;
}
mod reader {
mod test_reader;
}

mod role {
mod test_role_module;
mod test_role_store;
Expand Down
73 changes: 59 additions & 14 deletions src/market/market_utils.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ use satoru::market::{
};
use satoru::oracle::oracle::{IOracleDispatcher, IOracleDispatcherTrait};
use satoru::price::price::{Price, PriceTrait};
use satoru::utils::calc;
use satoru::utils::span32::Span32;
use satoru::utils::i128::{StoreI128, u128_to_i128, I128Serde, I128Div, I128Mul};
use satoru::utils::i128::{I128Store, I128Serde, I128Div, I128Mul, I128Default};

/// Struct to store the prices of tokens of a market.
/// # Params
/// * `indexTokenPrice` - Price of the market's index token.
Expand Down Expand Up @@ -73,11 +75,11 @@ fn get_cached_token_price(token: ContractAddress, market: Market, prices: Market
}

fn get_swap_impact_amount_with_cap(
dataStore: IDataStoreDispatcher,
data_store: IDataStoreDispatcher,
market: ContractAddress,
token: ContractAddress,
tokenPrice: Price,
priceImpactUsd: i128 //TODO : check u128
token_price: Price,
price_impact_usd: i128 //TODO : check u128
) -> i128 { //Todo : check u128
//TODO
return 0;
Expand Down Expand Up @@ -338,8 +340,8 @@ fn get_pnl(
maximize: bool
) -> i128 {
// Get the open interest.
let open_interest = u128_to_i128(
get_open_interest_for_market_is_long(data_store, market, is_long)
let open_interest = calc::to_signed(
get_open_interest_for_market_is_long(data_store, market, is_long), true
);
// Get the open interest in tokens.
let open_interest_in_tokens = get_open_interest_in_tokens_for_market(
Expand All @@ -354,7 +356,7 @@ fn get_pnl(
let price = index_token_price.pick_price_for_pnl(is_long, maximize);

// `open_interest` is the cost of all positions, `open_interest_valu`e is the current worth of all positions.
let open_interest_value = u128_to_i128(open_interest_in_tokens * price);
let open_interest_value = calc::to_signed(open_interest_in_tokens * price, true);

// Return the PNL.
// If `is_long` is true, then the PNL is the difference between the current worth of all positions and the cost of all positions.
Expand Down Expand Up @@ -694,6 +696,16 @@ fn is_pnl_factor_exceeded_direct(
(true, 0, 0)
}

fn get_ui_fee_factor(data_store: IDataStoreDispatcher, account: ContractAddress) -> u128 {
let max_ui_fee_factor = data_store.get_u128(keys::max_ui_fee_factor());
let ui_fee_factor = data_store.get_u128(keys::ui_fee_factor_key(account));
if ui_fee_factor < max_ui_fee_factor {
ui_fee_factor
} else {
max_ui_fee_factor
}
}

/// Gets the enabled market. This function will revert if the market does not exist or is not enabled.
/// # Arguments
/// * `dataStore` - DataStore
Expand Down Expand Up @@ -961,7 +973,6 @@ fn market_token_amount_to_usd(
0
}


/// Get the borrowing factor per second.
/// # Arguments
/// * `data_store` - The data store to use.
Expand Down Expand Up @@ -1039,18 +1050,52 @@ fn get_open_interest_with_pnl(
0
}


/// Get the virtual inventory for swaps
/// # Arguments
/// * `data_store` - The data store to use.
/// * `market` - The market address.
/// * `market` - The market.
/// # Returns
/// has virtual inventory, virtual long token inventory, virtual short token inventory
/// The tuple (has virtual inventory, virtual long token inventory, virtual short token inventory)
fn get_virtual_inventory_for_swaps(
data_store: IDataStoreDispatcher, market: ContractAddress,
data_store: IDataStoreDispatcher, market: ContractAddress
) -> (bool, u128, u128) {
// TODO
(false, 0, 0)
let virtual_market_id = data_store.get_felt252(keys::virtual_market_id_key(market));
if virtual_market_id.is_zero() {
return (false, 0, 0);
}

return (
true,
data_store.get_u128(keys::virtual_inventory_for_swaps_key(virtual_market_id, true)),
data_store.get_u128(keys::virtual_inventory_for_swaps_key(virtual_market_id, false))
);
}

fn get_adjusted_swap_impact_factor(
data_store: IDataStoreDispatcher, market: ContractAddress, is_positive: bool
) -> u128 {
let (positive_impact_factor, negative_impact_factor) = get_adjusted_swap_impact_factors(
data_store, market
);
if is_positive {
positive_impact_factor
} else {
negative_impact_factor
}
}

fn get_adjusted_swap_impact_factors(
data_store: IDataStoreDispatcher, market: ContractAddress
) -> (u128, u128) {
let mut positive_impact_factor = data_store
.get_u128(keys::swap_impact_factor_key(market, true));
let negative_impact_factor = data_store.get_u128(keys::swap_impact_factor_key(market, false));
// if the positive impact factor is more than the negative impact factor, positions could be opened
// and closed immediately for a profit if the difference is sufficient to cover the position fees
if positive_impact_factor > negative_impact_factor {
positive_impact_factor = negative_impact_factor;
}
(positive_impact_factor, negative_impact_factor)
}


Expand Down
11 changes: 6 additions & 5 deletions src/order/base_order_utils.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use integer::BoundedInt;
use starknet::ContractAddress;

// Local imports.
use satoru::utils::i128::{I128Div, u128_to_i128, i128_to_u128};
use satoru::data::data_store::{IDataStoreDispatcher, IDataStoreDispatcherTrait};
use satoru::event::event_emitter::{IEventEmitterDispatcher, IEventEmitterDispatcherTrait};
use satoru::oracle::oracle::{IOracleDispatcher, IOracleDispatcherTrait};
Expand All @@ -21,6 +20,8 @@ use satoru::utils::precision;
use satoru::utils::store_arrays::{StoreMarketArray, StoreU64Array, StoreContractAddressArray};
use satoru::mock::referral_storage::{IReferralStorageDispatcher, IReferralStorageDispatcherTrait};
use satoru::utils::span32::Span32;
use satoru::utils::calc;
use satoru::utils::i128::{I128Div, I128Store, I128Serde};

#[derive(Drop, starknet::Store, Serde)]
struct ExecuteOrderParams {
Expand Down Expand Up @@ -414,7 +415,7 @@ fn get_execution_price_for_decrease(
};

if adjusted_price_impact_usd < 0
&& i128_to_u128(-adjusted_price_impact_usd) > size_delta_usd {
&& calc::to_unsigned(-adjusted_price_impact_usd) > size_delta_usd {
panic(
array![
OrderError::PRICE_IMPACT_LARGER_THAN_ORDER_SIZE,
Expand All @@ -430,9 +431,9 @@ fn get_execution_price_for_decrease(
let numerator = precision::mul_div_inum(
position_size_in_usd, adjusted_price_impact_usd, position_size_in_tokens
);
let adjustment = numerator / u128_to_i128(size_delta_usd);
let adjustment = numerator / calc::to_signed(size_delta_usd, true);

let _execution_price: i128 = u128_to_i128(price) + adjustment;
let _execution_price: i128 = calc::to_signed(price, true) + adjustment;

if _execution_price < 0 {
panic(
Expand All @@ -447,7 +448,7 @@ fn get_execution_price_for_decrease(
);
}

execution_price = i128_to_u128(_execution_price);
execution_price = calc::to_unsigned(_execution_price);
}

// decrease order:
Expand Down
44 changes: 22 additions & 22 deletions src/position/position_utils.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,7 @@ use satoru::order::order::{Order, SecondaryOrderType};
use satoru::mock::referral_storage::{IReferralStorageDispatcher, IReferralStorageDispatcherTrait};
use satoru::order::base_order_utils::ExecuteOrderParamsContracts;
use satoru::price::price::{Price, PriceTrait};
use satoru::utils::{
precision, i128::{StoreI128, u128_to_i128, i128_to_u128, I128Serde, I128Div, I128Mul}
};
use satoru::utils::calc::{roundup_division};
use satoru::utils::{calc, precision, i128::{I128Store, I128Serde, I128Div, I128Mul}};
use satoru::referral::referral_utils;
use satoru::order::order_vault::{IOrderVaultDispatcher, IOrderVaultDispatcherTrait};

Expand Down Expand Up @@ -257,13 +254,13 @@ fn get_position_pnl_usd(
let execution_price = prices.index_token_price.pick_price_for_pnl(position.is_long, false);

// position.sizeInUsd is the cost of the tokens, positionValue is the current worth of the tokens
cache.position_value = u128_to_i128(position.size_in_tokens * execution_price);
cache.position_value = calc::to_signed(position.size_in_tokens * execution_price, true);
cache
.total_position_pnl =
if position.is_long {
cache.position_value - u128_to_i128(position.size_in_usd)
cache.position_value - calc::to_signed(position.size_in_usd, true)
} else {
u128_to_i128(position.size_in_usd) - cache.position_value
calc::to_signed(position.size_in_usd, true) - cache.position_value
};
cache.uncapped_total_position_pnl = cache.total_position_pnl;

Expand Down Expand Up @@ -305,9 +302,9 @@ fn get_position_pnl_usd(
cache
.total_position_pnl =
precision::mul_div_inum(
i128_to_u128(cache.total_position_pnl),
calc::to_unsigned(cache.total_position_pnl),
cache.capped_pool_pnl,
i128_to_u128(cache.pool_pnl)
calc::to_unsigned(cache.pool_pnl)
);
}
}
Expand All @@ -317,7 +314,7 @@ fn get_position_pnl_usd(
if position.is_long {
cache
.size_delta_in_tokens =
roundup_division(
calc::roundup_division(
position.size_in_tokens * size_delta_usd, position.size_in_usd
);
} else {
Expand Down Expand Up @@ -447,7 +444,7 @@ fn is_position_liquiditable(

cache.collateral_usd = position.collateral_amount * cache.collateral_token_price.min;
// calculate the usdDeltaForPriceImpact for fully closing the position
cache.usd_delta_for_price_impact = -u128_to_i128(position.size_in_usd);
cache.usd_delta_for_price_impact = calc::to_signed(position.size_in_usd, false);
cache
.price_impact_usd =
position_pricing_utils::get_price_impact_usd(
Expand All @@ -474,8 +471,8 @@ fn is_position_liquiditable(
// this could result in very large price impact temporarily
// cap the max negative price impact to prevent cascading liquidations

let max_negatice_price_impact = u128_to_i128(
precision::apply_factor_u128(position.size_in_usd, max_price_impact_factor)
let max_negatice_price_impact = calc::to_signed(
precision::apply_factor_u128(position.size_in_usd, max_price_impact_factor), true
);
if cache.price_impact_usd < max_negatice_price_impact {
cache.price_impact_usd = max_negatice_price_impact;
Expand All @@ -501,13 +498,15 @@ fn is_position_liquiditable(
// the position's pnl is counted as collateral for the liquidation check
// as a position in profit should not be liquidated if the pnl is sufficient
// to cover the position's fees
cache.remaining_collateral_usd = u128_to_i128(cache.collateral_usd)
cache.remaining_collateral_usd = calc::to_signed(cache.collateral_usd, true)
+ cache.position_pnl_usd
+ cache.price_impact_usd
- u128_to_i128(collateral_cost_usd);
- calc::to_signed(collateral_cost_usd, true);

if should_validate_min_collateral_usd {
cache.min_collateral_usd = u128_to_i128(data_store.get_u128(keys::min_collateral_usd()));
cache
.min_collateral_usd =
calc::to_signed(data_store.get_u128(keys::min_collateral_usd()), true);
if (cache.remaining_collateral_usd < cache.min_collateral_usd) {
return (true, 'min collateral');
}
Expand All @@ -523,8 +522,9 @@ fn is_position_liquiditable(
// i.e. if the position does not have sufficient collateral after closing fees it is considered a liquidatable position
cache
.min_collateral_usd_for_leverage =
u128_to_i128(
precision::apply_factor_u128(position.size_in_usd, cache.min_collateral_factor)
calc::to_signed(
precision::apply_factor_u128(position.size_in_usd, cache.min_collateral_factor),
true
);
if cache.remaining_collateral_usd <= cache.min_collateral_usd_for_leverage {
return (true, 'min collateral for leverage');
Expand Down Expand Up @@ -574,8 +574,8 @@ fn will_position_collateral_be_sufficient(
let collateral_token_price = market_utils::get_cached_token_price(
collateral_token, market, prices
);
let mut remaining_collateral_usd = u128_to_i128(values.position_collateral_amount)
* u128_to_i128(collateral_token_price.min);
let mut remaining_collateral_usd = calc::to_signed(values.position_collateral_amount, true)
* calc::to_signed(collateral_token_price.min, true);
// deduct realized pnl if it is negative since this would be paid from
// the position's collateral
if values.realized_pnl_usd < 0 {
Expand All @@ -602,8 +602,8 @@ fn will_position_collateral_be_sufficient(
if (min_collateral_factor_for_market > min_collateral_factor) {
min_collateral_factor = min_collateral_factor_for_market;
}
let min_collateral_usd_for_leverage = u128_to_i128(
precision::apply_factor_u128(values.position_size_in_usd, min_collateral_factor)
let min_collateral_usd_for_leverage = calc::to_signed(
precision::apply_factor_u128(values.position_size_in_usd, min_collateral_factor), true
);
let will_be_sufficient: bool = remaining_collateral_usd >= min_collateral_usd_for_leverage;

Expand Down
3 changes: 3 additions & 0 deletions src/pricing/error.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
mod PricingError {
const USD_DELTA_EXCEEDS_POOL_VALUE: felt252 = 'usd_delta_exceeds_pool_value';
}
2 changes: 1 addition & 1 deletion src/pricing/position_pricing_utils.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use satoru::market::market::Market;
use satoru::price::price::Price;
use satoru::position::position::Position;
use satoru::mock::referral_storage::{IReferralStorageDispatcher, IReferralStorageDispatcherTrait};
use satoru::utils::i128::{StoreI128, I128Serde,};
use satoru::utils::i128::{I128Store, I128Serde,};
/// Struct used in get_position_fees.
#[derive(Drop, starknet::Store, Serde)]
struct GetPositionFeesParams {
Expand Down
2 changes: 1 addition & 1 deletion src/pricing/pricing_utils.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ fn get_price_impact_usd_for_same_side_rebalance(
/// a crossover in balance is for example if the long open interest is larger
/// than the short open interest, and a short position is opened such that the
/// short open interest becomes larger than the long open interest.
fn get_price_impact_usd_for_crossover_side_rebalance(
fn get_price_impact_usd_for_crossover_rebalance(
initial_diff_usd: u128,
next_diff_usd: u128,
positive_impact_factor: u128,
Expand Down
Loading
Loading