Skip to content

Commit c02ab3e

Browse files
Bengt Lofgrena5-pickle
authored andcommitted
refactored execute_fast_order fn to be reused
1 parent 27b0cd1 commit c02ab3e

File tree

2 files changed

+258
-367
lines changed
  • solana/programs/matching-engine/src

2 files changed

+258
-367
lines changed

solana/programs/matching-engine/src/fallback/processor/execute_order.rs

Lines changed: 17 additions & 188 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ use solana_program::{instruction::Instruction, program::invoke_signed_unchecked}
99

1010
use crate::{
1111
error::MatchingEngineError,
12+
processor::{get_user_amount_and_new_status_and_penalized, ActiveAuctionAccountInfos},
1213
state::{Auction, AuctionStatus, Custodian, MessageProtocol},
13-
utils::{self, auction::DepositPenalty},
1414
ID,
1515
};
1616

@@ -346,193 +346,28 @@ pub(super) fn process(accounts: &[AccountInfo]) -> Result<()> {
346346
// TODO: Do we have to verify the CCTP message transmitter program is passed
347347
// in?
348348

349-
////////////////////////////////////////////////////////////////////////////
350-
//
351-
// TODO: This execute order logic has been taken from the original execute
352-
// order instructions. We plan on using a helper method instead of copy-
353-
// pasting the same logic here.
354-
//
355-
////////////////////////////////////////////////////////////////////////////
356-
357349
// Prepare the execute order (get the user amount, fill, and order executed event)
358-
let current_slot = Clock::get().unwrap().slot;
359-
360-
// We extend the grace period for locally executed orders. Reserving a sequence number for
361-
// the fast fill will most likely require an additional transaction, so this buffer allows
362-
// the best offer participant to perform his duty without the risk of getting slashed by
363-
// another executor.
364-
let additional_grace_period = match active_auction.target_protocol {
365-
MessageProtocol::Local { .. } => {
366-
crate::EXECUTE_FAST_ORDER_LOCAL_ADDITIONAL_GRACE_PERIOD.into()
367-
}
368-
_ => None,
350+
let active_auction_accounts = ActiveAuctionAccountInfos {
351+
auction_best_offer_token: auction_best_offer_token_info.to_account_info(),
352+
auction_executor_token: executor_token_info.to_account_info(),
353+
auction_initial_offer_token: auction_initial_offer_token_info.to_account_info(),
354+
auction_custody_token: auction_custody_info.to_account_info(),
355+
active_auction: active_auction_info.to_account_info(),
356+
auction_custodian: custodian_info.to_account_info(),
369357
};
370-
371-
let DepositPenalty {
372-
penalty,
373-
user_reward,
374-
} = utils::auction::compute_deposit_penalty(
375-
&auction_config,
376-
active_auction_inner_info,
377-
current_slot,
378-
additional_grace_period,
379-
);
380-
381-
let init_auction_fee = fast_market_order.init_auction_fee;
382-
383-
let user_amount = active_auction_inner_info
384-
.amount_in
385-
.saturating_sub(active_auction_inner_info.offer_price)
386-
.saturating_sub(init_auction_fee)
387-
.saturating_add(user_reward);
388-
389-
// Keep track of the remaining amount in the custody token account. Whatever remains will go
390-
// to the executor.
391-
392358
let custody_token =
393359
TokenAccount::try_deserialize(&mut &auction_custody_info.data.borrow()[..])?;
394-
let mut remaining_custodied_amount = custody_token.amount.saturating_sub(user_amount);
395-
396-
// Offer price + security deposit was checked in placing the initial offer.
397-
let mut deposit_and_fee = active_auction_inner_info
398-
.offer_price
399-
.saturating_add(active_auction_inner_info.security_deposit)
400-
.saturating_sub(user_reward);
401-
402-
let penalized = penalty > 0;
403-
404-
if penalized && auction_best_offer_token_info.key != executor_token_info.key {
405-
deposit_and_fee = deposit_and_fee.saturating_sub(penalty);
406-
}
407-
408-
// Need these seeds in order to transfer tokens and then set authority of auction custody token account to the custodian
409-
let auction_signer_seeds = &[
410-
Auction::SEED_PREFIX,
411-
active_auction.vaa_hash.as_ref(),
412-
&[active_auction.bump],
413-
];
414-
415-
// If the initial offer token account doesn't exist anymore, we have nowhere to send the
416-
// init auction fee. The executor will get these funds instead.
417-
//
418-
// We check that this is a legitimate token account.
419-
if utils::checked_deserialize_token_account(
420-
auction_initial_offer_token_info,
421-
&common::USDC_MINT,
422-
)
423-
.is_some()
424-
{
425-
if auction_best_offer_token_info.key() != auction_initial_offer_token_info.key() {
426-
// Pay the auction initiator their fee.
427-
let transfer_ix = spl_token::instruction::transfer(
428-
&spl_token::ID,
429-
&auction_custody_info.key(),
430-
&auction_initial_offer_token_info.key(),
431-
&active_auction_info.key(),
432-
&[],
433-
init_auction_fee,
434-
)
435-
.unwrap();
436-
437-
invoke_signed_unchecked(&transfer_ix, accounts, &[auction_signer_seeds])?;
438-
// Because the initial offer token was paid this fee, we account for it here.
439-
remaining_custodied_amount =
440-
remaining_custodied_amount.saturating_sub(init_auction_fee);
441-
} else {
442-
// Add it to the reimbursement.
443-
deposit_and_fee = deposit_and_fee
444-
.checked_add(init_auction_fee)
445-
.ok_or_else(|| MatchingEngineError::U64Overflow)?;
446-
}
447-
}
448-
449-
// Return the security deposit and the fee to the highest bidder.
450-
if auction_best_offer_token_info.key == executor_token_info.key {
451-
// If the best offer token is equal to the executor token, just send whatever remains in
452-
// the custody token account.
453-
//
454-
// NOTE: This will revert if the best offer token does not exist. But this will present
455-
// an opportunity for another executor to execute this order and take what the best
456-
// offer token would have received.
457-
let transfer_ix = spl_token::instruction::transfer(
458-
&spl_token::ID,
459-
&auction_custody_info.key(),
460-
&auction_best_offer_token_info.key(),
461-
&active_auction_info.key(),
462-
&[],
463-
deposit_and_fee,
464-
)
465-
.unwrap();
466-
msg!(
467-
"Sending deposit and fee amount {} to best offer token account",
468-
deposit_and_fee
469-
);
470-
invoke_signed_unchecked(&transfer_ix, accounts, &[auction_signer_seeds])?;
471-
} else {
472-
// Otherwise, send the deposit and fee to the best offer token. If the best offer token
473-
// doesn't exist at this point (which would be unusual), we will reserve these funds
474-
// for the executor token.
475-
if utils::checked_deserialize_token_account(
476-
auction_best_offer_token_info,
477-
&common::USDC_MINT,
478-
)
479-
.is_some()
480-
{
481-
let transfer_ix = spl_token::instruction::transfer(
482-
&spl_token::ID,
483-
&auction_custody_info.key(),
484-
&auction_best_offer_token_info.key(),
485-
&active_auction_info.key(),
486-
&[],
487-
deposit_and_fee,
488-
)
489-
.unwrap();
490-
msg!(
491-
"Sending deposit and fee {} to best offer token account",
492-
deposit_and_fee
493-
);
494-
invoke_signed_unchecked(&transfer_ix, accounts, &[auction_signer_seeds])?;
495-
remaining_custodied_amount = remaining_custodied_amount.saturating_sub(deposit_and_fee);
496-
}
497-
498-
// And pay the executor whatever remains in the auction custody token account.
499-
if remaining_custodied_amount > 0 {
500-
let instruction = spl_token::instruction::transfer(
501-
&spl_token::ID,
502-
auction_custody_info.key,
503-
executor_token_info.key,
504-
&active_auction_info.key(),
505-
&[],
506-
remaining_custodied_amount,
507-
)
508-
.unwrap();
509-
msg!(
510-
"Sending remaining custodied amount {} to executor token account",
511-
remaining_custodied_amount
512-
);
513-
invoke_signed_unchecked(&instruction, accounts, &[auction_signer_seeds])?;
514-
}
515-
}
516-
517-
// Set the authority of the custody token account to the custodian. He will take over from
518-
// here.
519-
let set_authority_ix = spl_token::instruction::set_authority(
520-
&spl_token::ID,
521-
auction_custody_info.key,
522-
Some(custodian_info.key),
523-
spl_token::instruction::AuthorityType::AccountOwner,
524-
active_auction_info.key,
525-
&[],
526-
)
527-
.unwrap();
528-
529-
invoke_signed_unchecked(&set_authority_ix, accounts, &[auction_signer_seeds])?;
360+
let (user_amount, new_status, _penalized) = get_user_amount_and_new_status_and_penalized(
361+
&active_auction,
362+
&custody_token,
363+
&auction_config,
364+
fast_market_order.init_auction_fee,
365+
active_auction_accounts,
366+
accounts,
367+
)?;
530368

531369
// Set the active auction status
532-
active_auction.status = AuctionStatus::Completed {
533-
slot: current_slot,
534-
execute_penalty: if penalized { penalty.into() } else { None },
535-
};
370+
active_auction.status = new_status;
536371

537372
let active_auction_info_data: &mut [u8] = &mut active_auction_info.data.borrow_mut();
538373
let mut active_auction_cursor = std::io::Cursor::new(active_auction_info_data);
@@ -549,12 +384,6 @@ pub(super) fn process(accounts: &[AccountInfo]) -> Result<()> {
549384
.unwrap(),
550385
};
551386

552-
////////////////////////////////////////////////////////////////////////////
553-
//
554-
// TODO: See above TODO. This is the end of the copy-pasted logic.
555-
//
556-
////////////////////////////////////////////////////////////////////////////
557-
558387
// TODO: Write test that passes in random keypair for CCTP message account
559388
// to show that not having to check the PDA address is safe.
560389
let (_, new_cctp_message_bump) = Pubkey::find_program_address(

0 commit comments

Comments
 (0)