Skip to content

Commit

Permalink
Don't discard orders with pre-interactions (#1177)
Browse files Browse the repository at this point in the history
  • Loading branch information
MartinquaXD authored Feb 3, 2023
1 parent 08e953c commit f0b9067
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 17 deletions.
48 changes: 32 additions & 16 deletions crates/autopilot/src/limit_orders/quoter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,12 @@ async fn orders_with_sufficient_balance(
balance_fetcher: &dyn BalanceFetching,
mut orders: Vec<OrderQuotingData>,
) -> Vec<OrderQuotingData> {
let queries = orders.iter().map(query_from).unique().collect_vec();
let queries = orders
.iter()
.filter(|order| order.pre_interactions <= 0)
.map(query_from)
.unique()
.collect_vec();
let balances = balance_fetcher.get_balances(&queries).await;
let balances: HashMap<_, _> = queries
.iter()
Expand All @@ -206,7 +211,11 @@ async fn orders_with_sufficient_balance(
true => balance >= &U256::one(), // any amount would be enough
false => balance >= &big_decimal_to_u256(&order.sell_amount).unwrap(),
};
return has_sufficient_balance;

// It's possible that a pre_interaction transfers the owner the required balance
// so we want to keep them even if the balance is insufficient at the moment.
let could_transfer_money_in = order.pre_interactions > 0;
return could_transfer_money_in || has_sufficient_balance;
}

// In case the balance couldn't be fetched err on the safe side and assume
Expand Down Expand Up @@ -262,13 +271,16 @@ mod tests {

#[tokio::test]
async fn removes_orders_with_insufficient_balance() {
let order = |sell_token, sell_amount: U256, partially_fillable| OrderQuotingData {
owner: ByteArray([1; 20]),
sell_token: ByteArray([sell_token; 20]),
sell_amount: u256_to_big_decimal(&sell_amount),
sell_token_balance: database::orders::SellTokenSource::Erc20,
partially_fillable,
..Default::default()
let order = |sell_token, sell_amount: U256, partially_fillable, pre_interactions| {
OrderQuotingData {
owner: ByteArray([1; 20]),
sell_token: ByteArray([sell_token; 20]),
sell_amount: u256_to_big_decimal(&sell_amount),
sell_token_balance: database::orders::SellTokenSource::Erc20,
partially_fillable,
pre_interactions,
..Default::default()
}
};

let mut balance_fetcher = MockBalanceFetching::new();
Expand All @@ -292,23 +304,27 @@ mod tests {

let orders = vec![
// Balance is sufficient.
order(1, 1_000.into(), false),
order(1, 1_000.into(), false, 0),
// Balance is 1 short.
order(1, 1_001.into(), false),
order(1, 1_001.into(), false, 0),
// For partially fillable orders a single atom is enough.
order(2, U256::MAX, true),
order(2, U256::MAX, true, 0),
// We always keep orders with pre_interactions in case they
// would transfer enough money to the owner before settling the order.
order(2, U256::MAX, false, 1),
// We always keep orders where our balance request fails.
order(3, U256::MAX, false),
order(3, U256::MAX, false, 0),
];

let filtered_orders = orders_with_sufficient_balance(&balance_fetcher, orders).await;

assert_eq!(
filtered_orders,
vec![
order(1, 1_000.into(), false),
order(2, U256::MAX, true),
order(3, U256::MAX, false),
order(1, 1_000.into(), false, 0),
order(2, U256::MAX, true, 0),
order(2, U256::MAX, false, 1),
order(3, U256::MAX, false, 0),
]
);
}
Expand Down
10 changes: 9 additions & 1 deletion crates/database/src/orders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -677,6 +677,7 @@ pub struct OrderQuotingData {
pub sell_amount: BigDecimal,
pub sell_token_balance: SellTokenSource,
pub partially_fillable: bool,
pub pre_interactions: i32,
}

/// Returns all limit orders that are currently waiting to be filled sorted
Expand All @@ -687,7 +688,7 @@ pub fn open_limit_orders(
min_valid_to: i64,
) -> BoxStream<'_, Result<OrderQuotingData, sqlx::Error>> {
const QUERY: &str = const_format::concatcp!(
" SELECT sell_token, buy_token, sell_amount, uid, owner, sell_token_balance, partially_fillable",
" SELECT sell_token, buy_token, sell_amount, uid, owner, sell_token_balance, partially_fillable, cardinality(pre_interactions) as pre_interactions",
" FROM (",
OPEN_ORDERS,
" AND class = 'limit'",
Expand Down Expand Up @@ -1710,6 +1711,12 @@ mod tests {
)
.await
.unwrap();

// Give the order a pre-interaction to test that the query finds it.
insert_or_overwrite_pre_interaction(&mut db, 0, &Default::default(), &ByteArray([1; 56]))
.await
.unwrap();

// Expired limit order.
insert_order(
&mut db,
Expand Down Expand Up @@ -1815,6 +1822,7 @@ mod tests {
assert_eq!(orders.len(), 2);
assert_eq!(orders[0].uid, ByteArray([5; 56]));
assert_eq!(orders[1].uid, ByteArray([1; 56]),);
assert_eq!(orders[1].pre_interactions, 1);

// Invalidate one of the orders through a trade.
crate::events::insert_trade(
Expand Down

0 comments on commit f0b9067

Please sign in to comment.