af_iperps/lib.rs
1#![cfg_attr(all(doc, not(doctest)), feature(doc_cfg))]
2
3//! Move types for Aftermath's `Perpetuals` package
4
5use af_move_type::otw::Otw;
6use af_sui_pkg_sdk::sui_pkg_sdk;
7use af_sui_types::{Address, IdentStr, SUI_FRAMEWORK_ADDRESS};
8use af_utilities::types::ifixed::IFixed;
9use sui_framework_sdk::balance::Balance;
10use sui_framework_sdk::dynamic_object_field::Wrapper;
11use sui_framework_sdk::object::{ID, UID};
12use sui_framework_sdk::sui::SUI;
13use sui_framework_sdk::{Field, FieldTypeTag};
14
15pub mod errors;
16pub mod event_ext;
17pub mod event_instance;
18#[cfg(feature = "graphql")]
19pub mod graphql;
20pub mod math;
21pub mod order_helpers;
22pub mod order_id;
23#[cfg(feature = "stop-orders")]
24pub mod stop_order_helpers;
25
26pub use self::market::{MarketParams, MarketState};
27pub use self::orderbook::Order;
28pub use self::position::Position;
29
30/// Package IDs of the perpetuals contract versions published on testnet, in order of its versions.
31pub const TESTNET_PACKAGE_VERSIONS: &[Address] = &[Address::from_static(
32 "0x1fc71972750d0d81567183a8500befef94d7699aac76edffcca253fe541367fd",
33)];
34
35// Convenient aliases since these types will never exist onchain with a type argument other than an
36// OTW.
37pub type AccountCap = self::account::AccountCap<Otw>;
38pub type AccountCapTypeTag = self::account::AccountCapTypeTag<Otw>;
39pub type Account = self::account::Account<Otw>;
40pub type AccountTypeTag = self::account::AccountTypeTag<Otw>;
41pub type StopOrderTicket = self::stop_orders::StopOrderTicket<Otw>;
42pub type StopOrderTicketTypetag = self::stop_orders::StopOrderTicketTypeTag<Otw>;
43pub type ClearingHouse = self::clearing_house::ClearingHouse<Otw>;
44pub type ClearingHouseTypeTag = self::clearing_house::ClearingHouseTypeTag<Otw>;
45pub type Vault = self::clearing_house::Vault<Otw>;
46pub type VaultTypeTag = self::clearing_house::VaultTypeTag<Otw>;
47
48/// Dynamic field storing a [`Vault`].
49pub type VaultDf = Field<self::keys::MarketVault, Vault>;
50/// Dynamic field storing a [`Position`].
51pub type PositionDf = Field<self::keys::Position, Position>;
52/// Dynamic field storing a leaf in a [`Map`] of [`Order`]s.
53///
54/// [`Map`]: self::ordered_map::Map
55pub type OrderLeafDf = Field<u64, self::ordered_map::Leaf<Order>>;
56/// Dynamic object field wrapper for the [`Orderbook`](orderbook::Orderbook) ID.
57pub type OrderbookDofWrapper = Field<Wrapper<keys::Orderbook>, ID>;
58/// Dynamic object field wrapper for the asks [`Map`](ordered_map::Map) ID.
59pub type AsksMapDofWrapper = Field<Wrapper<keys::AsksMap>, ID>;
60/// Dynamic object field wrapper for the bids [`Map`](ordered_map::Map) ID.
61pub type BidsMapDofWrapper = Field<Wrapper<keys::BidsMap>, ID>;
62
63sui_pkg_sdk!(perpetuals {
64 module account {
65 /// The AccountCap is used to check ownership of `Account` with the same `account_id`.
66 struct AccountCap<!phantom T> has key, store {
67 id: UID,
68 // Account object id
69 account_obj_id: ID,
70 /// Numerical value associated to the account
71 account_id: u64,
72 }
73
74 /// The Account object saves the collateral available to be used in clearing houses.
75 struct Account<!phantom T> has key, store {
76 id: UID,
77 /// Numerical value associated to the account
78 account_id: u64,
79 /// Balance available to be allocated to markets.
80 collateral: Balance<T>,
81 }
82
83 struct IntegratorConfig has store {
84 /// Max **additional** taker fee the user is willing
85 /// to pay for integrator-submitted orders.
86 max_taker_fee: IFixed
87 }
88 }
89
90 module admin {
91 /// Capability object required to perform admin functions.
92 ///
93 /// Minted once when the module is published and transfered to its creator.
94 struct AdminCapability has key, store {
95 id: UID
96 }
97 }
98
99 module adl {
100 /// Capability object required to perform auto-deleverage.
101 struct ADLCapability has key, store {
102 id: UID
103 }
104 }
105
106 module clearing_house {
107 /// The central object that owns the market state.
108 ///
109 /// Dynamic fields:
110 /// - [`position::Position`]
111 /// - [`Vault`]
112 ///
113 /// Dynamic objects:
114 /// - [`orderbook::Orderbook`]
115 struct ClearingHouse<!phantom T> has key {
116 id: UID,
117 version: u64,
118 paused: bool,
119 market_params: market::MarketParams,
120 market_state: market::MarketState
121 }
122
123 /// Stores all deposits from traders for collateral T.
124 /// Stores the funds reserved for covering bad debt from untimely
125 /// liquidations.
126 ///
127 /// The Clearing House keeps track of who owns each share of the vault.
128 struct Vault<!phantom T> has store {
129 collateral_balance: Balance<T>,
130 insurance_fund_balance: Balance<T>,
131 }
132
133 /// Stores the proposed parameters for updating margin ratios
134 struct MarginRatioProposal has store {
135 /// Target timestamp at which to apply the proposed updates
136 maturity: u64,
137 /// Proposed IMR
138 margin_ratio_initial: IFixed,
139 /// Proposed MMR
140 margin_ratio_maintenance: IFixed,
141 }
142
143 /// Stores the proposed parameters for a position's custom fees
144 struct PositionFeesProposal has store {
145 /// Proposed IMR
146 maker_fee: IFixed,
147 /// Proposed MMR
148 taker_fee: IFixed,
149 }
150
151 /// Structure that stores the amount of fees collected by an integrator
152 struct IntegratorVault has store {
153 /// Amount of fees collected by this integrator, in collateral units
154 fees: IFixed,
155 }
156
157 struct IntegratorInfo has copy, drop {
158 integrator_address: address,
159 taker_fee: IFixed,
160 }
161
162 /// Stores the proposed parameters for a position's custom fees
163 struct SettlementPrices has store {
164 /// Base asset's settlement price
165 base_price: IFixed,
166 /// Collateral asset's settlement price
167 collateral_price: IFixed,
168 }
169 /// Used by clearing house to check margin when placing an order
170 struct SessionHotPotato<!phantom T> {
171 clearing_house: ClearingHouse<T>,
172 orderbook: orderbook::Orderbook,
173 account_id: u64,
174 timestamp_ms: u64,
175 collateral_price: IFixed,
176 index_price: IFixed,
177 gas_price: u64,
178 margin_before: IFixed,
179 min_margin_before: IFixed,
180 position_base_before: IFixed,
181 total_open_interest: IFixed,
182 total_fees: IFixed,
183 maker_events: vector<events::FilledMakerOrder>,
184 liqee_account_id: Option<u64>,
185 liquidator_fees: IFixed,
186 session_summary: SessionSummary
187 }
188
189 struct SessionSummary has drop {
190 base_filled_ask: IFixed,
191 base_filled_bid: IFixed,
192 quote_filled_ask: IFixed,
193 quote_filled_bid: IFixed,
194 base_posted_ask: IFixed,
195 base_posted_bid: IFixed,
196 posted_orders: u64,
197 base_liquidated: IFixed,
198 quote_liquidated: IFixed,
199 is_liqee_long: bool,
200 bad_debt: IFixed
201 }
202 }
203
204 module stop_orders {
205 /// Object that allows to place one order on behalf of the user, used to
206 /// offer stop limit or market orders. A stop order is an order that is placed
207 /// only if the index price respects certain conditions, like being above or
208 /// below a certain price.
209 ///
210 /// Only the `AccountCap` owner can mint this object and can decide who can be
211 /// the executor of the ticket. This allows users to run their
212 /// own stop orders bots eventually, but it's mainly used to allow 3rd parties
213 /// to offer such a service (the user is required to trust such 3rd party).
214 /// The object is shared and the 3rd party is set as `executors`. The ticket
215 /// can be destroyed in any moment only by the user or by the executor.
216 /// The user needs to trust the 3rd party for liveness of the service offered.
217 ///
218 /// The order details are encrypted offchain and the result is stored in the ticket.
219 /// The user needs to share such details with the 3rd party only to allow for execution.
220 ///
221 /// The ticket can be either a shared, owned or party object.
222 /// The permission to execute or cancel it is controlled exclusively through `executors`,
223 /// which can be modified only by the `AccountCap` owner associated with the ticket
224 /// using the function `edit_stop_order_ticket_executors`.
225 struct StopOrderTicket<!phantom T> has key, store {
226 id: UID,
227 /// Addresses allowed to execute the order on behalf of the user.
228 executors: vector<address>,
229 /// Gas coin that must be provided by the user to cover for one stop order cost.
230 /// This amount of gas is going to be sent to the executor of the order.
231 gas: Balance<SUI>,
232 /// User account id
233 account_id: u64,
234 /// Value to indentify the stop order type. Available values can be found in the
235 /// constants module.
236 stop_order_type: u64,
237 /// Vector containing the blake2b hash obtained from offchain on the stop order parameters.
238 /// Depending on the stop order type value, a different set of parameters is expected to be used.
239 ///
240 /// Parameters encoded for a SLTP stop order (stop_order_type code 0):
241 /// - clearing_house_id: ID
242 /// - expire_timestamp: Option<u64>
243 /// - is_limit_order: `true` if limit order, `false` if market order
244 /// - stop_index_price: u256
245 /// - is_stop_loss: `true` if stop loss order, `false` if take profit order
246 /// - position_is_ask: `true` if position is short, `false` if position is long
247 /// - size: u64
248 /// - price: u64 (can be set at random value if `is_limit_order` is false)
249 /// - order_type: u64 (can be set at random value if `is_limit_order` is false)
250 /// - salt: vector<u8>
251 ///
252 /// Parameters encoded for a Standalone stop order (stop_order_type code 1):
253 /// - clearing_house_id: ID
254 /// - expire_timestamp: Option<u64>
255 /// - is_limit_order: `true` if limit order, `false` if market order
256 /// - stop_index_price: u256
257 /// - ge_stop_index_price: `true` means the order can be placed when
258 /// oracle index price is >= than chosen `stop_index_price`
259 /// - side: bool
260 /// - size: u64
261 /// - price: u64 (can be set at random value if `is_limit_order` is false)
262 /// - order_type: u64 (can be set at random value if `is_limit_order` is false)
263 /// - reduce_only: bool
264 /// - salt: vector<u8>
265 encrypted_details: vector<u8>
266 }
267 }
268
269 module events {
270 struct CreatedAccount<!phantom T> has copy, drop {
271 account_obj_id: ID,
272 user: address,
273 account_id: u64
274 }
275
276 struct DepositedCollateral<!phantom T> has copy, drop {
277 account_id: u64,
278 collateral: u64,
279 }
280
281 struct AllocatedCollateral has copy, drop {
282 ch_id: ID,
283 account_id: u64,
284 collateral: u64,
285 }
286
287 struct WithdrewCollateral<!phantom T> has copy, drop {
288 account_id: u64,
289 collateral: u64,
290 }
291
292 struct DeallocatedCollateral has copy, drop {
293 ch_id: ID,
294 account_id: u64,
295 collateral: u64,
296 }
297
298 struct CreatedOrderbook has copy, drop {
299 branch_min: u64,
300 branches_merge_max: u64,
301 branch_max: u64,
302 leaf_min: u64,
303 leaves_merge_max: u64,
304 leaf_max: u64
305 }
306
307 struct CreatedClearingHouse has copy, drop {
308 ch_id: ID,
309 collateral: String,
310 coin_decimals: u64,
311 margin_ratio_initial: IFixed,
312 margin_ratio_maintenance: IFixed,
313 base_oracle_id: ID,
314 collateral_oracle_id: ID,
315 funding_frequency_ms: u64,
316 funding_period_ms: u64,
317 premium_twap_frequency_ms: u64,
318 premium_twap_period_ms: u64,
319 spread_twap_frequency_ms: u64,
320 spread_twap_period_ms: u64,
321 maker_fee: IFixed,
322 taker_fee: IFixed,
323 liquidation_fee: IFixed,
324 force_cancel_fee: IFixed,
325 insurance_fund_fee: IFixed,
326 lot_size: u64,
327 tick_size: u64,
328 }
329
330 struct RegisteredMarketInfo<!phantom T> has copy, drop {
331 ch_id: ID,
332 base_pfs_id: ID,
333 collateral_pfs_id: ID,
334 scaling_factor: IFixed
335 }
336
337 struct RemovedRegisteredMarketInfo<!phantom T> has copy, drop {
338 ch_id: ID,
339 }
340
341 struct RegisteredCollateralInfo<!phantom T> has copy, drop {
342 ch_id: ID,
343 collateral_pfs_id: ID,
344 scaling_factor: IFixed
345 }
346
347 struct AddedIntegratorConfig<!phantom T> has copy, drop {
348 account_id: u64,
349 integrator_address: address,
350 max_taker_fee: IFixed
351 }
352
353 struct RemovedIntegratorConfig<!phantom T> has copy, drop {
354 account_id: u64,
355 integrator_address: address,
356 }
357
358 struct PaidIntegratorFees<!phantom T> has copy, drop {
359 account_id: u64,
360 integrator_address: address,
361 fees: IFixed
362 }
363
364 struct CreatedIntegratorVault has copy, drop {
365 ch_id: ID,
366 integrator_address: address,
367 }
368
369 struct WithdrewFromIntegratorVault has copy, drop {
370 ch_id: ID,
371 integrator_address: address,
372 fees: u64
373 }
374
375 struct UpdatedClearingHouseVersion has copy, drop {
376 ch_id: ID,
377 version: u64
378 }
379
380 struct PausedMarket has copy, drop {
381 ch_id: ID,
382 }
383
384 struct ResumedMarket has copy, drop {
385 ch_id: ID,
386 }
387
388 struct ClosedMarket has copy, drop {
389 ch_id: ID,
390 base_settlement_price: IFixed,
391 collateral_settlement_price: IFixed
392 }
393
394 struct ClosedPositionAtSettlementPrices has copy, drop {
395 ch_id: ID,
396 account_id: u64,
397 pnl: IFixed,
398 base_asset_amount: IFixed,
399 quote_asset_amount: IFixed,
400 deallocated_collateral: u64,
401 bad_debt: IFixed
402 }
403
404 struct UpdatedPremiumTwap has copy, drop {
405 ch_id: ID,
406 book_price: IFixed,
407 index_price: IFixed,
408 premium_twap: IFixed,
409 premium_twap_last_upd_ms: u64,
410 }
411
412 struct UpdatedSpreadTwap has copy, drop {
413 ch_id: ID,
414 book_price: IFixed,
415 index_price: IFixed,
416 spread_twap: IFixed,
417 spread_twap_last_upd_ms: u64,
418 }
419
420 struct UpdatedGasPriceTwap has copy, drop {
421 ch_id: ID,
422 gas_price: IFixed,
423 mean: IFixed,
424 variance: IFixed,
425 gas_price_last_upd_ms: u64
426 }
427
428 struct UpdatedGasPriceTwapParameters has copy, drop {
429 ch_id: ID,
430 gas_price_twap_period_ms: u64,
431 gas_price_taker_fee: IFixed,
432 z_score_threshold: IFixed
433 }
434
435 struct UpdatedMarketLotAndTick has copy, drop {
436 ch_id: ID,
437 lot_size: u64,
438 tick_size: u64
439 }
440
441 struct UpdatedFunding has copy, drop {
442 ch_id: ID,
443 cum_funding_rate_long: IFixed,
444 cum_funding_rate_short: IFixed,
445 funding_last_upd_ms: u64,
446 }
447
448 struct SettledFunding has copy, drop {
449 ch_id: ID,
450 account_id: u64,
451 collateral_change_usd: IFixed,
452 collateral_after: IFixed,
453 mkt_funding_rate_long: IFixed,
454 mkt_funding_rate_short: IFixed
455 }
456
457 struct FilledMakerOrders has copy, drop {
458 events: vector<FilledMakerOrder>
459 }
460
461 struct FilledMakerOrder has copy, drop {
462 ch_id: ID,
463 maker_account_id: u64,
464 taker_account_id: u64,
465 order_id: u128,
466 filled_size: u64,
467 remaining_size: u64,
468 canceled_size: u64,
469 pnl: IFixed,
470 fees: IFixed,
471 }
472
473 struct FilledTakerOrder has copy, drop {
474 ch_id: ID,
475 taker_account_id: u64,
476 taker_pnl: IFixed,
477 taker_fees: IFixed,
478 integrator_taker_fees: IFixed,
479 integrator_address: Option<address>,
480 base_asset_delta_ask: IFixed,
481 quote_asset_delta_ask: IFixed,
482 base_asset_delta_bid: IFixed,
483 quote_asset_delta_bid: IFixed,
484 }
485
486 struct PostedOrder has copy, drop {
487 ch_id: ID,
488 account_id: u64,
489 order_id: u128,
490 order_size: u64,
491 reduce_only: bool,
492 expiration_timestamp_ms: Option<u64>
493 }
494
495 struct CanceledOrder has copy, drop {
496 ch_id: ID,
497 account_id: u64,
498 size: u64,
499 order_id: u128,
500 }
501
502 struct LiquidatedPosition has copy, drop {
503 ch_id: ID,
504 liqee_account_id: u64,
505 liqor_account_id: u64,
506 is_liqee_long: bool,
507 base_liquidated: IFixed,
508 quote_liquidated: IFixed,
509 liqee_pnl: IFixed,
510 liquidation_fees: IFixed,
511 force_cancel_fees: IFixed,
512 insurance_fund_fees: IFixed,
513 bad_debt: IFixed
514 }
515
516 struct PerformedLiquidation has copy, drop {
517 ch_id: ID,
518 liqee_account_id: u64,
519 liqor_account_id: u64,
520 is_liqee_long: bool,
521 base_liquidated: IFixed,
522 quote_liquidated: IFixed,
523 liqor_pnl: IFixed,
524 liqor_fees: IFixed,
525 }
526
527 struct SocializedBadDebt has copy, drop {
528 ch_id: ID,
529 bad_debt_usd: IFixed,
530 socialized_fundings: IFixed,
531 added_to_long: bool,
532 cum_funding_rate_long: IFixed,
533 cum_funding_rate_short: IFixed,
534 }
535
536 struct PerformedADL has copy, drop {
537 ch_id: ID,
538 bad_debt_account_id: u64,
539 size_reduced: u64,
540 adl_price: u64,
541 counterparty_account_id: u64,
542 bad_debt_is_long: bool,
543 }
544
545 struct CreatedPosition has copy, drop {
546 ch_id: ID,
547 account_id: u64,
548 mkt_funding_rate_long: IFixed,
549 mkt_funding_rate_short: IFixed,
550 }
551
552 struct SetPositionInitialMarginRatio has copy, drop {
553 ch_id: ID,
554 account_id: u64,
555 initial_margin_ratio: IFixed,
556 }
557
558 struct CreatedStopOrderTicket<!phantom T> has copy, drop {
559 ticket_id: ID,
560 account_id: u64,
561 executors: vector<address>,
562 gas: u64,
563 stop_order_type: u64,
564 encrypted_details: vector<u8>
565 }
566
567 struct ExecutedStopOrderTicket<!phantom T> has copy, drop {
568 ticket_id: ID,
569 account_id: u64,
570 executor: address
571 }
572
573 struct DeletedStopOrderTicket<!phantom T> has copy, drop {
574 ticket_id: ID,
575 account_id: u64,
576 executor: address
577 }
578
579 struct EditedStopOrderTicketDetails<!phantom T> has copy, drop {
580 ticket_id: ID,
581 account_id: u64,
582 stop_order_type: u64,
583 encrypted_details: vector<u8>
584 }
585
586 struct EditedStopOrderTicketExecutors<!phantom T> has copy, drop {
587 ticket_id: ID,
588 account_id: u64,
589 executors: vector<address>
590 }
591
592 struct CreatedMarginRatiosProposal has copy, drop {
593 ch_id: ID,
594 margin_ratio_initial: IFixed,
595 margin_ratio_maintenance: IFixed,
596 }
597
598 struct UpdatedMarginRatios has copy, drop {
599 ch_id: ID,
600 margin_ratio_initial: IFixed,
601 margin_ratio_maintenance: IFixed,
602 }
603
604 struct DeletedMarginRatiosProposal has copy, drop {
605 ch_id: ID,
606 margin_ratio_initial: IFixed,
607 margin_ratio_maintenance: IFixed,
608 }
609
610 struct CreatedPositionFeesProposal has copy, drop {
611 ch_id: ID,
612 account_id: u64,
613 maker_fee: IFixed,
614 taker_fee: IFixed,
615 }
616
617 struct DeletedPositionFeesProposal has copy, drop {
618 ch_id: ID,
619 account_id: u64,
620 maker_fee: IFixed,
621 taker_fee: IFixed,
622 }
623
624 struct AcceptedPositionFeesProposal has copy, drop {
625 ch_id: ID,
626 account_id: u64,
627 maker_fee: IFixed,
628 taker_fee: IFixed,
629 }
630
631 struct RejectedPositionFeesProposal has copy, drop {
632 ch_id: ID,
633 account_id: u64,
634 maker_fee: IFixed,
635 taker_fee: IFixed,
636 }
637
638 struct ResettedPositionFees has copy, drop {
639 ch_id: ID,
640 account_id: u64,
641 }
642
643 struct UpdatedFees has copy, drop {
644 ch_id: ID,
645 maker_fee: IFixed,
646 taker_fee: IFixed,
647 liquidation_fee: IFixed,
648 force_cancel_fee: IFixed,
649 insurance_fund_fee: IFixed,
650 }
651
652 struct UpdatedFundingParameters has copy, drop {
653 ch_id: ID,
654 funding_frequency_ms: u64,
655 funding_period_ms: u64,
656 premium_twap_frequency_ms: u64,
657 premium_twap_period_ms: u64,
658 }
659
660 struct UpdatedSpreadTwapParameters has copy, drop {
661 ch_id: ID,
662 spread_twap_frequency_ms: u64,
663 spread_twap_period_ms: u64
664 }
665
666 struct UpdatedMinOrderUsdValue has copy, drop {
667 ch_id: ID,
668 min_order_usd_value: IFixed,
669 }
670
671 struct UpdatedBasePfsID has copy, drop {
672 ch_id: ID,
673 pfs_id: ID,
674 }
675
676 struct UpdatedCollateralPfsID has copy, drop {
677 ch_id: ID,
678 pfs_id: ID,
679 }
680
681 struct UpdatedBasePfsSourceID has copy, drop {
682 ch_id: ID,
683 source_id: ID,
684 }
685
686 struct UpdatedCollateralPfsSourceID has copy, drop {
687 ch_id: ID,
688 source_id: ID,
689 }
690
691 struct UpdatedBasePfsTolerance has copy, drop {
692 ch_id: ID,
693 pfs_tolerance: u64,
694 }
695
696 struct UpdatedCollateralPfsTolerance has copy, drop {
697 ch_id: ID,
698 pfs_tolerance: u64,
699 }
700
701 struct UpdatedMaxSocializeLossesMrDecrease has copy, drop {
702 ch_id: ID,
703 max_socialize_losses_mr_decrease: IFixed,
704 }
705 struct UpdatedMaxBadDebt has copy, drop {
706 ch_id: ID,
707 max_bad_debt: IFixed,
708 }
709
710 struct UpdatedCollateralHaircut has copy, drop {
711 ch_id: ID,
712 collateral_haircut: IFixed,
713 }
714
715 struct UpdatedMaxOpenInterest has copy, drop {
716 ch_id: ID,
717 max_open_interest: IFixed,
718 }
719
720 struct UpdatedMaxOpenInterestPositionParams has copy, drop {
721 ch_id: ID,
722 max_open_interest_threshold: IFixed,
723 max_open_interest_position_percent: IFixed,
724 }
725
726 struct UpdatedMaxPendingOrders has copy, drop {
727 ch_id: ID,
728 max_pending_orders: u64
729 }
730
731 struct UpdatedStopOrderMistCost has copy, drop {
732 stop_order_mist_cost: u64
733 }
734
735 struct DonatedToInsuranceFund has copy, drop {
736 sender: address,
737 ch_id: ID,
738 new_balance: u64,
739 }
740
741 struct WithdrewFees has copy, drop {
742 sender: address,
743 ch_id: ID,
744 amount: u64,
745 vault_balance_after: u64,
746 }
747
748 struct WithdrewInsuranceFund has copy, drop {
749 sender: address,
750 ch_id: ID,
751 amount: u64,
752 insurance_fund_balance_after: u64,
753 }
754
755 struct UpdatedOpenInterestAndFeesAccrued has copy, drop {
756 ch_id: ID,
757 open_interest: IFixed,
758 fees_accrued: IFixed
759 }
760 }
761
762 module keys {
763 /// Key type for accessing a `MarketInfo` saved in registry.
764 struct RegistryMarketInfo has copy, drop, store {
765 ch_id: ID
766 }
767
768 /// Key type for accessing a `CollateralInfo` saved in registry.
769 struct RegistryCollateralInfo<!phantom T> has copy, drop, store {}
770
771 /// Key type for accessing a `Config` saved in registry.
772 struct RegistryConfig has copy, drop, store {}
773
774 /// Key type for accessing integrator configs for an account.
775 struct IntegratorConfig has copy, drop, store {
776 integrator_address: address,
777 }
778
779 /// Key type for accessing integrator's collected fees.
780 struct IntegratorVault has copy, drop, store {
781 integrator_address: address,
782 }
783
784 /// Key type for accessing in clearing house.
785 struct SettlementPrices has copy, drop, store {}
786
787 /// Key type for accessing market params in clearing house.
788 struct Orderbook has copy, drop, store {}
789
790 /// Key type for accessing vault in clearing house.
791 struct MarketVault has copy, drop, store {}
792
793 /// Key type for accessing trader position in clearing house.
794 struct Position has copy, drop, store {
795 account_id: u64,
796 }
797
798 /// Key type for accessing market margin parameters change proposal in clearing house.
799 struct MarginRatioProposal has copy, drop, store {}
800
801 /// Key type for accessing custom fees parameters change proposal for an account
802 struct PositionFeesProposal has copy, drop, store {
803 account_id: u64
804 }
805
806 /// Key type for accessing asks map in the orderbook
807 struct AsksMap has copy, drop, store {}
808
809 /// Key type for accessing asks map in the orderbook
810 struct BidsMap has copy, drop, store {}
811 }
812
813 module market {
814 /// Static attributes of a perpetuals market.
815 struct MarketParams has copy, drop, store {
816 /// Set of parameters governing market's core behaviors
817 core_params: CoreParams,
818 /// Set of parameters related to market's fees
819 fees_params: FeesParams,
820 /// Set of parameters governing fundings and twap updates
821 twap_params: TwapParams,
822 /// Set of parameters defining market's limits
823 limits_params: LimitsParams
824 }
825
826 struct CoreParams has copy, drop, store {
827 /// Identifier of the base asset's price feed storage.
828 base_pfs_id: ID,
829 /// Identifier of the collateral asset's price feed storage.
830 collateral_pfs_id: ID,
831 /// Identifier of the base asset's price feed storage source id (pyth, stork, etc...).
832 base_pfs_source_id: ID,
833 /// Identifier of the collateral asset's price feed storage source id (pyth, stork, etc...).
834 collateral_pfs_source_id: ID,
835 /// Timestamp tolerance for base oracle price
836 base_pfs_tolerance: u64,
837 /// Timestamp tolerance for collateral oracle price
838 collateral_pfs_tolerance: u64,
839 /// Number of base units exchanged per lot
840 lot_size: u64,
841 /// Number of quote units exchanged per tick
842 tick_size: u64,
843 /// Scaling factor to use to convert collateral units to ifixed values and viceversa
844 scaling_factor: IFixed,
845 /// Value haircut applied to collateral allocated in the position.
846 /// Example: 98%
847 collateral_haircut: IFixed,
848 /// Minimum margin ratio for opening a new position.
849 margin_ratio_initial: IFixed,
850 /// Margin ratio below which full liquidations can occur.
851 margin_ratio_maintenance: IFixed,
852 }
853
854 struct FeesParams has copy, drop, store {
855 /// Proportion of volume charged as fees from makers upon processing
856 /// fill events.
857 maker_fee: IFixed,
858 /// Proportion of volume charged as fees from takers after processing
859 /// fill events.
860 taker_fee: IFixed,
861 /// Proportion of volume charged as fees from liquidatees
862 liquidation_fee: IFixed,
863 /// Proportion of volume charged as fees from liquidatees after forced cancelling
864 /// of pending orders during liquidation.
865 force_cancel_fee: IFixed,
866 /// Proportion of volume charged as fees from liquidatees to deposit into insurance fund
867 insurance_fund_fee: IFixed,
868 /// Additional taker fee to apply in case the gas price set for the transaction violates
869 /// the z-score constraint
870 gas_price_taker_fee: IFixed,
871 }
872
873 struct TwapParams has copy, drop, store {
874 /// The time span between each funding rate update.
875 funding_frequency_ms: u64,
876 /// Period of time over which funding (the difference between book and
877 /// index prices) gets paid.
878 ///
879 /// Setting the funding period too long may cause the perpetual to start
880 /// trading at a very dislocated price to the index because there's less
881 /// of an incentive for basis arbitrageurs to push the prices back in
882 /// line since they would have to carry the basis risk for a longer
883 /// period of time.
884 ///
885 /// Setting the funding period too short may cause nobody to trade the
886 /// perpetual because there's too punitive of a price to pay in the case
887 /// the funding rate flips sign.
888 funding_period_ms: u64,
889 /// The time span between each funding TWAP (both index price and orderbook price) update.
890 premium_twap_frequency_ms: u64,
891 /// The reference time span used for weighting the TWAP (both index price and orderbook price)
892 /// updates for funding rates estimation
893 premium_twap_period_ms: u64,
894 /// The time span between each spread TWAP updates (used for liquidations).
895 spread_twap_frequency_ms: u64,
896 /// The reference time span used for weighting the TWAP updates for spread.
897 spread_twap_period_ms: u64,
898 /// The reference time span used for weighting the TWAP updates for gas price.
899 gas_price_twap_period_ms: u64,
900 }
901
902 struct LimitsParams has copy, drop, store {
903 /// Minimum USD value an order is required to be worth to be placed
904 min_order_usd_value: IFixed,
905 /// Maximum number of pending orders that a position can have.
906 max_pending_orders: u64,
907 /// Max open interest (in base tokens) available for this market
908 max_open_interest: IFixed,
909 /// The check on `max_open_interest_position_percent` is not performed if
910 /// the market's open interest is below this threshold.
911 max_open_interest_threshold: IFixed,
912 /// Max open interest percentage a position can have relative to total market's open interest
913 max_open_interest_position_percent: IFixed,
914 /// Max amount of bad debt that can be socialized in nominal value.
915 /// Positions that violate this check should be ADL'd.
916 max_bad_debt: IFixed,
917 /// Max amount of bad debt that can be socialized relative to total market's open interest.
918 /// Positions that violate this check should be ADL'd.
919 max_socialize_losses_mr_decrease: IFixed,
920 /// Z-Score threshold level used to determine if to apply `gas_price_taker_fee` to the
921 /// executed order
922 z_score_threshold: IFixed,
923 }
924 /// The state of a perpetuals market.
925 struct MarketState has store {
926 /// The latest cumulative funding premium in this market for longs. Must be updated
927 /// periodically.
928 cum_funding_rate_long: IFixed,
929 /// The latest cumulative funding premium in this market for shorts. Must be updated
930 /// periodically.
931 cum_funding_rate_short: IFixed,
932 /// The timestamp (millisec) of the latest cumulative funding premium update
933 /// (both longs and shorts).
934 funding_last_upd_ms: u64,
935 /// The last calculated funding premium TWAP (used for funding settlement).
936 premium_twap: IFixed,
937 /// The timestamp (millisec) of the last update of `premium_twap`.
938 premium_twap_last_upd_ms: u64,
939 /// The last calculated spread TWAP (used for liquidations).
940 /// Spread is (book - index).
941 spread_twap: IFixed,
942 /// The timestamp (millisec) of `spread_twap` last update.
943 spread_twap_last_upd_ms: u64,
944 /// Gas price TWAP mean.
945 /// It is used to calculate the penalty to add to taker fees based on the Z-score of the current gas price
946 /// relative to the smoothed mean and variance.
947 gas_price_mean: IFixed,
948 /// Gas price TWAP variance.
949 /// It is used to calculate the penalty to add to taker fees based on the Z-score of the current gas price
950 /// relative to the smoothed mean and variance.
951 gas_price_variance: IFixed,
952 /// The timestamp (millisec) of the last update of `gas_price_mean` and `gas_price_variance`.
953 gas_price_last_upd_ms: u64,
954 /// Open interest (in base tokens) as a fixed-point number. Counts the
955 /// total size of contracts as the sum of all long positions.
956 open_interest: IFixed,
957 /// Total amount of fees accrued by this market (in T's units)
958 /// Only admin can withdraw these fees.
959 fees_accrued: IFixed,
960 }
961 }
962
963 module orderbook {
964 /// An order on the orderbook
965 struct Order has copy, drop, store {
966 /// User's account id
967 account_id: u64,
968 /// Amount of lots to be filled
969 size: u64,
970 /// Optional reduce-only requirement for this order.
971 reduce_only: bool,
972 /// Optional expiration time for the order
973 expiration_timestamp_ms: Option<u64>
974 }
975
976 /// The orderbook doesn't know the types of tokens traded, it assumes a correct
977 /// management by the clearing house
978 struct Orderbook has key, store {
979 id: UID,
980 /// Number of limit orders placed on book, monotonically increases
981 counter: u64,
982 }
983 }
984
985 module ordered_map {
986 /// Ordered map with `u128` type as a key and `V` type as a value.
987 struct Map<!phantom V: copy + drop + store> has key, store {
988 /// Object UID for adding dynamic fields that are used as pointers to nodes.
989 id: UID,
990 /// Number of key-value pairs in the map.
991 size: u64,
992 /// Counter for creating another node as a dynamic field.
993 counter: u64,
994 /// Pointer to the root node, which is a branch or a leaf.
995 root: u64,
996 /// Pointer to first leaf.
997 first: u64,
998 /// Minimal number of kids in a non-root branch;
999 /// must satisfy 2 <= branch_min <= branch_max / 2.
1000 branch_min: u64,
1001 /// Maximal number of kids in a branch, which is merge of two branches;
1002 /// must satisfy 2 * branch_min <= branches_merge_max <= branch_max.
1003 branches_merge_max: u64,
1004 /// Maximal number of kids in a branch.
1005 branch_max: u64,
1006 /// Minimal number of elements in a non-root leaf;
1007 /// must satisfy 2 <= leaf_min <= (leaf_max + 1) / 2.
1008 leaf_min: u64,
1009 /// Maximal number of elements in a leaf, which is merge of two leaves;
1010 /// must satisfy 2 * leaf_min - 1 <= leaves_merge_max <= leaf_max.
1011 leaves_merge_max: u64,
1012 /// Maximal number of elements in a leaf.
1013 leaf_max: u64,
1014 }
1015
1016 /// Branch node with kids and ordered separating keys.
1017 struct Branch has drop, store {
1018 /// Separating keys for kids sorted in ascending order.
1019 keys: vector<u128>,
1020 /// Kids of the node.
1021 kids: vector<u64>,
1022 }
1023
1024 /// Key-value pair.
1025 struct Pair<V: copy + drop + store> has copy, drop, store {
1026 key: u128,
1027 val: V,
1028 }
1029
1030 /// Leaf node with ordered key-value pairs.
1031 struct Leaf<V: copy + drop + store> has drop, store {
1032 /// Keys sorted in ascending order together with values.
1033 keys_vals: vector<Pair<V>>,
1034 /// Pointer to next leaf.
1035 next: u64,
1036 }
1037 }
1038
1039 module position {
1040 /// Stores information about an open position
1041 struct Position has store {
1042 /// Amount of allocated tokens (e.g., USD stables) backing this account's position.
1043 collateral: IFixed,
1044 /// The perpetual contract size, controlling the amount of exposure to
1045 /// the underlying asset. Positive implies long position and negative,
1046 /// short. Represented as a signed fixed-point number.
1047 base_asset_amount: IFixed,
1048 /// The entry value for this position, including leverage. Represented
1049 /// as a signed fixed-point number.
1050 quote_asset_notional_amount: IFixed,
1051 /// Last long cumulative funding rate used to update this position. The
1052 /// market's latest long cumulative funding rate minus this gives the funding
1053 /// rate this position must pay. This rate multiplied by this position's
1054 /// value (base asset amount * market price) gives the total funding
1055 /// owed, which is deducted from the trader account's margin. This debt
1056 /// is accounted for in margin ratio calculations, which may lead to
1057 /// liquidation. Represented as a signed fixed-point number.
1058 cum_funding_rate_long: IFixed,
1059 /// Last short cumulative funding rate used to update this position. The
1060 /// market's latest short cumulative funding rate minus this gives the funding
1061 /// rate this position must pay. This rate multiplied by this position's
1062 /// value (base asset amount * market price) gives the total funding
1063 /// owed, which is deducted from the trader account's margin. This debt
1064 /// is accounted for in margin ratio calculations, which may lead to
1065 /// liquidation. Represented as a signed fixed-point number.
1066 cum_funding_rate_short: IFixed,
1067 /// Base asset amount resting in ask orders in the orderbook.
1068 /// Represented as a signed fixed-point number.
1069 asks_quantity: IFixed,
1070 /// Base asset amount resting in bid orders in the orderbook.
1071 /// Represented as a signed fixed-point number.
1072 bids_quantity: IFixed,
1073 /// Number of pending orders in this position.
1074 pending_orders: u64,
1075 /// Custom maker fee for this position, set at default value of 100%
1076 maker_fee: IFixed,
1077 /// Custom taker fee for this position, set at default value of 100%
1078 taker_fee: IFixed,
1079 /// Initial Margin Ratio set by user for the position. Must always be less
1080 /// or equal than market's IMR. Used as a desired reference margin ratio when
1081 /// managing collateral in the position during all the actions. Can be changed
1082 /// by the user at any moment (between the allowed limits).
1083 initial_margin_ratio: IFixed
1084 }
1085 }
1086
1087 module registry {
1088 /// Registry object that maintains:
1089 /// - A mapping between a clearing house id and `MarketInfo`
1090 /// - A mapping between a collateral type `T` and `CollateralInfo`
1091 /// It also maintains the global counter for account creation.
1092 /// Minted and shared when the module is published.
1093 struct Registry has key {
1094 id: UID,
1095 next_account_id: u64
1096 }
1097
1098 /// Struct containing all the immutable info about a registered market
1099 struct MarketInfo<!phantom T> has store {
1100 base_pfs_id: ID,
1101 collateral_pfs_id: ID,
1102 scaling_factor: IFixed
1103 }
1104
1105 /// Struct containing all the immutable info about the collateral
1106 /// used in one or more markets
1107 struct CollateralInfo<!phantom T> has store {
1108 collateral_pfs_id: ID,
1109 scaling_factor: IFixed
1110 }
1111
1112 /// Config that stores useful info for the protocol
1113 struct Config has store {
1114 stop_order_mist_cost: u64,
1115 }
1116 }
1117});
1118
1119impl<T: af_move_type::MoveType> clearing_house::ClearingHouse<T> {
1120 /// Convenience function to build the type of a [`PositionDf`].
1121 pub fn position_df_type(package: Address) -> FieldTypeTag<self::keys::Position, Position> {
1122 Field::type_(
1123 self::keys::Position::type_(package),
1124 Position::type_(package),
1125 )
1126 }
1127
1128 /// Convenience function to build the type of an [`OrderbookDofWrapper`].
1129 pub fn orderbook_dof_wrapper_type(
1130 package: Address,
1131 ) -> FieldTypeTag<Wrapper<keys::Orderbook>, ID> {
1132 Field::type_(
1133 Wrapper::type_(keys::Orderbook::type_(package)),
1134 ID::type_(SUI_FRAMEWORK_ADDRESS, IdentStr::cast("object").to_owned()),
1135 )
1136 }
1137
1138 /// The ID of the package that governs this clearing house's logic.
1139 ///
1140 /// This may be different than the package defining the clearing house's type because a package
1141 /// upgrade + `interface::upgrade_clearing_house_version` call can change
1142 /// [`ClearingHouse::version`] so that the upgraded package is the one that is allowed to make
1143 /// changes to it.
1144 ///
1145 /// Attempting to make a PTB Move call that mutates this clearing house but is not defined in
1146 /// this package version will fail.
1147 pub const fn governing_package_testnet(&self) -> Address {
1148 // NOTE: we published the most recent testnet contracts starting with `VERSION = 1`
1149 TESTNET_PACKAGE_VERSIONS[self.version as usize - 1]
1150 }
1151}
1152
1153impl self::orderbook::Orderbook {
1154 /// Convenience function to build the type of an [`AsksMapDofWrapper`].
1155 pub fn asks_dof_wrapper_type(package: Address) -> FieldTypeTag<Wrapper<keys::AsksMap>, ID> {
1156 Field::type_(
1157 Wrapper::type_(keys::AsksMap::type_(package)),
1158 ID::type_(SUI_FRAMEWORK_ADDRESS, IdentStr::cast("object").to_owned()),
1159 )
1160 }
1161
1162 /// Convenience function to build the type of an [`BidsMapDofWrapper`].
1163 pub fn bids_dof_wrapper_type(package: Address) -> FieldTypeTag<Wrapper<keys::BidsMap>, ID> {
1164 Field::type_(
1165 Wrapper::type_(keys::BidsMap::type_(package)),
1166 ID::type_(SUI_FRAMEWORK_ADDRESS, IdentStr::cast("object").to_owned()),
1167 )
1168 }
1169}
1170
1171impl self::ordered_map::Map<Order> {
1172 /// Convenience function to build the type of an [`OrderLeafDf`].
1173 pub fn leaf_df_type(package: Address) -> FieldTypeTag<u64, self::ordered_map::Leaf<Order>> {
1174 Field::type_(
1175 af_move_type::U64TypeTag,
1176 self::ordered_map::Leaf::type_(package, Order::type_(package)),
1177 )
1178 }
1179}
1180
1181#[cfg(test)]
1182mod tests {
1183 /// Taken from
1184 /// <https://github.com/cargo-public-api/cargo-public-api?tab=readme-ov-file#-as-a-ci-check>
1185 #[test]
1186 fn public_api() {
1187 // Install a compatible nightly toolchain if it is missing
1188 rustup_toolchain::install(public_api::MINIMUM_NIGHTLY_RUST_VERSION).unwrap();
1189
1190 // Build rustdoc JSON
1191 let rustdoc_json = rustdoc_json::Builder::default()
1192 .toolchain(public_api::MINIMUM_NIGHTLY_RUST_VERSION)
1193 .build()
1194 .unwrap();
1195
1196 // Derive the public API from the rustdoc JSON
1197 let public_api = public_api::Builder::from_rustdoc_json(rustdoc_json)
1198 .omit_blanket_impls(true)
1199 .omit_auto_trait_impls(true)
1200 .omit_auto_derived_impls(true)
1201 .build()
1202 .unwrap();
1203
1204 // Assert that the public API looks correct
1205 insta::assert_snapshot!(public_api);
1206 }
1207}