Skip to content

Commit

Permalink
Order Matching (#46)
Browse files Browse the repository at this point in the history
* minor

* comments and bigvec stubs

* cleanup

* order matching without fees

* basic v0 wip

* match bid and ask

* additional return values

* update

* order matching logic v0

* cleanup

* more cleanup

* comments

* bug fix

* orderfill events, quantity base standard

* separate taker and maker deposit and withdrawals

* simple modifiers for user settle amounts

* update user settle balances after matching

* order filled event

* pool updates

* update

* patch

* bid/ask updates

* bigvec implementation for bid matching

* matching ask bigvec

* taker order id

* math helper improvements

* simplify functions

* update math vars

* separate out taker and maker sections

* refresh user accurately

* slight cleanup

* trying out market order using new format, quite easiy

* cleanups

* BigVec removal

* reformat taker and maker

* nit

* account updates

* cleanup

* cleanup
  • Loading branch information
tonylee08 authored Apr 26, 2024
1 parent 213cbcb commit 55d4118
Show file tree
Hide file tree
Showing 7 changed files with 545 additions and 66 deletions.
6 changes: 4 additions & 2 deletions deepbook/sources/deepbook.move
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ module deepbook::deepbook {
expire_timestamp: u64, // Expiration timestamp in ms
clock: &Clock,
ctx: &mut TxContext,
): u128 {
): (u64, u64, u128) {
pool.place_limit_order(
account,
proof,
Expand All @@ -151,13 +151,15 @@ module deepbook::deepbook {
public fun place_market_order<BaseAsset, QuoteAsset>(
pool: &mut Pool<BaseAsset, QuoteAsset>,
account: &mut Account,
proof: &TradeProof,
client_order_id: u64,
quantity: u64,
is_bid: bool,
ctx: &mut TxContext,
): u128 {
): (u64, u64) {
pool.place_market_order(
account,
proof,
client_order_id,
quantity,
is_bid,
Expand Down
75 changes: 75 additions & 0 deletions deepbook/sources/helper/big_vector.move
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,52 @@ module deepbook::big_vector {
&mut slice[offset]
}

/// This assumes SliceRef is not null. Returns value at offset `offset` in slice `ref`
public fun borrow_mut_ref_offset<E: store>(self: &mut BigVector<E>, ref: SliceRef, offset: u64): &mut E {
let slice = self.borrow_slice_mut(ref);
&mut slice[offset]
}

/// Return whether there is a valid next value in BigVector
public fun valid_next<E: store>(self: &BigVector<E>, ref: SliceRef, offset: u64): bool {
let slice = self.borrow_slice(ref);
(offset + 1 < slice.vals.length() || !slice.next().is_null())
}

/// Gets the next value within slice if exists, if at maximum gets the next element of the next slice
/// Assumes valid_next is true
public fun borrow_mut_next<E: store>(self: &mut BigVector<E>, ref: SliceRef, offset: u64): (SliceRef, u64, &mut E) {
let slice = self.borrow_slice_mut(ref);
if (offset + 1 < slice.vals.length()) {
(ref, offset + 1, &mut slice[offset + 1])
} else {
let next_ref = slice.next();
let next_slice = self.borrow_slice_mut(next_ref);
(next_ref, 0, &mut next_slice.vals[0])
}
}

/// Return whether there is a valid prev value in BigVector
public fun valid_prev<E: store>(self: &BigVector<E>, ref: SliceRef, offset: u64): bool {
let slice = self.borrow_slice(ref);
(offset > 0 || !slice.prev().is_null())
}

/// Gets the prev value within slice if exists, if at minimum gets the last element of the prev slice
/// Assumes valid_prev is true
public fun borrow_prev_mut<E: store>(self: &mut BigVector<E>, ref: SliceRef, offset: u64): (SliceRef, u64, &mut E) {
let slice = self.borrow_slice_mut(ref);
if (offset > 0) {
(ref, offset - 1, &mut slice[offset - 1])
} else {
let prev_ref = slice.prev();
// Borrow the previous slice and get the last element
let prev_slice = self.borrow_slice_mut(prev_ref);
let last_index = prev_slice.vals.length() - 1;
(prev_ref, last_index, &mut prev_slice[last_index])
}
}

// === BigVector Mutators ===

/// Add `val` to `self` at index `key`. Aborts if `key` is already
Expand Down Expand Up @@ -398,6 +444,35 @@ module deepbook::big_vector {
}
}

public fun slice_before<E: store>(
self: &BigVector<E>,
key: u128,
): (SliceRef, u64) {
if (self.root_id == NO_SLICE) {
return (SliceRef { ix: NO_SLICE }, 0)
};

let (ix, leaf, off) = self.find_leaf(key);

// If the key index is 0 or the key is less than the first key in the leaf
if (off == 0 || key < leaf.keys[0]) {
let prev_ref = leaf.prev();
if (prev_ref.is_null()) {
// If there is no previous slice, return NO_SLICE
(SliceRef { ix: NO_SLICE }, 0)
} else {
// Borrow the previous slice to get the last key's index
let prev_slice = self.borrow_slice(prev_ref);
(prev_ref, prev_slice.keys.length() - 1)
}
} else {
// Return the current slice with the index decremented by one if the key does not exactly match
// or use the found offset otherwise
let actual_offset = off - 1;
(SliceRef { ix }, actual_offset)
}
}

/// Borrow a slice from this vector.
public fun borrow_slice<E: store>(
self: &BigVector<E>,
Expand Down
45 changes: 40 additions & 5 deletions deepbook/sources/helper/math.move
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,25 @@ module deepbook::math {
const EUnderflow: u64 = 1;
// <<<<<<<<<<<<<<<<<<<<<<<< Error codes <<<<<<<<<<<<<<<<<<<<<<<<

// multiply two floating numbers and assert the result is non zero
// Note that this function will still round down
public(package) fun mul(x: u64, y: u64): u64 {
let (_, result) = unsafe_mul_round(x, y);
assert!(result > 0, EUnderflow);
result
}

// TODO: verify logic here
public(package) fun mul_round_up(x: u64, y: u64): u64 {
let (is_round_down, result) = unsafe_mul_round(x, y);
assert!(result > 0, EUnderflow);
if (is_round_down) {
result + 1
} else {
result
}
}

// multiply two floating numbers
// also returns whether the result is rounded down
public(package) fun unsafe_mul_round(x: u64, y: u64): (bool, u64) {
Expand All @@ -19,14 +38,30 @@ module deepbook::math {
(is_round_down, (x * y / FLOAT_SCALING_U128) as u64)
}

// multiply two floating numbers and assert the result is non zero
// Note that this function will still round down
public(package) fun mul(x: u64, y: u64): u64 {
let (_, result) = unsafe_mul_round(x, y);
assert!(result > 0, EUnderflow);
/// divide two floating numbers
public(package) fun div(x: u64, y: u64): u64 {
let (_, result) = unsafe_div_round(x, y);
result
}

/// divide two floating numbers
/// also returns whether the result is rounded down
public(package) fun unsafe_div_round(x: u64, y: u64): (bool, u64) {
let x = x as u128;
let y = y as u128;
let mut is_round_down = true;
if ((x * FLOAT_SCALING_U128 % y) == 0) is_round_down = false;
(is_round_down, (x * FLOAT_SCALING_U128 / y) as u64)
}

public(package) fun min(x: u64, y: u64): u64 {
if (x <= y) {
x
} else {
y
}
}

public(package) fun max(x: u64, y: u64): u64 {
if (x > y) {
x
Expand Down
11 changes: 6 additions & 5 deletions deepbook/sources/pool/account.move
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// Copyright (c) Mysten Labs, Inc.
// SPDX-License-Identifier: Apache-2.0

/// The Account is a shared object that holds all of the balances for a user. A combination of `Account` and
/// `TradeProof` are passed into a pool to perform trades. A `TradeProof` can be generated in two ways: by the
/// owner directly, or by any `TradeCap` owner. The owner can generate a `TradeProof` without the risk of
/// equivocation. The `TradeCap` owner, due to it being an owned object, risks equivocation when generating
/// The Account is a shared object that holds all of the balances for a user. A combination of `Account` and
/// `TradeProof` are passed into a pool to perform trades. A `TradeProof` can be generated in two ways: by the
/// owner directly, or by any `TradeCap` owner. The owner can generate a `TradeProof` without the risk of
/// equivocation. The `TradeCap` owner, due to it being an owned object, risks equivocation when generating
/// a `TradeProof`. Generally, a high frequency trading engine will trade as the default owner.
module deepbook::account {
use sui::{
Expand All @@ -23,7 +23,7 @@ module deepbook::account {

const MAX_TRADE_CAPS: u64 = 1000;

/// A shared object that is passed into pools for placing orders.
/// A shared object that is passed into pools for placing orders.
public struct Account has key {
id: UID,
owner: address,
Expand Down Expand Up @@ -55,6 +55,7 @@ module deepbook::account {
}
}

#[allow(lint(share_owned))]
public fun share(account: Account) {
transfer::share_object(account);
}
Expand Down
Loading

0 comments on commit 55d4118

Please sign in to comment.