Skip to content

Commit e6cac3a

Browse files
author
Bengt Lofgren
committed
refactored execute_fast_order fn to be reused
1 parent eb549e9 commit e6cac3a

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

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

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

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

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

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

0 commit comments

Comments
 (0)