@@ -583,8 +583,9 @@ impl Service {
583583
584584 // User has to wrap Sol
585585 if transaction_data. accounts . mint_user == spl_token:: native_mint:: id ( ) {
586- // Sometimes the user doesn't have enough SOL, but we want the transaction to fail in the Express Relay program with InsufficientUserFunds
587- // Therefore we allow the user to wrap less SOL than needed so it doesn't fail in the transfer instruction
586+ // Sometimes the user doesn't have enough SOL, but we want the transaction to fail in the Express Relay program with InsufficientUserFunds.
587+ // Sometimes the user will already have a WSOL account, and they don't need to wrap the full user_amount of SOL.
588+ // For both these reasons, we allow the user to wrap less SOL than needed so it doesn't fail in the transfer instruction.
588589 let amount_user_to_wrap =
589590 opportunity_swap_data. get_user_amount_to_wrap ( transaction_data. data . amount_user ) ;
590591
@@ -2752,6 +2753,85 @@ mod tests {
27522753 }
27532754 }
27542755
2756+ #[ tokio:: test]
2757+ async fn test_verify_bid_when_create_ata_relayer_payer ( ) {
2758+ let ( service, opportunities) = get_service ( true ) ;
2759+ let opportunity = opportunities. user_token_specified . clone ( ) ;
2760+ let bid_amount = 1 ;
2761+ let searcher = Keypair :: new ( ) ;
2762+ let swap_instruction = svm:: Svm :: get_swap_instruction ( GetSwapInstructionParams {
2763+ searcher : searcher. pubkey ( ) ,
2764+ opportunity_params : get_opportunity_params ( opportunity. clone ( ) ) ,
2765+ bid_amount,
2766+ deadline : ( OffsetDateTime :: now_utc ( ) + Duration :: seconds ( 30 ) ) . unix_timestamp ( ) ,
2767+ fee_receiver_relayer : Pubkey :: new_unique ( ) ,
2768+ relayer_signer : service. config . chain_config . express_relay . relayer . pubkey ( ) ,
2769+ } )
2770+ . unwrap ( ) ;
2771+ let relayer = service. config . chain_config . express_relay . relayer . pubkey ( ) ;
2772+ let program = match opportunity. program . clone ( ) {
2773+ OpportunitySvmProgram :: Swap ( program) => program,
2774+ _ => panic ! ( "Expected swap program" ) ,
2775+ } ;
2776+ let create_ata_instruction =
2777+ spl_associated_token_account:: instruction:: create_associated_token_account (
2778+ & relayer,
2779+ & relayer,
2780+ & opportunity. buy_tokens [ 0 ] . token ,
2781+ & program. token_program_user ,
2782+ ) ;
2783+ let result = get_verify_bid_result (
2784+ service. clone ( ) ,
2785+ searcher. insecure_clone ( ) ,
2786+ vec ! [ create_ata_instruction, swap_instruction. clone( ) ] ,
2787+ opportunities. user_token_specified . clone ( ) ,
2788+ )
2789+ . await ;
2790+ assert_eq ! (
2791+ result. unwrap_err( ) ,
2792+ RestError :: InvalidInstruction (
2793+ Some ( 0 ) ,
2794+ InstructionError :: InvalidPayerInCreateAtaInstruction {
2795+ expected: searcher. pubkey( ) ,
2796+ found: relayer,
2797+ }
2798+ )
2799+ ) ;
2800+ }
2801+
2802+ #[ tokio:: test]
2803+ async fn test_verify_bid_when_sol_transfer_relayer ( ) {
2804+ let ( service, opportunities) = get_service ( true ) ;
2805+ let opportunity = opportunities. user_token_specified . clone ( ) ;
2806+ let bid_amount = 1 ;
2807+ let searcher = Keypair :: new ( ) ;
2808+ let swap_instruction = svm:: Svm :: get_swap_instruction ( GetSwapInstructionParams {
2809+ searcher : searcher. pubkey ( ) ,
2810+ opportunity_params : get_opportunity_params ( opportunity. clone ( ) ) ,
2811+ bid_amount,
2812+ deadline : ( OffsetDateTime :: now_utc ( ) + Duration :: seconds ( 30 ) ) . unix_timestamp ( ) ,
2813+ fee_receiver_relayer : Pubkey :: new_unique ( ) ,
2814+ relayer_signer : service. config . chain_config . express_relay . relayer . pubkey ( ) ,
2815+ } )
2816+ . unwrap ( ) ;
2817+ let relayer = service. config . chain_config . express_relay . relayer . pubkey ( ) ;
2818+ let transfer_instruction = system_instruction:: transfer ( & relayer, & Pubkey :: new_unique ( ) , 1 ) ;
2819+ let result = get_verify_bid_result (
2820+ service. clone ( ) ,
2821+ searcher. insecure_clone ( ) ,
2822+ vec ! [ transfer_instruction, swap_instruction. clone( ) ] ,
2823+ opportunities. user_token_specified . clone ( ) ,
2824+ )
2825+ . await ;
2826+ assert_eq ! (
2827+ result. unwrap_err( ) ,
2828+ RestError :: InvalidInstruction (
2829+ Some ( 0 ) ,
2830+ InstructionError :: RelayerTransferInstructionNotAllowed
2831+ )
2832+ ) ;
2833+ }
2834+
27552835 #[ tokio:: test]
27562836 async fn test_verify_bid_when_arbitrary_program_does_not_invoke_user ( ) {
27572837 let ( service, opportunities) = get_service ( true ) ;
@@ -5034,6 +5114,7 @@ mod tests {
50345114 let bid_amount = 1 ;
50355115 let searcher = Keypair :: new ( ) ;
50365116 let memo_instruction = svm:: Svm :: get_memo_instruction ( "memo" . to_string ( ) ) ;
5117+ let memo_instruction_extra = svm:: Svm :: get_memo_instruction ( "extra memo" . to_string ( ) ) ;
50375118 let instruction = svm:: Svm :: get_swap_instruction ( GetSwapInstructionParams {
50385119 searcher : searcher. pubkey ( ) ,
50395120 opportunity_params : get_opportunity_params ( opportunity. clone ( ) ) ,
@@ -5046,7 +5127,7 @@ mod tests {
50465127 get_verify_bid_result (
50475128 service,
50485129 searcher. insecure_clone ( ) ,
5049- vec ! [ memo_instruction, instruction] ,
5130+ vec ! [ memo_instruction, memo_instruction_extra , instruction] ,
50505131 opportunity. clone ( ) ,
50515132 )
50525133 . await
0 commit comments