@@ -583,8 +583,9 @@ impl Service {
583
583
584
584
// User has to wrap Sol
585
585
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.
588
589
let amount_user_to_wrap =
589
590
opportunity_swap_data. get_user_amount_to_wrap ( transaction_data. data . amount_user ) ;
590
591
@@ -2752,6 +2753,85 @@ mod tests {
2752
2753
}
2753
2754
}
2754
2755
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
+
2755
2835
#[ tokio:: test]
2756
2836
async fn test_verify_bid_when_arbitrary_program_does_not_invoke_user ( ) {
2757
2837
let ( service, opportunities) = get_service ( true ) ;
@@ -5034,6 +5114,7 @@ mod tests {
5034
5114
let bid_amount = 1 ;
5035
5115
let searcher = Keypair :: new ( ) ;
5036
5116
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 ( ) ) ;
5037
5118
let instruction = svm:: Svm :: get_swap_instruction ( GetSwapInstructionParams {
5038
5119
searcher : searcher. pubkey ( ) ,
5039
5120
opportunity_params : get_opportunity_params ( opportunity. clone ( ) ) ,
@@ -5046,7 +5127,7 @@ mod tests {
5046
5127
get_verify_bid_result (
5047
5128
service,
5048
5129
searcher. insecure_clone ( ) ,
5049
- vec ! [ memo_instruction, instruction] ,
5130
+ vec ! [ memo_instruction, memo_instruction_extra , instruction] ,
5050
5131
opportunity. clone ( ) ,
5051
5132
)
5052
5133
. await
0 commit comments