Skip to content
Draft
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
2 changes: 1 addition & 1 deletion docs/spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -3154,4 +3154,4 @@ Only the Operator can execute.
- ASSET_NOT_EXISTS
- ACTIVE_SYNTHETIC
- POSITION_IS_NOT_HEALTHIER
- POSITION_NOT_HEALTHY_NOR_HEALTHIER
- POSITION_NOT_HEALTHY_NOR_HEALTHIER

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ pub const ASSET_NAME_TOO_LONG: felt252 = 'ASSET_NAME_TOO_LONG';
pub const ASSET_NOT_ACTIVE: felt252 = 'ASSET_NOT_ACTIVE';
pub const ASSET_NOT_EXISTS: felt252 = 'ASSET_NOT_EXISTS';
pub const ASSET_REGISTERED_AS_COLLATERAL: felt252 = 'ASSET_REGISTERED_AS_COLLATERAL';
pub const ASSET_ALREADY_HAS_ERC20: felt252 = 'ASSET_ALREADY_HAS_ERC20';
pub const COLLATERAL_NOT_EXISTS: felt252 = 'COLLATERAL_NOT_EXISTS';
pub const COLLATERAL_NOT_REGISTERED: felt252 = 'COLLATERAL_NOT_REGISTERED';
pub const INACTIVE_ASSET: felt252 = 'INACTIVE_ASSET';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use starknet::ContractAddress;
use openzeppelin::token::erc20::interface::IERC20Dispatcher;
use perpetuals::core::types::asset::AssetId;
use perpetuals::core::types::asset::synthetic::{SyntheticConfig, SyntheticTimelyData};
use perpetuals::core::types::asset::synthetic::{AssetConfig, SyntheticTimelyData};
use perpetuals::core::types::funding::FundingTick;
use perpetuals::core::types::price::SignedPrice;
use perpetuals::core::types::risk_factor::RiskFactor;
Expand All @@ -27,6 +28,17 @@ pub trait IAssets<TContractState> {
quorum: u8,
resolution_factor: u64,
);
fn add_vault_share_asset(
ref self: TContractState,
asset_id: AssetId,
risk_factor_tiers: Span<u16>,
risk_factor_first_tier_boundary: u128,
risk_factor_tier_size: u128,
quorum: u8,
resolution_factor: u64,
quantum: u64,
erc20_address: ContractAddress,
);
fn deactivate_synthetic(ref self: TContractState, synthetic_id: AssetId);
fn funding_tick(
ref self: TContractState, operator_nonce: u64, funding_ticks: Span<FundingTick>,
Expand Down Expand Up @@ -54,9 +66,11 @@ pub trait IAssets<TContractState> {
fn get_max_oracle_price_validity(self: @TContractState) -> TimeDelta;
fn get_num_of_active_synthetic_assets(self: @TContractState) -> usize;
fn get_collateral_id(self: @TContractState) -> AssetId;
fn get_synthetic_config(self: @TContractState, synthetic_id: AssetId) -> SyntheticConfig;
fn get_asset_config(self: @TContractState, synthetic_id: AssetId) -> AssetConfig;
fn get_synthetic_timely_data(
self: @TContractState, synthetic_id: AssetId,
) -> SyntheticTimelyData;
fn get_risk_factor_tiers(self: @TContractState, asset_id: AssetId) -> Span<RiskFactor>;

fn get_asset_erc20_contract(self: @TContractState, asset_id: AssetId) -> IERC20Dispatcher;
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ pub(crate) mod Deposit {
use starkware_utils::components::roles::RolesComponent;
use starkware_utils::signature::stark::HashType;
use starkware_utils::time::time::{Time, TimeDelta};
use crate::core::types::asset::AssetId;

#[storage]
pub struct Storage {
Expand Down Expand Up @@ -70,6 +71,7 @@ pub(crate) mod Deposit {
/// - Emits a Deposit event.
fn deposit(
ref self: ComponentState<TContractState>,
asset_id: AssetId,
position_id: PositionId,
quantized_amount: u64,
salt: felt252,
Expand All @@ -80,7 +82,14 @@ pub(crate) mod Deposit {
assert(quantized_amount.is_non_zero(), errors::ZERO_AMOUNT);
let caller_address = get_caller_address();
let assets = get_dep_component!(@self, Assets);
let token_contract = assets.get_collateral_token_contract();

let (token_contract, quantum) = if (asset_id == assets.get_collateral_id()) {
(assets.get_collateral_token_contract(), assets.get_collateral_quantum())
} else {
let asset_config = assets.get_asset_config(asset_id);
(assets.get_asset_erc20_contract(asset_id), asset_config.quantum)
};

let deposit_hash = deposit_hash(
token_address: token_contract.contract_address,
depositor: caller_address,
Expand All @@ -95,7 +104,6 @@ pub(crate) mod Deposit {
self
.registered_deposits
.write(key: deposit_hash, value: DepositStatus::PENDING(Time::now()));
let quantum = assets.get_collateral_quantum();
let unquantized_amount = quantized_amount * quantum.into();
token_contract
.transfer_from(
Expand All @@ -108,7 +116,7 @@ pub(crate) mod Deposit {
events::Deposit {
position_id,
depositing_address: caller_address,
collateral_id: get_dep_component!(@self, Assets).get_collateral_id(),
collateral_id: asset_id,
quantized_amount,
unquantized_amount,
deposit_request_hash: deposit_hash,
Expand Down Expand Up @@ -197,6 +205,7 @@ pub(crate) mod Deposit {
fn process_deposit(
ref self: ComponentState<TContractState>,
operator_nonce: u64,
asset_id: AssetId,
depositor: ContractAddress,
position_id: PositionId,
quantized_amount: u64,
Expand All @@ -206,9 +215,29 @@ pub(crate) mod Deposit {
get_dep_component!(@self, Pausable).assert_not_paused();
let mut nonce = get_dep_component_mut!(ref self, OperatorNonce);
nonce.use_checked_nonce(:operator_nonce);

let assets = get_dep_component!(@self, Assets);
let token_contract = assets.get_collateral_token_contract();
let (token_contract, quantum, position_diff) = if (asset_id == assets
.get_collateral_id()) {
let position_diff = PositionDiff {
base_collateral_diff: quantized_amount.into(),
synthetic_diff: Option::None,
non_base_collateral_diff: Option::None,
};
(
assets.get_collateral_token_contract(),
assets.get_collateral_quantum(),
position_diff,
)
} else {
let asset_config = assets.get_asset_config(asset_id);
let position_diff = PositionDiff {
base_collateral_diff: 0_i64.into(),
synthetic_diff: Option::None,
non_base_collateral_diff: Option::Some((asset_id, quantized_amount.into())),
};
(assets.get_asset_erc20_contract(asset_id), asset_config.quantum, position_diff)
};

let deposit_hash = deposit_hash(
token_address: token_contract.contract_address,
:depositor,
Expand All @@ -227,20 +256,16 @@ pub(crate) mod Deposit {
DepositStatus::CANCELED => { panic_with_felt252(errors::DEPOSIT_ALREADY_CANCELED) },
DepositStatus::PENDING(_) => {},
}
let quantum = assets.get_collateral_quantum();
let unquantized_amount = quantized_amount * quantum.into();
self.registered_deposits.write(deposit_hash, DepositStatus::PROCESSED);
let mut positions = get_dep_component_mut!(ref self, Positions);
let position_diff = PositionDiff {
collateral_diff: quantized_amount.into(), synthetic_diff: Option::None,
};
positions.apply_diff(:position_id, :position_diff);
self
.emit(
events::DepositProcessed {
position_id,
depositing_address: depositor,
collateral_id: assets.get_collateral_id(),
collateral_id: asset_id,
quantized_amount,
unquantized_amount,
deposit_request_hash: deposit_hash,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
use perpetuals::core::types::asset::AssetId;
use perpetuals::core::types::position::PositionId;
use starknet::ContractAddress;
use starkware_utils::signature::stark::HashType;
use starkware_utils::signature::stark::{HashType, Signature};
use starkware_utils::time::time::{TimeDelta, Timestamp};

#[starknet::interface]
pub trait IDeposit<TContractState> {
/// Deposit is called by the user to add a deposit request.
/// in the case of vault shares the perps contract will call the deposit of the vault shares to
/// the user that initilazes the transfer_into_vault flow
fn deposit(
ref self: TContractState, position_id: PositionId, quantized_amount: u64, salt: felt252,
ref self: TContractState,
asset_id: AssetId,
position_id: PositionId,
quantized_amount: u64,
salt: felt252,
);
fn cancel_deposit(
ref self: TContractState, position_id: PositionId, quantized_amount: u64, salt: felt252,
);
fn process_deposit(
ref self: TContractState,
operator_nonce: u64,
asset_id: AssetId,
depositor: ContractAddress,
position_id: PositionId,
quantized_amount: u64,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,16 +83,20 @@ pub(crate) mod Positions {
self: @ComponentState<TContractState>, position_id: PositionId,
) -> PositionData {
let position = self.get_position_snapshot(:position_id);
let (provisional_delta, synthetics) = self
.derive_funding_delta_and_unchanged_synthetics(
let (provisional_delta, synthetics, collaterals) = self
.derive_funding_delta_and_unchanged_balances(
:position, position_diff: Default::default(),
);
let collateral_balance = self
.get_collateral_provisional_balance(
:position, provisional_delta: Option::Some(provisional_delta),
);

PositionData { synthetics, collateral_balance }
PositionData {
synthetics,
base_collateral_balance: collateral_balance,
other_collateral_balances: collaterals,
}
}

/// This function is primarily used as a view function—knowing the total value and/or
Expand All @@ -101,16 +105,16 @@ pub(crate) mod Positions {
self: @ComponentState<TContractState>, position_id: PositionId,
) -> PositionTVTR {
let position = self.get_position_snapshot(:position_id);
let (provisional_delta, unchanged_synthetics) = self
.derive_funding_delta_and_unchanged_synthetics(
let (provisional_delta, unchanged_synthetics, collaterals) = self
.derive_funding_delta_and_unchanged_balances(
:position, position_diff: Default::default(),
);
let collateral_balance = self
.get_collateral_provisional_balance(
:position, provisional_delta: Option::Some(provisional_delta),
);

calculate_position_tvtr(:unchanged_synthetics, :collateral_balance)
calculate_position_tvtr(:unchanged_synthetics, :collateral_balance, unchanged_collaterals: collaterals)
}

/// This function is mostly used as view function - it's better to use the
Expand Down Expand Up @@ -403,14 +407,25 @@ pub(crate) mod Positions {
position_diff: PositionDiff,
) {
let position_mut = self.get_position_mut(:position_id);
position_mut.collateral_balance.add_and_write(position_diff.collateral_diff);

position_mut.collateral_balance.add_and_write(position_diff.base_collateral_diff);
if let Option::Some((synthetic_id, synthetic_diff)) = position_diff.synthetic_diff {
self
._update_synthetic_balance_and_funding(
position: position_mut, :synthetic_id, :synthetic_diff,
);
};
}
if let Option::Some((asset_id, collateral_diff)) = position_diff
.non_base_collateral_diff {
let current_balance = if let Option::Some(balance) = position_mut
.collateral_balances
.read(key: asset_id) {
balance
} else {
0_i64.into()
};
let new_balance = current_balance + collateral_diff;
position_mut.collateral_balances.write(key: asset_id, value: new_balance);
}
}

fn get_position_snapshot(
Expand Down Expand Up @@ -471,19 +486,28 @@ pub(crate) mod Positions {
/// Returns all assets from the position, excluding assets with zero balance
/// and those included in `position_diff`.
/// Also calculates the provisional funding delta for the position.
fn derive_funding_delta_and_unchanged_synthetics(
fn derive_funding_delta_and_unchanged_balances(
self: @ComponentState<TContractState>,
position: StoragePath<Position>,
position_diff: PositionDiff,
) -> (Balance, Span<SyntheticAsset>) {
) -> (Balance, Span<SyntheticAsset>, Span<SyntheticAsset>) {
let assets = get_dep_component!(self, Assets);
let mut unchanged_synthetics = array![];
let mut unchanged_collaterals = array![];

let synthetic_diff_id = if let Option::Some((id, _)) = position_diff.synthetic_diff {
id
} else {
Default::default()
};

let collateral_diff_id = if let Option::Some((id, _)) = position_diff
.non_base_collateral_diff {
id
} else {
Default::default()
};

let mut provisional_delta: Balance = 0_i64.into();

for (synthetic_id, synthetic) in position.synthetic_balance {
Expand All @@ -501,13 +525,33 @@ pub(crate) mod Positions {
continue;
}

let price = assets.get_synthetic_price(synthetic_id);
let risk_factor = assets.get_synthetic_risk_factor(synthetic_id, balance, price);
let price = assets.get_asset_price(synthetic_id);
let risk_factor = assets.get_asset_risk_factor(synthetic_id, balance, price);
unchanged_synthetics
.append(SyntheticAsset { id: synthetic_id, balance, price, risk_factor });
}

(provisional_delta, unchanged_synthetics.span())
for (collateral_id, collateral_balance) in position.collateral_balances {
if collateral_balance.is_zero() {
continue;
}
if collateral_diff_id == collateral_id {
continue;
}
let price = assets.get_asset_price(collateral_id);
let risk_factor = assets
.get_asset_risk_factor(
synthetic_id: collateral_id, balance: collateral_balance, price: price,
);
unchanged_collaterals
.append(
SyntheticAsset {
id: collateral_id, balance: collateral_balance, price, risk_factor,
},
);
}

(provisional_delta, unchanged_synthetics.span(), unchanged_collaterals.span())
}
}

Expand Down Expand Up @@ -587,13 +631,13 @@ pub(crate) mod Positions {
self: @ComponentState<TContractState>, position: StoragePath<Position>,
) -> PositionState {
let position_diff = Default::default();
let (provisional_delta, unchanged_synthetics) = self
.derive_funding_delta_and_unchanged_synthetics(:position, :position_diff);
let (provisional_delta, unchanged_synthetics, unchanged_collaterals) = self
.derive_funding_delta_and_unchanged_balances(:position, :position_diff);
let collateral_balance = self
.get_collateral_provisional_balance(
:position, provisional_delta: Option::Some(provisional_delta),
);
evaluate_position(:unchanged_synthetics, :collateral_balance)
evaluate_position(:unchanged_synthetics, :unchanged_collaterals, :collateral_balance)
}
}
}
Loading