Skip to content

Commit 29dc1e7

Browse files
committed
Fix qty calculation bug. Refactor mulitplier logic.
1 parent abb8b87 commit 29dc1e7

File tree

5 files changed

+51
-50
lines changed

5 files changed

+51
-50
lines changed

program/src/processor/cancel_order.rs

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -163,17 +163,8 @@ pub(crate) fn process(
163163
};
164164
let side = get_side_from_order_id(order_id);
165165

166-
order_summary.total_base_qty = order_summary
167-
.total_base_qty
168-
.checked_mul(market_state.base_currency_multiplier)
169-
.unwrap();
170-
order_summary.total_base_qty_posted = order_summary
171-
.total_base_qty_posted
172-
.checked_mul(market_state.base_currency_multiplier)
173-
.unwrap();
174-
order_summary.total_quote_qty = order_summary
175-
.total_quote_qty
176-
.checked_mul(market_state.quote_currency_multiplier)
166+
market_state
167+
.unscale_order_summary(&mut order_summary)
177168
.unwrap();
178169

179170
match side {

program/src/processor/new_order.rs

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
use crate::{
33
error::DexError,
44
state::{CallBackInfo, DexState, FeeTier, Order, UserAccount},
5+
utils::check_account_owner,
56
utils::{check_account_key, check_signer},
6-
utils::{check_account_owner, fp32_mul},
77
};
88
use agnostic_orderbook::error::AoError;
99
use agnostic_orderbook::state::Side;
@@ -235,8 +235,6 @@ pub(crate) fn process(
235235
let mut user_account_data = accounts.user.data.borrow_mut();
236236
let mut user_account = accounts.load_user_account(&mut user_account_data)?;
237237

238-
let max_base_qty_scaled = max_base_qty / market_state.base_currency_multiplier;
239-
240238
// Check the order size
241239
if max_base_qty < &market_state.min_base_order_size {
242240
msg!("The base order size is too small.");
@@ -262,11 +260,10 @@ pub(crate) fn process(
262260
// We make sure to leave enough quote quantity to pay for taker fees in the worst case
263261
max_quote_qty = fee_tier.remove_taker_fee(max_quote_qty);
264262
}
265-
let max_quote_qty_scaled = max_quote_qty / market_state.quote_currency_multiplier;
266263

267264
let invoke_params = agnostic_orderbook::instruction::new_order::Params {
268-
max_base_qty: max_base_qty_scaled,
269-
max_quote_qty: max_quote_qty_scaled,
265+
max_base_qty: market_state.scale_base_amount(*max_base_qty),
266+
max_quote_qty: market_state.scale_quote_amount(max_quote_qty),
270267
limit_price: *limit_price,
271268
side: FromPrimitive::from_u8(*side).unwrap(),
272269
match_limit: *match_limit,
@@ -294,25 +291,18 @@ pub(crate) fn process(
294291
Ok(s) => s,
295292
};
296293

297-
order_summary.total_base_qty = order_summary
298-
.total_base_qty
299-
.checked_mul(market_state.base_currency_multiplier)
300-
.unwrap();
301-
order_summary.total_base_qty_posted = order_summary
302-
.total_base_qty_posted
303-
.checked_mul(market_state.base_currency_multiplier)
294+
market_state
295+
.unscale_order_summary(&mut order_summary)
304296
.unwrap();
305-
order_summary.total_quote_qty = order_summary
306-
.total_quote_qty
307-
.checked_mul(market_state.quote_currency_multiplier)
297+
298+
let posted_quote_qty = market_state
299+
.get_quote_from_base(order_summary.total_base_qty_posted, *limit_price)
308300
.unwrap();
309301

310302
let (qty_to_transfer, transfer_destination, referral_fee) =
311303
match FromPrimitive::from_u8(*side).unwrap() {
312304
Side::Bid => {
313305
// We update the order summary to properly handle the FOK order type
314-
let posted_quote_qty =
315-
fp32_mul(order_summary.total_base_qty_posted, *limit_price).unwrap();
316306
let matched_quote_qty = order_summary.total_quote_qty - posted_quote_qty;
317307
let taker_fee = fee_tier.taker_fee(matched_quote_qty);
318308
let royalties_fees = matched_quote_qty
@@ -343,8 +333,6 @@ pub(crate) fn process(
343333
.base_token_free
344334
.saturating_sub(order_summary.total_base_qty);
345335
user_account.header.base_token_locked += order_summary.total_base_qty_posted;
346-
let posted_quote_qty =
347-
fp32_mul(order_summary.total_base_qty_posted, *limit_price).unwrap();
348336
let taken_quote_qty = order_summary.total_quote_qty - posted_quote_qty;
349337
let taker_fee = fee_tier.taker_fee(taken_quote_qty);
350338
let royalties_fees = taken_quote_qty
@@ -439,7 +427,7 @@ pub(crate) fn process(
439427
.saturating_sub(order_summary.total_base_qty_posted);
440428
user_account.header.accumulated_taker_quote_volume += order_summary
441429
.total_quote_qty
442-
.saturating_sub(fp32_mul(order_summary.total_base_qty_posted, *limit_price).unwrap());
430+
.saturating_sub(posted_quote_qty);
443431

444432
Ok(())
445433
}

program/src/processor/swap.rs

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,6 @@ pub(crate) fn process(
177177

178178
let market_state = DexState::get(accounts.market)?;
179179

180-
let base_qty_scaled = base_qty / market_state.base_currency_multiplier;
181-
182180
// Check the order size
183181
if base_qty < &market_state.min_base_order_size {
184182
msg!("The base order size is too small.");
@@ -199,7 +197,6 @@ pub(crate) fn process(
199197
// We make sure to leave enough quote quantity to pay for taker fees in the worst case
200198
quote_qty = fee_tier.remove_taker_fee(quote_qty);
201199
}
202-
let quote_qty_scaled = quote_qty / market_state.quote_currency_multiplier;
203200

204201
let mut orderbook_guard = accounts.orderbook.data.borrow_mut();
205202
let orderbook = agnostic_orderbook::state::market_state::MarketState::from_buffer(
@@ -213,10 +210,10 @@ pub(crate) fn process(
213210
match FromPrimitive::from_u8(*side).unwrap() {
214211
Side::Bid => (
215212
u64::MAX,
216-
quote_qty_scaled,
213+
market_state.scale_quote_amount(quote_qty),
217214
u64::MAX - (u64::MAX % tick_size),
218215
),
219-
Side::Ask => (base_qty_scaled, u64::MAX, 0),
216+
Side::Ask => (market_state.scale_base_amount(*base_qty), u64::MAX, 0),
220217
};
221218

222219
let invoke_params = agnostic_orderbook::instruction::new_order::Params {
@@ -250,17 +247,8 @@ pub(crate) fn process(
250247
Ok(s) => s,
251248
};
252249

253-
order_summary.total_base_qty = order_summary
254-
.total_base_qty
255-
.checked_mul(market_state.base_currency_multiplier)
256-
.unwrap();
257-
order_summary.total_base_qty_posted = order_summary
258-
.total_base_qty_posted
259-
.checked_mul(market_state.base_currency_multiplier)
260-
.unwrap();
261-
order_summary.total_quote_qty = order_summary
262-
.total_quote_qty
263-
.checked_mul(market_state.quote_currency_multiplier)
250+
market_state
251+
.unscale_order_summary(&mut order_summary)
264252
.unwrap();
265253

266254
let referral_fee = fee_tier.referral_fee(order_summary.total_quote_qty);

program/src/state.rs

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use agnostic_orderbook::state::orderbook::CallbackInfo;
1+
use agnostic_orderbook::state::{orderbook::CallbackInfo, OrderSummary};
22
use borsh::{BorshDeserialize, BorshSerialize};
33
use bytemuck::{try_cast_slice_mut, try_from_bytes_mut, Pod, Zeroable};
44
use num_derive::{FromPrimitive, ToPrimitive};
@@ -109,6 +109,40 @@ impl DexState {
109109
});
110110
a
111111
}
112+
113+
pub(crate) fn scale_quote_amount(&self, raw_quote_amount: u64) -> u64 {
114+
raw_quote_amount / self.quote_currency_multiplier
115+
}
116+
117+
pub(crate) fn scale_base_amount(&self, raw_base_amount: u64) -> u64 {
118+
raw_base_amount / self.base_currency_multiplier
119+
}
120+
121+
pub(crate) fn unscale_quote_amount(&self, scaled_quote_amount: u64) -> Option<u64> {
122+
scaled_quote_amount.checked_mul(self.quote_currency_multiplier)
123+
}
124+
125+
pub(crate) fn unscale_base_amount(&self, scaled_base_amount: u64) -> Option<u64> {
126+
scaled_base_amount.checked_mul(self.base_currency_multiplier)
127+
}
128+
129+
pub(crate) fn unscale_order_summary(&self, order_summary: &mut OrderSummary) -> Option<()> {
130+
order_summary.total_base_qty = self.unscale_base_amount(order_summary.total_base_qty)?;
131+
order_summary.total_base_qty_posted =
132+
self.unscale_base_amount(order_summary.total_base_qty_posted)?;
133+
order_summary.total_quote_qty = self.unscale_quote_amount(order_summary.total_quote_qty)?;
134+
Some(())
135+
}
136+
137+
pub(crate) fn get_quote_from_base(
138+
&self,
139+
raw_base_amount: u64,
140+
scaled_price_fp32: u64,
141+
) -> Option<u64> {
142+
fp32_mul(raw_base_amount, scaled_price_fp32)
143+
.and_then(|n| n.checked_mul(self.quote_currency_multiplier))
144+
.and_then(|n| n.checked_div(self.base_currency_multiplier))
145+
}
112146
}
113147

114148
/// This header describes a user account's state

program/tests/functional.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,7 @@ async fn test_dex() {
533533
},
534534
swap::Params {
535535
side: agnostic_orderbook::state::Side::Bid as u8,
536-
base_qty: 10,
536+
base_qty: 10_000,
537537
quote_qty: 100000,
538538
match_limit: 10,
539539
has_discount_token_account: 0,

0 commit comments

Comments
 (0)