diff --git a/typescript/agentkit/src/action-providers/flaunch/swap_utils.test.ts b/typescript/agentkit/src/action-providers/flaunch/swap_utils.test.ts new file mode 100644 index 000000000..c7aa9bee5 --- /dev/null +++ b/typescript/agentkit/src/action-providers/flaunch/swap_utils.test.ts @@ -0,0 +1,35 @@ +import { getAmountWithSlippage, ethToMemecoin } from "./swap_utils"; +import { zeroAddress } from "viem"; + +describe("getAmountWithSlippage", () => { + it("throws when quote amount is missing", () => { + expect(() => getAmountWithSlippage(undefined, "0.01", "EXACT_IN")).toThrow( + /missing or zero/, + ); + }); + + it("throws when quote amount is zero", () => { + expect(() => getAmountWithSlippage(0n, "0.01", "EXACT_IN")).toThrow(/missing or zero/); + }); + + it("applies slippage for a positive quote", () => { + const out = getAmountWithSlippage(100n, "0", "EXACT_IN"); + expect(out).toBe(100n); + }); +}); + +describe("ethToMemecoin", () => { + it("rejects zero amountOutMin for EXACT_IN", () => { + expect(() => + ethToMemecoin({ + sender: zeroAddress, + memecoin: "0x1234567890123456789012345678901234567890", + chainId: 8453, + referrer: null, + swapType: "EXACT_IN", + amountIn: 1n, + amountOutMin: 0n, + }), + ).toThrow(/non-zero amountOutMin/); + }); +}); diff --git a/typescript/agentkit/src/action-providers/flaunch/swap_utils.ts b/typescript/agentkit/src/action-providers/flaunch/swap_utils.ts index 32376f13a..2cdf87de0 100644 --- a/typescript/agentkit/src/action-providers/flaunch/swap_utils.ts +++ b/typescript/agentkit/src/action-providers/flaunch/swap_utils.ts @@ -34,8 +34,9 @@ export const getAmountWithSlippage = ( slippage: string, swapType: "EXACT_IN" | "EXACT_OUT", ) => { - if (amount == null) { - return 0n; + // Missing/zero quotes used to become amountOutMinimum=0 (fail-open sandwich). + if (amount == null || amount === 0n) { + throw new Error("Quote amount is missing or zero"); } const absAmount = amount < 0n ? -amount : amount; @@ -76,8 +77,10 @@ export const ethToMemecoin = (params: { // Configure path and parameters based on swapType if (params.swapType === "EXACT_IN") { - if (params.amountIn == null || params.amountOutMin == null) { - throw new Error("amountIn and amountOutMin are required for EXACT_IN swap"); + if (params.amountIn == null || params.amountOutMin == null || params.amountOutMin === 0n) { + throw new Error( + "amountIn and a non-zero amountOutMin are required for EXACT_IN swap", + ); } // Path for 'EXACT_IN' swap @@ -111,8 +114,10 @@ export const ethToMemecoin = (params: { }, ]); } else { - if (params.amountOut == null || params.amountInMax == null) { - throw new Error("amountOut and amountInMax are required for EXACT_OUT swap"); + if (params.amountOut == null || params.amountInMax == null || params.amountInMax === 0n) { + throw new Error( + "amountOut and a non-zero amountInMax are required for EXACT_OUT swap", + ); } // Path for 'EXACT_OUT' swap @@ -232,6 +237,10 @@ export const memecoinToEthWithPermit2 = (params: { signature: Hex | undefined; referrer: Address | null; }) => { + if (params.ethOutMin === 0n) { + throw new Error("ethOutMin must be non-zero"); + } + const flETH = FLETHAddress[params.chainId]; const flETHHooks = FLETHHooksAddress[params.chainId];