Skip to content

Commit 99a3e48

Browse files
author
Bengt Lofgren
committed
instruction checks added
1 parent 45d2880 commit 99a3e48

File tree

1 file changed

+129
-45
lines changed

1 file changed

+129
-45
lines changed

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

Lines changed: 129 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use crate::ID;
12
use anchor_lang::{prelude::*, Discriminator};
23
use anchor_spl::token::{spl_token, TokenAccount};
34
use common::wormhole_io::TypePrefixedPayload;
@@ -12,7 +13,7 @@ use crate::{
1213

1314
use super::{
1415
burn_and_post::{burn_and_post, PostMessageAccounts, PostMessageDerivedAccounts},
15-
helpers::{require_min_account_infos_len, create_account_reliably},
16+
helpers::{create_account_reliably, require_min_account_infos_len},
1617
};
1718

1819
#[derive(Copy, Clone)]
@@ -38,81 +39,81 @@ impl SettleAuctionNoneCctpShimData {
3839

3940
pub struct SettleAuctionNoneCctpShimAccounts<'ix> {
4041
/// Payer of the account
41-
pub payer: &'ix Pubkey, // 0
42+
pub payer: &'ix Pubkey, // 0
4243
/// Post shim message account
43-
pub post_shim_message: &'ix Pubkey, // 1
44+
pub post_shim_message: &'ix Pubkey, // 1
4445
/// Core bridge emitter sequence account
45-
pub core_bridge_emitter_sequence: &'ix Pubkey, // 2
46-
/// Post message shim event authority CHECK: Mutable. Seeds must be \["core-msg", payer, payer_sequence.value\].
47-
pub post_message_shim_event_authority: &'ix Pubkey, // 3
46+
pub core_bridge_emitter_sequence: &'ix Pubkey, // 2
47+
/// Post message shim event authority
48+
pub post_message_shim_event_authority: &'ix Pubkey, // 3
4849
/// Post message shim program
49-
pub post_message_shim_program: &'ix Pubkey, // 4
50-
/// Cctp message
51-
pub cctp_message: &'ix Pubkey, // 5
50+
pub post_message_shim_program: &'ix Pubkey, // 4
51+
/// Cctp message CHECK: Seeds must be \["cctp-msg", auction.key().as_ref()\].
52+
pub cctp_message: &'ix Pubkey, // 5
5253
/// Custodian account
53-
pub custodian: &'ix Pubkey, // 6
54+
pub custodian: &'ix Pubkey, // 6
5455
/// Fee recipient token
55-
pub fee_recipient_token: &'ix Pubkey, // 7
56+
pub fee_recipient_token: &'ix Pubkey, // 7
5657
/// Closed prepared order response actor (closed_by)
57-
pub closed_prepared_order_response_actor: &'ix Pubkey, // 8
58+
pub closed_prepared_order_response_actor: &'ix Pubkey, // 8
5859
/// Closed prepared order response
59-
pub closed_prepared_order_response: &'ix Pubkey, // 9
60+
pub closed_prepared_order_response: &'ix Pubkey, // 9
6061
/// Closed prepared order response custody token
6162
pub closed_prepared_order_response_custody_token: &'ix Pubkey, // 10
62-
/// Auction account
63-
pub auction: &'ix Pubkey, // 11
63+
/// Auction account CHECK: Init if needed, Seeds must be \["auction", prepared.order_response.seeds.fast_vaa_hash.as_ref()\].
64+
pub auction: &'ix Pubkey, // 11
6465
/// Cctp mint (must be USDC mint)
65-
pub cctp_mint: &'ix Pubkey, // 12
66+
pub cctp_mint: &'ix Pubkey, // 12
6667
/// Cctp token messenger minter sender authority
6768
pub cctp_token_messenger_minter_sender_authority: &'ix Pubkey, // 13
6869
/// Cctp message transmitter config
69-
pub cctp_message_transmitter_config: &'ix Pubkey, // 14
70+
pub cctp_message_transmitter_config: &'ix Pubkey, // 14
7071
/// Cctp token messenger
71-
pub cctp_token_messenger: &'ix Pubkey, // 15
72+
pub cctp_token_messenger: &'ix Pubkey, // 15
7273
/// Cctp remote token messenger
73-
pub cctp_remote_token_messenger: &'ix Pubkey, // 16
74+
pub cctp_remote_token_messenger: &'ix Pubkey, // 16
7475
/// Cctp token minter
75-
pub cctp_token_minter: &'ix Pubkey, // 17
76+
pub cctp_token_minter: &'ix Pubkey, // 17
7677
/// Cctp local token
77-
pub cctp_local_token: &'ix Pubkey, // 18
78+
pub cctp_local_token: &'ix Pubkey, // 18
7879
/// Cctp token messenger minter event authority
79-
pub cctp_token_messenger_minter_event_authority: &'ix Pubkey, // 19
80+
pub cctp_token_messenger_minter_event_authority: &'ix Pubkey, // 19
8081
/// Cctp token messenger minter program
81-
pub cctp_token_messenger_minter_program: &'ix Pubkey, // 20
82+
pub cctp_token_messenger_minter_program: &'ix Pubkey, // 20
8283
/// Cctp message transmitter program
83-
pub cctp_message_transmitter_program: &'ix Pubkey, // 21
84+
pub cctp_message_transmitter_program: &'ix Pubkey, // 21
8485
/// Core bridge program
85-
pub core_bridge_program: &'ix Pubkey, // 22
86+
pub core_bridge_program: &'ix Pubkey, // 22
8687
/// Core bridge fee collector
87-
pub core_bridge_fee_collector: &'ix Pubkey, // 23
88+
pub core_bridge_fee_collector: &'ix Pubkey, // 23
8889
/// Core bridge config
89-
pub core_bridge_config: &'ix Pubkey, // 24
90+
pub core_bridge_config: &'ix Pubkey, // 24
9091
/// Token program
91-
pub token_program: &'ix Pubkey, // 25
92+
pub token_program: &'ix Pubkey, // 25
9293
/// System program
93-
pub system_program: &'ix Pubkey, // 26
94+
pub system_program: &'ix Pubkey, // 26
9495
/// Clock
95-
pub clock: &'ix Pubkey, // 27
96+
pub clock: &'ix Pubkey, // 27
9697
/// Rent
97-
pub rent: &'ix Pubkey, // 28
98+
pub rent: &'ix Pubkey, // 28
9899
}
99100

100101
impl<'ix> SettleAuctionNoneCctpShimAccounts<'ix> {
101102
pub fn to_account_metas(&self) -> Vec<AccountMeta> {
102103
vec![
103-
AccountMeta::new_readonly(*self.payer, true), // 0
104+
AccountMeta::new_readonly(*self.payer, true), // 0
104105
AccountMeta::new(*self.post_shim_message, false), // 1
105106
AccountMeta::new(*self.core_bridge_emitter_sequence, false), // 2
106107
AccountMeta::new_readonly(*self.post_message_shim_event_authority, false), // 3
107108
AccountMeta::new_readonly(*self.post_message_shim_program, false), // 4
108-
AccountMeta::new(*self.cctp_message, false), // 5
109-
AccountMeta::new(*self.custodian, false), // 6
110-
AccountMeta::new(*self.fee_recipient_token, false), // 7
109+
AccountMeta::new(*self.cctp_message, false), // 5
110+
AccountMeta::new(*self.custodian, false), // 6
111+
AccountMeta::new(*self.fee_recipient_token, false), // 7
111112
AccountMeta::new(*self.closed_prepared_order_response_actor, false), // 8
112113
AccountMeta::new_readonly(*self.closed_prepared_order_response, false), // 9
113114
AccountMeta::new(*self.closed_prepared_order_response_custody_token, false), // 10
114-
AccountMeta::new(*self.auction, false), // 11
115-
AccountMeta::new(*self.cctp_mint, false), // 12
115+
AccountMeta::new(*self.auction, false), // 11
116+
AccountMeta::new(*self.cctp_mint, false), // 12
116117
AccountMeta::new_readonly(*self.cctp_token_messenger_minter_sender_authority, false), // 13
117118
AccountMeta::new(*self.cctp_message_transmitter_config, false), // 14
118119
AccountMeta::new_readonly(*self.cctp_token_messenger, false), // 15
@@ -186,20 +187,83 @@ pub fn settle_auction_none_cctp_shim(
186187
_ => return Err(MatchingEngineError::InvalidCctpEndpoint.into()),
187188
};
188189

189-
// TODO: Make more checks
190-
// Do checks
190+
// Start of checks
191191
// ------------------------------------------------------------------------------------------------
192+
193+
// Check cctp message is writable
192194
if !cctp_message.is_writable {
193195
msg!("Cctp message is not writable");
194196
return Err(MatchingEngineError::AccountNotWritable.into())
195197
.map_err(|e: Error| e.with_account_name("cctp_message"));
196198
}
197-
// End of checks
198-
// ------------------------------------------------------------------------------------------------
199+
let auction_key = auction.key();
199200

200-
// Begin of initialisation of auction account
201-
// ------------------------------------------------------------------------------------------------
202-
let auction_space = 8 + Auction::INIT_SPACE_NO_AUCTION;
201+
// Check cctp message seeds are valid
202+
let cctp_message_seeds = [
203+
common::CCTP_MESSAGE_SEED_PREFIX,
204+
auction_key.as_ref(),
205+
&[data.cctp_message_bump],
206+
];
207+
208+
let cctp_message_pda = Pubkey::create_program_address(&cctp_message_seeds, &ID)
209+
.map_err(|_| MatchingEngineError::InvalidPda)?;
210+
if cctp_message_pda != cctp_message.key() {
211+
msg!("Cctp message seeds are invalid");
212+
return Err(ErrorCode::ConstraintSeeds.into())
213+
.map_err(|e: Error| e.with_pubkeys((cctp_message_pda, cctp_message.key())));
214+
};
215+
// Check custodian owner is the matching engine program and that it deserializes into a checked custodian
216+
require_eq!(custodian.owner, &ID);
217+
let _checked_custodian = Custodian::try_deserialize(&mut &custodian.data.borrow_mut()[..])?;
218+
// Check that fee recipient token is a token account
219+
let _checked_fee_recipient_token = Box::new(TokenAccount::try_deserialize(
220+
&mut &fee_recipient_token.data.borrow_mut()[..],
221+
)?);
222+
// Check seeds of prepared order response are valid
223+
let prepared_order_response_pda = Pubkey::create_program_address(
224+
&[
225+
PreparedOrderResponse::SEED_PREFIX,
226+
prepared_order_response_account.seeds.fast_vaa_hash.as_ref(),
227+
&[prepared_order_response_account.seeds.bump],
228+
],
229+
program_id,
230+
)
231+
.map_err(|_| MatchingEngineError::InvalidPda)?;
232+
if prepared_order_response_pda != closed_prepared_order_response.key() {
233+
msg!("Prepared order response seeds are invalid");
234+
return Err(ErrorCode::ConstraintSeeds.into()).map_err(|e: Error| {
235+
e.with_pubkeys((
236+
prepared_order_response_pda,
237+
closed_prepared_order_response.key(),
238+
))
239+
});
240+
};
241+
// Check seeds of prepared custody token are valid
242+
{
243+
let (prepared_custody_token_pda, _) = Pubkey::find_program_address(
244+
&[
245+
crate::PREPARED_CUSTODY_TOKEN_SEED_PREFIX,
246+
closed_prepared_order_response.key().as_ref(),
247+
],
248+
program_id,
249+
);
250+
if prepared_custody_token_pda != closed_prepared_order_response_custody_token.key() {
251+
msg!("Prepared custody token seeds are invalid");
252+
return Err(ErrorCode::ConstraintSeeds.into()).map_err(|e: Error| {
253+
e.with_pubkeys((
254+
prepared_custody_token_pda,
255+
closed_prepared_order_response_custody_token.key(),
256+
))
257+
});
258+
};
259+
}
260+
// Check that custody token is a token account
261+
let _checked_prepared_custody_token = Box::new(TokenAccount::try_deserialize(
262+
&mut &closed_prepared_order_response_custody_token
263+
.data
264+
.borrow_mut()[..],
265+
)?);
266+
// Check seeds of auction are valid
203267
let auction_seeds = [
204268
Auction::SEED_PREFIX,
205269
prepared_order_response_account.seeds.fast_vaa_hash.as_ref(),
@@ -210,6 +274,14 @@ pub fn settle_auction_none_cctp_shim(
210274
if auction_pda != auction.key() {
211275
return Err(MatchingEngineError::InvalidPda.into());
212276
}
277+
278+
// End of checks
279+
// ------------------------------------------------------------------------------------------------
280+
281+
// Begin of initialisation of auction account
282+
// ------------------------------------------------------------------------------------------------
283+
let auction_space = 8 + Auction::INIT_SPACE_NO_AUCTION;
284+
213285
let auction_signer_seeds = &[&auction_seeds[..]];
214286
create_account_reliably(
215287
&payer.key(),
@@ -251,6 +323,11 @@ pub fn settle_auction_none_cctp_shim(
251323
.try_to_vec()
252324
.map_err(|_| MatchingEngineError::BorshDeserializationError)?;
253325
auction_data[8..8_usize.saturating_add(auction_bytes.len())].copy_from_slice(&auction_bytes);
326+
// ------------------------------------------------------------------------------------------------
327+
// End of initialisation of auction account
328+
329+
// Begin of burning and posting the message
330+
// ------------------------------------------------------------------------------------------------
254331
let post_message_accounts = PostMessageAccounts {
255332
emitter: custodian.key(),
256333
payer: payer.key(),
@@ -303,7 +380,11 @@ pub fn settle_auction_none_cctp_shim(
303380
post_message_accounts,
304381
accounts,
305382
)?;
306-
// TODO: Emit event?
383+
// ------------------------------------------------------------------------------------------------
384+
// End of burning and posting the message
385+
386+
// Begin of closing the prepared order response
387+
// ------------------------------------------------------------------------------------------------
307388
let close_token_account_ix = spl_token::instruction::close_account(
308389
&spl_token::ID,
309390
&closed_prepared_order_response_custody_token.key(),
@@ -316,6 +397,9 @@ pub fn settle_auction_none_cctp_shim(
316397
accounts,
317398
&[&Custodian::SIGNER_SEEDS],
318399
)?;
400+
// ------------------------------------------------------------------------------------------------
401+
// End of closing the prepared order response
402+
319403
Ok(())
320404
}
321405

0 commit comments

Comments
 (0)