Overview v0.2 (DEPRECATED)

[DEPRECATED - ONLY FOR REFERENCE] Capturing the core logic behind order placement, matching, finalisation, and settlement in Fermi DEX v0.2

1. Order placement

Adding to Bids/Asks PDA

A new order is placed on the orderbook, by adding it to the bids or asks queue, for later matching. Note, the Order_ID contains complete information on the price-time priority of that trade.

let insert_result = self.bids.insert(Order {
            order_id,
            qty: max_coin_qty,
            owner,
            owner_slot,
        });

Approving tokens

When new orders are placed, the program checks if there is enough tokens in the user's openorders to perform the trade. If not, the delta tokens needed are "approved" from the user, for later just-in-time settlement:

```rust
```rust
Side::Bid => {
                let lock_qty_native = max_native_pc_qty;
                native_pc_qty_locked = Some(lock_qty_native);
                let free_qty_to_lock = lock_qty_native.min(open_orders.native_pc_free);
                let total_deposit_amount = lock_qty_native - free_qty_to_lock;
                //deposit_amount = total_deposit_amount * 2/100; //marginal deposit up front
                deposit_amount = total_deposit_amount; //for test with matching, L1044
                deposit_vault = pc_vault;
```rust
 Side::Ask => {
                native_pc_qty_locked = None;
                let lock_qty_native = max_coin_qty
                    .checked_mul(market.coin_lot_size)
                    .ok_or(error!(ErrorCode::InsufficientFunds))?;
                let free_qty_to_lock = lock_qty_native.min(open_orders.native_coin_free);
                let total_deposit_amount = lock_qty_native - free_qty_to_lock;
                //deposit_amount = total_deposit_amount * 2/100; //marginal deposit up front
                deposit_amount = total_deposit_amount; //for test with matching, L1044
                deposit_vault = coin_vault;
```
                

2. Matching

Any new order is tested against the counterpart of the orderbook (i.e. bids are matched against asks, and vice versa. The price is derived from the orderId using the impl .price().For example, for a bid:

Events tracking matched orders

If a match is found, two appropriate Fill events are added to the eventQ. These will be utilised later for just-in-time settlement of orders.

Note that the bids and asks are updated in case of a fill. If no quantity remains, that order is removed from the BidsPDA or AsksPDA. If an order is partially filled, the Bid or Ask is modified in place to reflect the remaining quantity still to be traded.

3. Finalisation

In the finalisation stage (finalise_bid and finalise_ask), the program checks whether the user has sufficient tokens in their openorders account to complete the trade. If not, it attempts to transfer those tokens from the user/counterparty, to provide just in time liquidity. This is in addition to general validation of the events passed.

Finalize Events

Once liquidity has been fetched for one side of the trade, an EventView::Finalize event is created in place of the original EventView:Fill. This marks the order as "finalized" - therby preventing any double spending, and marking the order eligible for settlement.

4. Settlement

Once liquidity has been fetched from both counterparties for both sides of the order, the order can be settled by the program. This is done by debiting the openOrders balances of one Counterparty, and crediting the same amount to the other counterparty. After settlement, the updated balances of the users are free to be withdrawn, or used for further trades.

Last updated