Skip to content
Closed
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
24 changes: 4 additions & 20 deletions packages/predict/sources/expiry_market.move
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use deepbook_predict::{
pricing_config::PricingConfig,
protocol_config::ProtocolConfig,
pyth_source::PythSource,
strike_exposure::{Self, StrikeExposure}
strike_exposure::{Self, ExpiryTerms, StrikeExposure}
};
use dusdc::dusdc::DUSDC;
use sui::{balance::{Self, Balance}, clock::Clock, vec_set::VecSet};
Expand Down Expand Up @@ -327,12 +327,7 @@ public(package) fun create_and_share(
allowed_versions: VecSet<u64>,
market_oracle_id: ID,
pyth_lazer_feed_id: u32,
expiry: u64,
min_strike: u64,
tick_size: u64,
preallocated_ticks: u64,
expiry_fee_window_ms: u64,
expiry_fee_max_multiplier: u64,
terms: ExpiryTerms,
ctx: &mut TxContext,
): ID {
let id = object::new(ctx);
Expand All @@ -341,22 +336,11 @@ public(package) fun create_and_share(
id,
market_oracle_id,
pyth_lazer_feed_id,
expiry,
expiry: terms.expiry_ms(),
trading_loss_rebate_rate: config.fee_config().trading_loss_rebate_rate(),
cash_balance: balance::zero(),
unresolved_trading_fees_paid: 0,
strike_exposure: strike_exposure::new(
expiry_market_id,
expiry,
min_strike,
tick_size,
preallocated_ticks,
config.leverage_config().max_expiry_floor_premium(),
config.leverage_config().liquidation_ltv(),
expiry_fee_window_ms,
expiry_fee_max_multiplier,
ctx,
),
strike_exposure: strike_exposure::new(expiry_market_id, terms, ctx),
ewma: ewma::new(ctx),
allowed_versions,
mint_paused: false,
Expand Down
18 changes: 12 additions & 6 deletions packages/predict/sources/registry.move
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ use deepbook_predict::{
predict_manager::{Self, PredictDepositCap, PredictManager, PredictTradeCap, PredictWithdrawCap},
pricing,
protocol_config::{Self, ProtocolConfig},
pyth_source::{Self, PythSource}
pyth_source::{Self, PythSource},
strike_exposure
};
use std::type_name::{Self, TypeName};
use sui::{
Expand Down Expand Up @@ -437,17 +438,22 @@ public fun create_expiry_market(
allowed_versions,
ctx,
);
let expiry_market_id = expiry_market::create_and_share(
config,
allowed_versions,
market_oracle_id,
pyth_lazer_feed_id,
let terms = strike_exposure::expiry_terms(
expiry,
min_strike,
tick_size,
preallocated_ticks,
config.leverage_config().max_expiry_floor_premium(),
config.leverage_config().liquidation_ltv(),
expiry_fee_window_ms,
expiry_fee_max_multiplier,
);
let expiry_market_id = expiry_market::create_and_share(
config,
allowed_versions,
market_oracle_id,
pyth_lazer_feed_id,
terms,
ctx,
);
pool_vault.register_expiry_market(expiry_market_id);
Expand Down
53 changes: 50 additions & 3 deletions packages/predict/sources/strike_exposure/strike_exposure.move
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,22 @@ public struct LiveExposure has store {
minted_max_strike: u64,
}

/// Immutable creation terms for one expiry's `StrikeExposure`, bundled so the
/// market-creation flow passes a single labeled value through `expiry_market` and
/// into `new` instead of a long list of interchangeable `u64`s. Every field is
/// snapshotted into `StrikeExposure` by `new`; see that struct for units and
/// economic meaning.
public struct ExpiryTerms has copy, drop {
expiry_ms: u64,
min_strike: u64,
tick_size: u64,
preallocated_ticks: u64,
max_expiry_floor_premium: u64,
liquidation_ltv: u64,
expiry_fee_window_ms: u64,
expiry_fee_max_multiplier: u64,
}

/// Return conservative max-live backing, or remaining settled payout liability once materialized.
public(package) fun payout_liability(exposure: &StrikeExposure): u64 {
if (exposure.settled_liability_materialized) {
Expand Down Expand Up @@ -153,9 +169,8 @@ public(package) fun is_liquidated_order(exposure: &StrikeExposure, order: &Order
exposure.liquidation.is_liquidated(order)
}

/// Create a strike exposure book for the oracle grid.
public(package) fun new(
expiry_market_id: ID,
/// Bundle the immutable terms used to create one expiry's `StrikeExposure`.
public(package) fun expiry_terms(
expiry_ms: u64,
min_strike: u64,
tick_size: u64,
Expand All @@ -164,8 +179,40 @@ public(package) fun new(
liquidation_ltv: u64,
expiry_fee_window_ms: u64,
expiry_fee_max_multiplier: u64,
): ExpiryTerms {
ExpiryTerms {
expiry_ms,
min_strike,
tick_size,
preallocated_ticks,
max_expiry_floor_premium,
liquidation_ltv,
expiry_fee_window_ms,
expiry_fee_max_multiplier,
}
}

/// Terminal timestamp these terms will stamp onto the expiry market.
public(package) fun expiry_ms(terms: &ExpiryTerms): u64 {
terms.expiry_ms
}

/// Create a strike exposure book for the oracle grid.
public(package) fun new(
expiry_market_id: ID,
terms: ExpiryTerms,
ctx: &mut TxContext,
): StrikeExposure {
let ExpiryTerms {
expiry_ms,
min_strike,
tick_size,
preallocated_ticks,
max_expiry_floor_premium,
liquidation_ltv,
expiry_fee_window_ms,
expiry_fee_max_multiplier,
} = terms;
let max_strike = validated_max_strike(min_strike, tick_size);
StrikeExposure {
expiry_market_id,
Expand Down
35 changes: 17 additions & 18 deletions packages/predict/tests/expiry_market_tests.move
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use deepbook_predict::{
protocol_config::{Self, ProtocolConfig},
pyth_source::{Self, PythSource},
registry::{Self, Registry},
strike_exposure,
test_constants
};
use dusdc::dusdc::DUSDC;
Expand Down Expand Up @@ -58,6 +59,19 @@ const EXPECTED_PENALTY: u64 = 2_000_000;
const POOL_CASH: u64 = 1_000_000_000_000;
const LARGE_DEPOSIT: u64 = 1_000_000_000_000;

fun default_expiry_terms(config: &ProtocolConfig): strike_exposure::ExpiryTerms {
strike_exposure::expiry_terms(
EXPIRY_MS,
MIN_STRIKE,
TICK_SIZE,
constants::default_expiry_preallocated_ticks!(),
config.leverage_config().max_expiry_floor_premium(),
config.leverage_config().liquidation_ltv(),
config_constants::default_expiry_fee_window_ms!(),
constants::float_scaling!(),
)
}

#[test]
fun rebate_eligibility_offsets_fee_reserve_by_gross_profit() {
let mut scenario = test::begin(test_constants::alice());
Expand All @@ -80,12 +94,7 @@ fun rebate_eligibility_offsets_fee_reserve_by_gross_profit() {
vec_set::singleton(constants::current_version!()),
oracle.id(),
pyth.feed_id(),
EXPIRY_MS,
MIN_STRIKE,
TICK_SIZE,
constants::default_expiry_preallocated_ticks!(),
config_constants::default_expiry_fee_window_ms!(),
constants::float_scaling!(),
default_expiry_terms(&config),
scenario.ctx(),
);
let mut manager = registry::create_manager(&mut registry, scenario.ctx());
Expand Down Expand Up @@ -189,12 +198,7 @@ fun mint_withholds_ewma_penalty_into_pool_on_gas_spike() {
vec_set::singleton(constants::current_version!()),
oracle.id(),
pyth.feed_id(),
EXPIRY_MS,
MIN_STRIKE,
TICK_SIZE,
constants::default_expiry_preallocated_ticks!(),
config_constants::default_expiry_fee_window_ms!(),
constants::float_scaling!(),
default_expiry_terms(&config),
scenario.ctx(),
);
let mut manager = registry::create_manager(&mut registry, scenario.ctx());
Expand Down Expand Up @@ -299,12 +303,7 @@ fun redeem_withholds_ewma_penalty_from_payout_on_gas_spike() {
vec_set::singleton(constants::current_version!()),
oracle.id(),
pyth.feed_id(),
EXPIRY_MS,
MIN_STRIKE,
TICK_SIZE,
constants::default_expiry_preallocated_ticks!(),
config_constants::default_expiry_fee_window_ms!(),
constants::float_scaling!(),
default_expiry_terms(&config),
scenario.ctx(),
);
let mut manager = registry::create_manager(&mut registry, scenario.ctx());
Expand Down
18 changes: 10 additions & 8 deletions packages/predict/tests/strike_exposure/strike_exposure_tests.move
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,16 @@ fun new_exposure(
): strike_exposure::StrikeExposure {
strike_exposure::new(
FAKE_EXPIRY_ID.to_id(),
expiry_ms,
min_strike,
tick_size,
constants::default_expiry_preallocated_ticks!(),
max_expiry_floor_premium,
LIQUIDATION_LTV,
config_constants::default_expiry_fee_window_ms!(),
constants::float_scaling!(),
strike_exposure::expiry_terms(
expiry_ms,
min_strike,
tick_size,
constants::default_expiry_preallocated_ticks!(),
max_expiry_floor_premium,
LIQUIDATION_LTV,
config_constants::default_expiry_fee_window_ms!(),
constants::float_scaling!(),
),
ctx,
)
}
Expand Down
Loading