Skip to content

Commit

Permalink
Calculate in-market based on the stored quote
Browse files Browse the repository at this point in the history
  • Loading branch information
m-lord-renkse committed Mar 4, 2024
1 parent 82a6558 commit f74923b
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 8 deletions.
39 changes: 39 additions & 0 deletions crates/database/src/orders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -716,6 +716,45 @@ pub async fn count_limit_orders_by_owner(
.await
}

#[derive(Debug, sqlx::FromRow)]
pub struct OrderWithQuote {
pub order_buy_amount: BigDecimal,
pub order_sell_amount: BigDecimal,
pub order_fee_amount: BigDecimal,
pub quote_buy_amount: BigDecimal,
pub quote_sell_amount: BigDecimal,
pub quote_gas_amount: f64,
pub quote_gas_price: f64,
pub quote_sell_token_price: f64,
}

pub async fn user_orders_with_quote(
ex: &mut PgConnection,
min_valid_to: i64,
owner: &Address,
) -> Result<Vec<OrderWithQuote>, sqlx::Error> {
#[rustfmt::skip]
const QUERY: &str = const_format::concatcp!(
"SELECT o_quotes.sell_amount as quote_sell_amount, o.sell_amount as order_sell_amount,",
" o_quotes.buy_amount as quote_buy_amount, o.buy_amount as order_buy_amount,",
" o.fee_amount as order_fee_amount, o_quotes.gas_amount as quote_gas_amount,",
" o_quotes.gas_price as quote_gas_price, o_quotes.sell_token_price as quote_sell_token_price",
" FROM order_quotes o_quotes",
" LEFT JOIN (",
" SELECT *",
" FROM (", OPEN_ORDERS,
" AND owner = $2",
" AND class = 'limit'",
" ) AS subquery",
" ) AS o ON o_quotes.order_uid = o.uid"
);
sqlx::query_as::<_, OrderWithQuote>(QUERY)
.bind(min_valid_to)
.bind(owner)
.fetch_all(ex)
.await
}

#[cfg(test)]
mod tests {
use {
Expand Down
40 changes: 39 additions & 1 deletion crates/e2e/tests/e2e/limit_orders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -544,11 +544,29 @@ async fn limit_does_not_apply_to_in_market_orders_test(web3: Web3) {
};
let quote = services.submit_quote(&quote_request).await.unwrap();

// Place "in-market" order
let order = OrderCreation {
sell_token: token_a.address(),
sell_amount: quote.quote.sell_amount,
buy_token: onchain.contracts().weth.address(),
buy_amount: quote.quote.buy_amount.saturating_sub(to_wei(1)),
buy_amount: quote.quote.buy_amount.saturating_sub(to_wei(4)),
valid_to: model::time::now_in_epoch_seconds() + 300,
kind: OrderKind::Sell,
..Default::default()
}
.sign(
EcdsaSigningScheme::Eip712,
&onchain.contracts().domain_separator,
SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()),
);
assert!(services.create_order(&order).await.is_ok());

// Place a "limit" order
let order = OrderCreation {
sell_token: token_a.address(),
sell_amount: to_wei(1),
buy_token: onchain.contracts().weth.address(),
buy_amount: to_wei(3),
valid_to: model::time::now_in_epoch_seconds() + 300,
kind: OrderKind::Sell,
..Default::default()
Expand Down Expand Up @@ -578,6 +596,26 @@ async fn limit_does_not_apply_to_in_market_orders_test(web3: Web3) {
SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()),
);
assert!(services.create_order(&order).await.is_ok());

// Place a "limit" order in order to see if fails
let order = OrderCreation {
sell_token: token_a.address(),
sell_amount: to_wei(1),
buy_token: onchain.contracts().weth.address(),
buy_amount: to_wei(2),
valid_to: model::time::now_in_epoch_seconds() + 300,
kind: OrderKind::Sell,
..Default::default()
}
.sign(
EcdsaSigningScheme::Eip712,
&onchain.contracts().domain_separator,
SecretKeyRef::from(&SecretKey::from_slice(trader.private_key()).unwrap()),
);

let (status, body) = services.create_order(&order).await.unwrap_err();
assert_eq!(status, 400);
assert!(body.contains("TooManyLimitOrders"));
}

