Skip to content

Commit 79ce9bc

Browse files
committed
Add negative tests for order response preparation in MatchingEngine
1 parent aed7a43 commit 79ce9bc

File tree

1 file changed

+252
-0
lines changed

1 file changed

+252
-0
lines changed

solana/ts/tests/01__matchingEngine.ts

+252
Original file line numberDiff line numberDiff line change
@@ -2667,6 +2667,258 @@ describe("Matching Engine", function () {
26672667
const localVariables = new Map<string, any>();
26682668

26692669
// 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 () {});
26702922

26712923
it("Prepare Order Response", async function () {
26722924
const redeemer = Keypair.generate();

0 commit comments

Comments
 (0)