@@ -2667,6 +2667,258 @@ describe("Matching Engine", function () {
2667
2667
const localVariables = new Map < string , any > ( ) ;
2668
2668
2669
2669
// TODO: add negative tests
2670
+ it ( "Cannot Prepare Order Response with Emitter Chain Mismatch" , async function ( ) {
2671
+ const redeemer = Keypair . generate ( ) ;
2672
+
2673
+ const sourceCctpDomain = 0 ;
2674
+ const cctpNonce = testCctpNonce ++ ;
2675
+ const amountIn = 690000n ; // 69 cents
2676
+
2677
+ // Concoct a Circle message.
2678
+ const burnSource = Array . from ( Buffer . alloc ( 32 , "beefdead" , "hex" ) ) ;
2679
+ const { destinationCctpDomain, burnMessage, encodedCctpMessage, cctpAttestation } =
2680
+ await craftCctpTokenBurnMessage ( engine , sourceCctpDomain , cctpNonce , amountIn ) ;
2681
+
2682
+ const fastMessage = new LiquidityLayerMessage ( {
2683
+ fastMarketOrder : {
2684
+ amountIn,
2685
+ minAmountOut : 0n ,
2686
+ targetChain : wormholeSdk . CHAIN_ID_SOLANA as number ,
2687
+ redeemer : Array . from ( redeemer . publicKey . toBuffer ( ) ) ,
2688
+ sender : new Array ( 32 ) . fill ( 0 ) ,
2689
+ refundAddress : new Array ( 32 ) . fill ( 0 ) ,
2690
+ maxFee : 42069n ,
2691
+ initAuctionFee : 2000n ,
2692
+ deadline : 2 ,
2693
+ redeemerMessage : Buffer . from ( "Somebody set up us the bomb" ) ,
2694
+ } ,
2695
+ } ) ;
2696
+
2697
+ const finalizedMessage = new LiquidityLayerMessage ( {
2698
+ deposit : new LiquidityLayerDeposit (
2699
+ {
2700
+ tokenAddress : burnMessage . burnTokenAddress ,
2701
+ amount : amountIn ,
2702
+ sourceCctpDomain,
2703
+ destinationCctpDomain,
2704
+ cctpNonce,
2705
+ burnSource,
2706
+ mintRecipient : Array . from ( engine . cctpMintRecipientAddress ( ) . toBuffer ( ) ) ,
2707
+ } ,
2708
+ {
2709
+ slowOrderResponse : {
2710
+ baseFee : 420n ,
2711
+ } ,
2712
+ } ,
2713
+ ) ,
2714
+ } ) ;
2715
+
2716
+ const finalizedVaa = await postLiquidityLayerVaa (
2717
+ connection ,
2718
+ payer ,
2719
+ MOCK_GUARDIANS ,
2720
+ ethRouter ,
2721
+ wormholeSequence ++ ,
2722
+ finalizedMessage ,
2723
+ ) ;
2724
+ const fastVaa = await postLiquidityLayerVaa (
2725
+ connection ,
2726
+ payer ,
2727
+ MOCK_GUARDIANS ,
2728
+ ethRouter ,
2729
+ wormholeSequence ++ ,
2730
+ fastMessage ,
2731
+ "arbitrum" ,
2732
+ ) ;
2733
+
2734
+ const ix = await engine . prepareOrderResponseCctpIx (
2735
+ {
2736
+ payer : payer . publicKey ,
2737
+ fastVaa,
2738
+ finalizedVaa,
2739
+ mint : USDC_MINT_ADDRESS ,
2740
+ } ,
2741
+ {
2742
+ encodedCctpMessage,
2743
+ cctpAttestation,
2744
+ } ,
2745
+ ) ;
2746
+
2747
+ const computeIx = ComputeBudgetProgram . setComputeUnitLimit ( {
2748
+ units : 300_000 ,
2749
+ } ) ;
2750
+
2751
+ await expectIxErr ( connection , [ computeIx , ix ] , [ payer ] , "Error Code: VaaMismatch" ) ;
2752
+ } ) ;
2753
+
2754
+ it ( "Cannot Prepare Order Response with Emitter Address Mismatch" , async function ( ) {
2755
+ const redeemer = Keypair . generate ( ) ;
2756
+
2757
+ const sourceCctpDomain = 0 ;
2758
+ const cctpNonce = testCctpNonce ++ ;
2759
+ const amountIn = 690000n ; // 69 cents
2760
+
2761
+ // Concoct a Circle message.
2762
+ const burnSource = Array . from ( Buffer . alloc ( 32 , "beefdead" , "hex" ) ) ;
2763
+ const { destinationCctpDomain, burnMessage, encodedCctpMessage, cctpAttestation } =
2764
+ await craftCctpTokenBurnMessage ( engine , sourceCctpDomain , cctpNonce , amountIn ) ;
2765
+
2766
+ const fastMessage = new LiquidityLayerMessage ( {
2767
+ fastMarketOrder : {
2768
+ amountIn,
2769
+ minAmountOut : 0n ,
2770
+ targetChain : wormholeSdk . CHAIN_ID_SOLANA as number ,
2771
+ redeemer : Array . from ( redeemer . publicKey . toBuffer ( ) ) ,
2772
+ sender : new Array ( 32 ) . fill ( 0 ) ,
2773
+ refundAddress : new Array ( 32 ) . fill ( 0 ) ,
2774
+ maxFee : 42069n ,
2775
+ initAuctionFee : 2000n ,
2776
+ deadline : 2 ,
2777
+ redeemerMessage : Buffer . from ( "Somebody set up us the bomb" ) ,
2778
+ } ,
2779
+ } ) ;
2780
+
2781
+ const finalizedMessage = new LiquidityLayerMessage ( {
2782
+ deposit : new LiquidityLayerDeposit (
2783
+ {
2784
+ tokenAddress : burnMessage . burnTokenAddress ,
2785
+ amount : amountIn ,
2786
+ sourceCctpDomain,
2787
+ destinationCctpDomain,
2788
+ cctpNonce,
2789
+ burnSource,
2790
+ mintRecipient : Array . from ( engine . cctpMintRecipientAddress ( ) . toBuffer ( ) ) ,
2791
+ } ,
2792
+ {
2793
+ slowOrderResponse : {
2794
+ baseFee : 420n ,
2795
+ } ,
2796
+ } ,
2797
+ ) ,
2798
+ } ) ;
2799
+
2800
+ const finalizedVaa = await postLiquidityLayerVaa (
2801
+ connection ,
2802
+ payer ,
2803
+ MOCK_GUARDIANS ,
2804
+ ethRouter ,
2805
+ wormholeSequence ++ ,
2806
+ finalizedMessage ,
2807
+ ) ;
2808
+ const fastVaa = await postLiquidityLayerVaa (
2809
+ connection ,
2810
+ payer ,
2811
+ MOCK_GUARDIANS ,
2812
+ arbRouter ,
2813
+ wormholeSequence ++ ,
2814
+ fastMessage ,
2815
+ ) ;
2816
+
2817
+ const ix = await engine . prepareOrderResponseCctpIx (
2818
+ {
2819
+ payer : payer . publicKey ,
2820
+ fastVaa,
2821
+ finalizedVaa,
2822
+ mint : USDC_MINT_ADDRESS ,
2823
+ } ,
2824
+ {
2825
+ encodedCctpMessage,
2826
+ cctpAttestation,
2827
+ } ,
2828
+ ) ;
2829
+
2830
+ const computeIx = ComputeBudgetProgram . setComputeUnitLimit ( {
2831
+ units : 300_000 ,
2832
+ } ) ;
2833
+
2834
+ await expectIxErr ( connection , [ computeIx , ix ] , [ payer ] , "Error Code: VaaMismatch" ) ;
2835
+ } ) ;
2836
+
2837
+ it ( "Cannot Prepare Order Response with Emitter Sequence Mismatch" , async function ( ) {
2838
+ const redeemer = Keypair . generate ( ) ;
2839
+
2840
+ const sourceCctpDomain = 0 ;
2841
+ const cctpNonce = testCctpNonce ++ ;
2842
+ const amountIn = 690000n ; // 69 cents
2843
+
2844
+ // Concoct a Circle message.
2845
+ const burnSource = Array . from ( Buffer . alloc ( 32 , "beefdead" , "hex" ) ) ;
2846
+ const { destinationCctpDomain, burnMessage, encodedCctpMessage, cctpAttestation } =
2847
+ await craftCctpTokenBurnMessage ( engine , sourceCctpDomain , cctpNonce , amountIn ) ;
2848
+
2849
+ const fastMessage = new LiquidityLayerMessage ( {
2850
+ fastMarketOrder : {
2851
+ amountIn,
2852
+ minAmountOut : 0n ,
2853
+ targetChain : wormholeSdk . CHAIN_ID_SOLANA as number ,
2854
+ redeemer : Array . from ( redeemer . publicKey . toBuffer ( ) ) ,
2855
+ sender : new Array ( 32 ) . fill ( 0 ) ,
2856
+ refundAddress : new Array ( 32 ) . fill ( 0 ) ,
2857
+ maxFee : 42069n ,
2858
+ initAuctionFee : 2000n ,
2859
+ deadline : 2 ,
2860
+ redeemerMessage : Buffer . from ( "Somebody set up us the bomb" ) ,
2861
+ } ,
2862
+ } ) ;
2863
+
2864
+ const finalizedMessage = new LiquidityLayerMessage ( {
2865
+ deposit : new LiquidityLayerDeposit (
2866
+ {
2867
+ tokenAddress : burnMessage . burnTokenAddress ,
2868
+ amount : amountIn ,
2869
+ sourceCctpDomain,
2870
+ destinationCctpDomain,
2871
+ cctpNonce,
2872
+ burnSource,
2873
+ mintRecipient : Array . from ( engine . cctpMintRecipientAddress ( ) . toBuffer ( ) ) ,
2874
+ } ,
2875
+ {
2876
+ slowOrderResponse : {
2877
+ baseFee : 420n ,
2878
+ } ,
2879
+ } ,
2880
+ ) ,
2881
+ } ) ;
2882
+
2883
+ const finalizedVaa = await postLiquidityLayerVaa (
2884
+ connection ,
2885
+ payer ,
2886
+ MOCK_GUARDIANS ,
2887
+ ethRouter ,
2888
+ wormholeSequence ++ ,
2889
+ finalizedMessage ,
2890
+ ) ;
2891
+ const fastVaa = await postLiquidityLayerVaa (
2892
+ connection ,
2893
+ payer ,
2894
+ MOCK_GUARDIANS ,
2895
+ ethRouter ,
2896
+ wormholeSequence + 2n ,
2897
+ fastMessage ,
2898
+ ) ;
2899
+
2900
+ const ix = await engine . prepareOrderResponseCctpIx (
2901
+ {
2902
+ payer : payer . publicKey ,
2903
+ fastVaa,
2904
+ finalizedVaa,
2905
+ mint : USDC_MINT_ADDRESS ,
2906
+ } ,
2907
+ {
2908
+ encodedCctpMessage,
2909
+ cctpAttestation,
2910
+ } ,
2911
+ ) ;
2912
+
2913
+ const computeIx = ComputeBudgetProgram . setComputeUnitLimit ( {
2914
+ units : 300_000 ,
2915
+ } ) ;
2916
+
2917
+ await expectIxErr ( connection , [ computeIx , ix ] , [ payer ] , "Error Code: VaaMismatch" ) ;
2918
+ } ) ;
2919
+
2920
+ // TODO: Test timestamp mismatch
2921
+ it . skip ( "Cannot Prepare Order Response with VAA Timestamp Mismatch" , async function ( ) { } ) ;
2670
2922
2671
2923
it ( "Prepare Order Response" , async function ( ) {
2672
2924
const redeemer = Keypair . generate ( ) ;
0 commit comments