async fn forked_mainnet_single_limit_order_test(web3: Web3) {
Expand Down
26 changes: 24 additions & 2 deletions crates/orderbook/src/database/orders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,9 @@ use {
signing_scheme_from,
signing_scheme_into,
},
fee::FeeParameters,
order_quoting::Quote,
order_validation::LimitOrderCounting,
order_validation::{is_order_outside_market_price, Amounts, LimitOrderCounting},
},
sqlx::{types::BigDecimal, Connection, PgConnection},
std::convert::TryInto,
Expand Down Expand Up @@ -374,12 +375,33 @@ impl LimitOrderCounting for Postgres {
.start_timer();

let mut ex = self.pool.acquire().await?;
Ok(database::orders::count_limit_orders_by_owner(
Ok(database::orders::user_orders_with_quote(
&mut ex,
now_in_epoch_seconds().into(),
&ByteArray(owner.0),
)
.await?
.into_iter()
.filter(|order_with_quote| {
is_order_outside_market_price(
&Amounts {
sell: big_decimal_to_u256(&order_with_quote.order_sell_amount).unwrap(),
buy: big_decimal_to_u256(&order_with_quote.order_buy_amount).unwrap(),
fee: big_decimal_to_u256(&order_with_quote.order_fee_amount).unwrap(),
},
&Amounts {
sell: big_decimal_to_u256(&order_with_quote.quote_sell_amount).unwrap(),
buy: big_decimal_to_u256(&order_with_quote.quote_buy_amount).unwrap(),
fee: FeeParameters {
gas_amount: order_with_quote.quote_gas_amount,
gas_price: order_with_quote.quote_gas_price,
sell_token_price: order_with_quote.quote_sell_token_price,
}
.fee(),
},
)
})
.count()
.try_into()
.unwrap())
}
Expand Down
15 changes: 10 additions & 5 deletions crates/shared/src/order_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -669,7 +669,7 @@ impl OrderValidating for OrderValidator {
},
) {
tracing::debug!(%uid, ?owner, ?class, "order being flagged as outside market price");
(OrderClass::Liquidity, Some(quote))
(OrderClass::Limit, Some(quote))
} else {
(class, Some(quote))
}
Expand Down Expand Up @@ -700,7 +700,7 @@ impl OrderValidating for OrderValidator {
}
(class, Some(quote))
}
OrderClass::Liquidity => (class, None),
OrderClass::Liquidity => (OrderClass::Limit, None),
};

let order = Order {
Expand Down Expand Up @@ -1458,8 +1458,12 @@ mod tests {

let validator = OrderValidator::new(
dummy_contract!(WETH9, [0xef; 20]),
hashset!(),
OrderValidPeriodConfiguration::any(),
Arc::new(order_validation::banned::Users::none()),
OrderValidPeriodConfiguration {
min: Duration::from_secs(1),
max_market: Duration::from_secs(100),
max_limit: Duration::from_secs(200),
},
false,
Arc::new(bad_token_detector),
dummy_contract!(HooksTrampoline, [0xcf; 20]),
Expand All @@ -1470,6 +1474,7 @@ mod tests {
MAX_LIMIT_ORDERS_PER_USER,
Arc::new(MockCodeFetching::new()),
Default::default(),
None,
);

let creation = OrderCreation {
Expand Down Expand Up @@ -1677,7 +1682,7 @@ mod tests {

// Out-of-price orders are intentionally marked as liquidity
// orders!
assert_eq!(order.metadata.class, OrderClass::Liquidity);
assert_eq!(order.metadata.class, OrderClass::Limit);
assert!(quote.is_some());
}

Expand Down

0 comments on commit f74923b

Please sign in to comment.