-
Notifications
You must be signed in to change notification settings - Fork 6
feat: opt risk factor #81
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
base: dev
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -54,6 +54,7 @@ pub mod AssetsComponent { | |
| }; | ||
| use starkware_utils::storage::utils::{AddToStorage, SubFromStorage}; | ||
| use starkware_utils::time::time::{Time, TimeDelta, Timestamp}; | ||
| use crate::core::types::asset::RiskConfig; | ||
|
|
||
| #[storage] | ||
| pub struct Storage { | ||
|
|
@@ -70,6 +71,8 @@ pub mod AssetsComponent { | |
| num_of_active_synthetic_assets: usize, | ||
| #[rename("synthetic_config")] | ||
| pub asset_config: Map<AssetId, Option<AssetConfig>>, | ||
| pub risk_config: Map<AssetId, RiskConfig>, | ||
| pub risk_factor_tiers_opt: Map<AssetId, Map<u64, RiskFactor>>, | ||
| #[rename("synthetic_timely_data")] | ||
| pub asset_timely_data: IterableMap<AssetId, AssetTimelyData>, | ||
| pub risk_factor_tiers: Map<AssetId, Vec<RiskFactor>>, | ||
|
|
@@ -151,6 +154,33 @@ pub mod AssetsComponent { | |
| self.emit(events::OracleAdded { asset_id, asset_name, oracle_public_key, oracle_name }); | ||
| } | ||
|
|
||
| fn migrate_risk(ref self: ComponentState<TContractState>) { | ||
| for (asset_id, _) in self.asset_timely_data { | ||
| // pub risk_factor_first_tier_boundary: u128, | ||
| // /// - `risk_factor_tier_size` — 92-bit field stored in a `u128`. | ||
| // pub risk_factor_tier_size: u128, | ||
| // pub len: u32, | ||
| let x = self.asset_config.read(asset_id).unwrap(); | ||
|
|
||
| self | ||
| .risk_config | ||
| .write( | ||
| asset_id, | ||
| RiskConfig { | ||
| risk_factor_first_tier_boundary: x.risk_factor_first_tier_boundary, | ||
| risk_factor_tier_size: x.risk_factor_tier_size, | ||
| len: self.risk_factor_tiers.entry(asset_id).len().try_into().unwrap(), | ||
| }, | ||
| ); | ||
| let vec = self.risk_factor_tiers.entry(asset_id); | ||
| for i in 0..vec.len() { | ||
| let value = vec.at(i.into()).read(); | ||
| self.risk_factor_tiers_opt.entry(asset_id).write(i.into(), value); | ||
| } | ||
| } | ||
| } | ||
|
|
||
|
|
||
| /// Add asset is called by the app governer to add a new synthetic asset. | ||
| /// | ||
| /// Validations: | ||
|
|
@@ -548,26 +578,22 @@ pub mod AssetsComponent { | |
| balance: Balance, | ||
| price: Price, | ||
| ) -> RiskFactor { | ||
| if let Option::Some(asset_config) = self.asset_config.read(asset_id) { | ||
| let asset_risk_factor_tiers = self.risk_factor_tiers.entry(asset_id); | ||
| let synthetic_value: u128 = price.mul(rhs: balance).abs(); | ||
| let index = if synthetic_value < asset_config.risk_factor_first_tier_boundary { | ||
| 0_u128 | ||
| } else { | ||
| let tier_size = asset_config.risk_factor_tier_size; | ||
| let first_tier_offset = synthetic_value | ||
| - asset_config.risk_factor_first_tier_boundary; | ||
| min( | ||
| 1_u128 + (first_tier_offset / tier_size), | ||
| asset_risk_factor_tiers.len().into() - 1, | ||
| ) | ||
| }; | ||
| asset_risk_factor_tiers | ||
| .at(index.try_into().expect('INDEX_SHOULD_NEVER_OVERFLOW')) | ||
| .read() | ||
| let risk_config = self.risk_config.read(asset_id); | ||
| let synthetic_value: u128 = price.mul(rhs: balance).abs(); | ||
| let index = if synthetic_value < risk_config.risk_factor_first_tier_boundary { | ||
| 0_u128 | ||
| } else { | ||
| panic_with_felt252(ASSET_NOT_EXISTS) | ||
| } | ||
| let first_tier_offset = synthetic_value | ||
| - risk_config.risk_factor_first_tier_boundary; | ||
| min( | ||
| 1_u128 + (first_tier_offset / risk_config.risk_factor_tier_size), | ||
| risk_config.len.into() - 1, | ||
| ) | ||
| }; | ||
| self | ||
| .risk_factor_tiers_opt | ||
| .entry(asset_id) | ||
| .read(index.try_into().expect('INDEX_SHOULD_NEVER_OVERFLOW')) | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: Asset Risk Factor Calculation Fails SilentlyThe There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: New Assets Lack Risk Config Initialization
|
||
| } | ||
|
|
||
| fn get_funding_index( | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1099,7 +1099,22 @@ pub mod Core { | |
| fulfillment_entry.write(total_amount); | ||
| } | ||
|
|
||
| fn _validate_order(ref self: ContractState, order: Order) { | ||
| fn _validate_order( | ||
| ref self: ContractState, | ||
| order: Order, | ||
| now: Option<Timestamp>, | ||
| collateral_id: Option<AssetId>, | ||
| ) -> (Timestamp, AssetId) { | ||
| let now = if now.is_none() { | ||
| Time::now() | ||
| } else { | ||
| now.unwrap() | ||
| }; | ||
| let collateral_id = if collateral_id.is_none() { | ||
| self.assets.get_collateral_id() | ||
| } else { | ||
| collateral_id.unwrap() | ||
| }; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Bug: Redundant Time::now() Call Breaks Timestamp ConsistencyDuplicate |
||
| // Verify that position is not fee position. | ||
| assert(order.position_id != FEE_POSITION, CANT_TRADE_WITH_FEE_POSITION); | ||
| // This is to make sure that the fee is relative to the quote amount. | ||
|
|
@@ -1119,9 +1134,9 @@ pub mod Core { | |
| assert(!have_same_sign(order.quote_amount, order.base_amount), INVALID_AMOUNT_SIGN); | ||
|
|
||
| // Validate asset ids. | ||
| let collateral_id = self.assets.get_collateral_id(); | ||
| assert(order.quote_asset_id == collateral_id, ASSET_ID_NOT_COLLATERAL); | ||
| assert(order.fee_asset_id == collateral_id, ASSET_ID_NOT_COLLATERAL); | ||
| (now, collateral_id) | ||
| } | ||
|
|
||
| fn _validate_trade( | ||
|
|
@@ -1135,12 +1150,20 @@ pub mod Core { | |
| ) { | ||
| // Base asset check. | ||
| assert(order_a.base_asset_id == order_b.base_asset_id, DIFFERENT_BASE_ASSET_IDS); | ||
| self.assets.validate_active_asset(asset_id: order_a.base_asset_id); | ||
| // self.assets.validate_active_asset(asset_id: order_a.base_asset_id); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
|
|
||
| assert(order_a.position_id != order_b.position_id, INVALID_SAME_POSITIONS); | ||
|
|
||
| self._validate_order(order: order_a); | ||
| self._validate_order(order: order_b); | ||
| let (now, collateral_id) = self | ||
| ._validate_order( | ||
| order: order_a, now: Default::default(), collateral_id: Default::default(), | ||
| ); | ||
| self | ||
| ._validate_order( | ||
| order: order_b, | ||
| now: Option::Some(now), | ||
| collateral_id: Option::Some(collateral_id), | ||
| ); | ||
|
|
||
| // Non-zero actual amount check. | ||
| assert(actual_amount_base_a.is_non_zero(), INVALID_ZERO_AMOUNT); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Bug: Unprotected Migration Overwrites Current Risk Configurations
The
migrate_riskfunction is a public, unprotected migration function. Anyone can call it, allowing current risk configurations to be overwritten with initial configuration data from the old storage structures.