From b5859729b3878666eb37d020d6e97563a291026c Mon Sep 17 00:00:00 2001 From: Dong-Ha Kim Date: Thu, 21 Nov 2024 19:16:18 +0700 Subject: [PATCH] feat: support native eth as input/output (#1279) * feat: build cross swap tx * fixup * fixup * refactor * fix * fixup * fixup * feat: add leftover handling type * fixup * fixup * feat: support native eth as input/output * review requests * refactor leftover type into exact_output and min_output for clarity * add temp swap and bridge typechain binding and use for testing * fixup --- api/_dexes/cross-swap.ts | 79 +- api/_dexes/types.ts | 5 +- api/_dexes/uniswap.ts | 103 ++- api/_dexes/utils.ts | 104 ++- api/_multicall-handler.ts | 31 + .../SwapAndBridge.sol/SwapAndBridge.ts | 345 ++++++++ .../SwapAndBridge.sol/SwapAndBridgeBase.ts | 211 +++++ .../UniversalSwapAndBridge.ts | 671 +++++++++++++++ api/_typechain/SwapAndBridge.sol/index.ts | 6 + .../SwapAndBridgeBase__factory.ts | 153 ++++ .../SwapAndBridge__factory.ts | 367 +++++++++ .../UniversalSwapAndBridge__factory.ts | 777 ++++++++++++++++++ .../factories/SwapAndBridge.sol/index.ts | 6 + api/_utils.ts | 8 + api/swap.ts | 52 +- scripts/generate-routes.ts | 8 +- scripts/tests/swap.ts | 178 +++- ...6fA914353c44b2E33eBE05f21846F1048bEda.json | 8 +- 18 files changed, 2995 insertions(+), 117 deletions(-) create mode 100644 api/_typechain/SwapAndBridge.sol/SwapAndBridge.ts create mode 100644 api/_typechain/SwapAndBridge.sol/SwapAndBridgeBase.ts create mode 100644 api/_typechain/SwapAndBridge.sol/UniversalSwapAndBridge.ts create mode 100644 api/_typechain/SwapAndBridge.sol/index.ts create mode 100644 api/_typechain/factories/SwapAndBridge.sol/SwapAndBridgeBase__factory.ts create mode 100644 api/_typechain/factories/SwapAndBridge.sol/SwapAndBridge__factory.ts create mode 100644 api/_typechain/factories/SwapAndBridge.sol/UniversalSwapAndBridge__factory.ts create mode 100644 api/_typechain/factories/SwapAndBridge.sol/index.ts diff --git a/api/_dexes/cross-swap.ts b/api/_dexes/cross-swap.ts index 8599baa3d..800c0a70d 100644 --- a/api/_dexes/cross-swap.ts +++ b/api/_dexes/cross-swap.ts @@ -1,4 +1,5 @@ import { SpokePool } from "@across-protocol/contracts/dist/typechain"; +import { PopulatedTransaction } from "ethers"; import { isRouteEnabled, @@ -9,14 +10,17 @@ import { latestGasPriceCache, } from "../_utils"; import { - getUniswapCrossSwapQuotesForMinOutputB2A, - getUniswapCrossSwapQuotesForMinOutputA2B, - getBestUniswapCrossSwapQuotesForMinOutputA2A, + getUniswapCrossSwapQuotesForOutputB2A, + getUniswapCrossSwapQuotesForOutputA2B, + getBestUniswapCrossSwapQuotesForOutputA2A, } from "./uniswap"; import { CrossSwap, CrossSwapQuotes } from "./types"; -import { getSwapAndBridge } from "./utils"; +import { + buildExactOutputBridgeTokenMessage, + buildMinOutputBridgeTokenMessage, + getSwapAndBridge, +} from "./utils"; import { tagIntegratorId } from "../_integrator-id"; -import { PopulatedTransaction } from "ethers"; import { getMultiCallHandlerAddress } from "../_multicall-handler"; export type CrossSwapType = @@ -28,6 +32,7 @@ export type LeftoverType = (typeof LEFTOVER_TYPE)[keyof typeof LEFTOVER_TYPE]; export const AMOUNT_TYPE = { EXACT_INPUT: "exactInput", + EXACT_OUTPUT: "exactOutput", MIN_OUTPUT: "minOutput", } as const; @@ -53,14 +58,17 @@ export async function getCrossSwapQuotes( throw new Error("Not implemented yet"); } - if (crossSwap.type === AMOUNT_TYPE.MIN_OUTPUT) { - return getCrossSwapQuotesForMinOutput(crossSwap); + if ( + crossSwap.type === AMOUNT_TYPE.MIN_OUTPUT || + crossSwap.type === AMOUNT_TYPE.EXACT_OUTPUT + ) { + return getCrossSwapQuotesForOutput(crossSwap); } throw new Error("Invalid amount type"); } -export async function getCrossSwapQuotesForMinOutput(crossSwap: CrossSwap) { +export async function getCrossSwapQuotesForOutput(crossSwap: CrossSwap) { const crossSwapType = getCrossSwapType({ inputToken: crossSwap.inputToken.address, originChainId: crossSwap.inputToken.chainId, @@ -69,19 +77,19 @@ export async function getCrossSwapQuotesForMinOutput(crossSwap: CrossSwap) { }); if (crossSwapType === CROSS_SWAP_TYPE.BRIDGEABLE_TO_BRIDGEABLE) { - return getCrossSwapQuotesForMinOutputB2B(crossSwap); + return getCrossSwapQuotesForOutputB2B(crossSwap); } if (crossSwapType === CROSS_SWAP_TYPE.BRIDGEABLE_TO_ANY) { - return getCrossSwapQuotesForMinOutputB2A(crossSwap); + return getCrossSwapQuotesForOutputB2A(crossSwap); } if (crossSwapType === CROSS_SWAP_TYPE.ANY_TO_BRIDGEABLE) { - return getCrossSwapQuotesForMinOutputA2B(crossSwap); + return getCrossSwapQuotesForOutputA2B(crossSwap); } if (crossSwapType === CROSS_SWAP_TYPE.ANY_TO_ANY) { - return getCrossSwapQuotesForMinOutputA2A(crossSwap); + return getCrossSwapQuotesForOutputA2A(crossSwap); } throw new Error("Invalid cross swap type"); @@ -92,14 +100,25 @@ export async function getCrossSwapQuotesForExactInput(crossSwap: CrossSwap) { throw new Error("Not implemented yet"); } -export async function getCrossSwapQuotesForMinOutputB2B(crossSwap: CrossSwap) { +export async function getCrossSwapQuotesForOutputB2B(crossSwap: CrossSwap) { const bridgeQuote = await getBridgeQuoteForMinOutput({ inputToken: crossSwap.inputToken, outputToken: crossSwap.outputToken, minOutputAmount: crossSwap.amount, - // @TODO: handle ETH/WETH message generation - message: "0x", + recipient: getMultiCallHandlerAddress(crossSwap.outputToken.chainId), + message: + crossSwap.type === AMOUNT_TYPE.EXACT_OUTPUT + ? buildExactOutputBridgeTokenMessage(crossSwap) + : buildMinOutputBridgeTokenMessage(crossSwap), }); + + if (crossSwap.type === AMOUNT_TYPE.MIN_OUTPUT) { + bridgeQuote.message = buildMinOutputBridgeTokenMessage( + crossSwap, + bridgeQuote.outputAmount + ); + } + return { crossSwap, destinationSwapQuote: undefined, @@ -108,19 +127,19 @@ export async function getCrossSwapQuotesForMinOutputB2B(crossSwap: CrossSwap) { }; } -export async function getCrossSwapQuotesForMinOutputB2A(crossSwap: CrossSwap) { +export async function getCrossSwapQuotesForOutputB2A(crossSwap: CrossSwap) { // @TODO: Add support for other DEXes / aggregators - return getUniswapCrossSwapQuotesForMinOutputB2A(crossSwap); + return getUniswapCrossSwapQuotesForOutputB2A(crossSwap); } -export async function getCrossSwapQuotesForMinOutputA2B(crossSwap: CrossSwap) { +export async function getCrossSwapQuotesForOutputA2B(crossSwap: CrossSwap) { // @TODO: Add support for other DEXes / aggregators - return getUniswapCrossSwapQuotesForMinOutputA2B(crossSwap); + return getUniswapCrossSwapQuotesForOutputA2B(crossSwap); } -export async function getCrossSwapQuotesForMinOutputA2A(crossSwap: CrossSwap) { +export async function getCrossSwapQuotesForOutputA2A(crossSwap: CrossSwap) { // @TODO: Add support for other DEXes / aggregators - return getBestUniswapCrossSwapQuotesForMinOutputA2A(crossSwap, { + return getBestUniswapCrossSwapQuotesForOutputA2A(crossSwap, { preferredBridgeTokens: PREFERRED_BRIDGE_TOKENS, bridgeRoutesLimit: 2, }); @@ -163,9 +182,7 @@ export async function buildCrossSwapTx( const spokePool = getSpokePool(originChainId); const deposit = { depositor: crossSwapQuotes.crossSwap.depositor, - recipient: crossSwapQuotes.destinationSwapQuote - ? getMultiCallHandlerAddress(destinationChainId) - : crossSwapQuotes.crossSwap.recipient, + recipient: getMultiCallHandlerAddress(destinationChainId), inputToken: crossSwapQuotes.bridgeQuote.inputToken.address, outputToken: crossSwapQuotes.bridgeQuote.outputToken.address, inputAmount: crossSwapQuotes.bridgeQuote.inputAmount, @@ -191,7 +208,12 @@ export async function buildCrossSwapTx( crossSwapQuotes.originSwapQuote.swapTx.data, crossSwapQuotes.originSwapQuote.maximumAmountIn, crossSwapQuotes.originSwapQuote.minAmountOut, - deposit + deposit, + { + value: crossSwapQuotes.crossSwap.isInputNative + ? deposit.inputAmount + : 0, + } ); toAddress = swapAndBridge.address; } else { @@ -210,7 +232,12 @@ export async function buildCrossSwapTx( deposit.quoteTimestamp, deposit.fillDeadline, deposit.exclusivityDeadline, - deposit.message + deposit.message, + { + value: crossSwapQuotes.crossSwap.isInputNative + ? deposit.inputAmount + : 0, + } ); toAddress = spokePool.address; } diff --git a/api/_dexes/types.ts b/api/_dexes/types.ts index 6e00f04ce..d8205279a 100644 --- a/api/_dexes/types.ts +++ b/api/_dexes/types.ts @@ -19,7 +19,8 @@ export type Swap = { recipient: string; slippageTolerance: number; type: AmountType; - leftoverType?: LeftoverType; + isInputNative?: boolean; + isOutputNative?: boolean; }; export type CrossSwap = { @@ -33,6 +34,8 @@ export type CrossSwap = { leftoverType?: LeftoverType; refundOnOrigin: boolean; refundAddress?: string; + isInputNative?: boolean; + isOutputNative?: boolean; }; export type SupportedDex = "1inch" | "uniswap"; diff --git a/api/_dexes/uniswap.ts b/api/_dexes/uniswap.ts index b658edfc8..02f46cdc4 100644 --- a/api/_dexes/uniswap.ts +++ b/api/_dexes/uniswap.ts @@ -19,6 +19,10 @@ import { import { TOKEN_SYMBOLS_MAP } from "../_constants"; import { buildMulticallHandlerMessage, + encodeApproveCalldata, + encodeDrainCalldata, + encodeTransferCalldata, + encodeWethWithdrawCalldata, getMultiCallHandlerAddress, } from "../_multicall-handler"; import { @@ -28,8 +32,13 @@ import { CrossSwap, SwapQuote, } from "./types"; -import { getSwapAndBridgeAddress, NoSwapRouteError } from "./utils"; -import { LEFTOVER_TYPE } from "./cross-swap"; +import { + buildExactOutputBridgeTokenMessage, + buildMinOutputBridgeTokenMessage, + getSwapAndBridgeAddress, + NoSwapRouteError, +} from "./utils"; +import { AMOUNT_TYPE } from "./cross-swap"; // Taken from here: https://docs.uniswap.org/contracts/v3/reference/deployments/ export const SWAP_ROUTER_02_ADDRESS = { @@ -103,7 +112,7 @@ export async function getUniswapQuoteForOriginSwapExactInput( * 1. Get destination swap quote for bridgeable output token -> any token * 2. Get bridge quote for bridgeable input token -> bridgeable output token */ -export async function getUniswapCrossSwapQuotesForMinOutputB2A( +export async function getUniswapCrossSwapQuotesForOutputB2A( crossSwap: CrossSwap ) { const destinationSwapChainId = crossSwap.outputToken.chainId; @@ -141,7 +150,7 @@ export async function getUniswapCrossSwapQuotesForMinOutputB2A( chainId: destinationSwapChainId, tokenIn: bridgeableOutputToken, tokenOut: crossSwap.outputToken, - recipient: crossSwap.recipient, + recipient: getMultiCallHandlerAddress(destinationSwapChainId), slippageTolerance: crossSwap.slippageTolerance, }; // 1.1. Get destination swap quote for bridgeable output token -> any token @@ -154,8 +163,8 @@ export async function getUniswapCrossSwapQuotesForMinOutputB2A( TradeType.EXACT_OUTPUT ); // 1.2. Re-fetch destination swap quote with exact input amount if leftover tokens - // should be sent as output tokens instead of bridgeable output tokens. - if (crossSwap.leftoverType === LEFTOVER_TYPE.OUTPUT_TOKEN) { + // should be sent to receiver. + if (crossSwap.type === AMOUNT_TYPE.MIN_OUTPUT) { destinationSwapQuote = await getUniswapQuote( { ...destinationSwap, @@ -196,10 +205,11 @@ export async function getUniswapCrossSwapQuotesForMinOutputB2A( * 1. Get bridge quote for bridgeable input token -> bridgeable output token * 2. Get origin swap quote for any input token -> bridgeable input token */ -export async function getUniswapCrossSwapQuotesForMinOutputA2B( +export async function getUniswapCrossSwapQuotesForOutputA2B( crossSwap: CrossSwap ) { const originSwapChainId = crossSwap.inputToken.chainId; + const destinationChainId = crossSwap.outputToken.chainId; const bridgeRoute = getRouteByOutputTokenAndOriginChain( crossSwap.outputToken.address, originSwapChainId @@ -235,8 +245,16 @@ export async function getUniswapCrossSwapQuotesForMinOutputA2B( inputToken: bridgeableInputToken, outputToken: crossSwap.outputToken, minOutputAmount: crossSwap.amount, - // @TODO: handle ETH/WETH message generation + recipient: getMultiCallHandlerAddress(destinationChainId), + message: buildExactOutputBridgeTokenMessage(crossSwap), }); + // 1.1. Update bridge quote message for min. output amount + if (crossSwap.type === AMOUNT_TYPE.MIN_OUTPUT && crossSwap.isOutputNative) { + bridgeQuote.message = buildMinOutputBridgeTokenMessage( + crossSwap, + bridgeQuote.outputAmount + ); + } const originSwap = { chainId: originSwapChainId, @@ -286,7 +304,7 @@ export async function getUniswapCrossSwapQuotesForMinOutputA2B( * @param crossSwap * @param opts */ -export async function getBestUniswapCrossSwapQuotesForMinOutputA2A( +export async function getBestUniswapCrossSwapQuotesForOutputA2A( crossSwap: CrossSwap, opts: { preferredBridgeTokens: string[]; @@ -321,7 +339,7 @@ export async function getBestUniswapCrossSwapQuotesForMinOutputA2A( const crossSwapQuotes = await Promise.all( bridgeRoutesToCompare.map((bridgeRoute) => - getUniswapCrossSwapQuotesForMinOutputA2A(crossSwap, bridgeRoute) + getUniswapCrossSwapQuotesForOutputA2A(crossSwap, bridgeRoute) ) ); @@ -342,7 +360,7 @@ export async function getBestUniswapCrossSwapQuotesForMinOutputA2A( * @param crossSwap * @param bridgeRoute */ -export async function getUniswapCrossSwapQuotesForMinOutputA2A( +export async function getUniswapCrossSwapQuotesForOutputA2A( crossSwap: CrossSwap, bridgeRoute: { fromTokenAddress: string; @@ -398,7 +416,7 @@ export async function getUniswapCrossSwapQuotesForMinOutputA2A( chainId: destinationSwapChainId, tokenIn: bridgeableOutputToken, tokenOut: crossSwap.outputToken, - recipient: crossSwap.recipient, + recipient: getMultiCallHandlerAddress(destinationSwapChainId), slippageTolerance: crossSwap.slippageTolerance, }; @@ -412,8 +430,8 @@ export async function getUniswapCrossSwapQuotesForMinOutputA2A( TradeType.EXACT_OUTPUT ); // 1.2. Re-fetch destination swap quote with exact input amount if leftover tokens - // should be sent as output tokens instead of bridgeable output tokens. - if (crossSwap.leftoverType === LEFTOVER_TYPE.OUTPUT_TOKEN) { + // should be sent to receiver. + if (crossSwap.type === AMOUNT_TYPE.MIN_OUTPUT) { destinationSwapQuote = await getUniswapQuote( { ...destinationSwap, @@ -607,6 +625,41 @@ function buildDestinationSwapCrossChainMessage({ destinationSwapQuote: SwapQuote; }) { const destinationSwapChainId = destinationSwapQuote.tokenOut.chainId; + const transferActions = crossSwap.isOutputNative + ? // If output token is native, we need to unwrap WETH before sending it to the + // recipient. This is because we only handle WETH in the destination swap. + [ + { + target: crossSwap.outputToken.address, + callData: encodeWethWithdrawCalldata(crossSwap.amount), + value: "0", + }, + { + target: crossSwap.recipient, + callData: "0x", + value: crossSwap.amount.toString(), + }, + ] + : [ + { + target: crossSwap.outputToken.address, + callData: encodeTransferCalldata( + crossSwap.recipient, + crossSwap.amount + ), + value: "0", + }, + { + target: getMultiCallHandlerAddress(destinationSwapChainId), + callData: encodeDrainCalldata( + crossSwap.outputToken.address, + crossSwap.type === AMOUNT_TYPE.EXACT_OUTPUT + ? crossSwap.depositor + : crossSwap.recipient + ), + value: "0", + }, + ]; return buildMulticallHandlerMessage({ // @TODO: handle fallback recipient for params `refundOnOrigin` and `refundAddress` fallbackRecipient: crossSwap.depositor, @@ -626,12 +679,16 @@ function buildDestinationSwapCrossChainMessage({ callData: destinationSwapQuote.swapTx.data, value: destinationSwapQuote.swapTx.value, }, + // transfer output tokens to recipient + ...transferActions, // drain remaining bridgeable output tokens from MultiCallHandler contract { target: getMultiCallHandlerAddress(destinationSwapChainId), callData: encodeDrainCalldata( bridgeableOutputToken.address, - crossSwap.depositor + crossSwap.type === AMOUNT_TYPE.EXACT_OUTPUT + ? crossSwap.depositor + : crossSwap.recipient ), value: "0", }, @@ -639,22 +696,6 @@ function buildDestinationSwapCrossChainMessage({ }); } -function encodeApproveCalldata(spender: string, value: ethers.BigNumber) { - const approveFunction = "function approve(address spender, uint256 value)"; - const erc20Interface = new ethers.utils.Interface([approveFunction]); - return erc20Interface.encodeFunctionData("approve", [spender, value]); -} - -function encodeDrainCalldata(token: string, destination: string) { - const drainFunction = - "function drainLeftoverTokens(address token, address payable destination)"; - const multicallHandlerInterface = new ethers.utils.Interface([drainFunction]); - return multicallHandlerInterface.encodeFunctionData("drainLeftoverTokens", [ - token, - destination, - ]); -} - function assertMinOutputAmount( amountOut: BigNumber, expectedMinAmountOut: BigNumber diff --git a/api/_dexes/utils.ts b/api/_dexes/utils.ts index 06cb97ece..3702417dd 100644 --- a/api/_dexes/utils.ts +++ b/api/_dexes/utils.ts @@ -1,6 +1,15 @@ -import { UniversalSwapAndBridge__factory } from "@across-protocol/contracts/dist/typechain"; +import { UniversalSwapAndBridge__factory } from "../_typechain/factories/SwapAndBridge.sol"; +import { BigNumber } from "ethers"; import { ENABLED_ROUTES, getProvider } from "../_utils"; +import { + buildMulticallHandlerMessage, + encodeDrainCalldata, + encodeTransferCalldata, + encodeWethWithdrawCalldata, + getMultiCallHandlerAddress, +} from "../_multicall-handler"; +import { CrossSwap } from "./types"; export class UnsupportedDex extends Error { constructor(dex: string) { @@ -60,3 +69,96 @@ function _isDexSupported( ): dex is keyof typeof ENABLED_ROUTES.swapAndBridgeAddresses { return swapAndBridgeDexes.includes(dex); } + +/** + * This builds a cross-chain message for a (any/bridgeable)-to-bridgeable cross swap + * with a specific amount of output tokens that the recipient will receive. Excess + * tokens are refunded to the depositor. + */ +export function buildExactOutputBridgeTokenMessage(crossSwap: CrossSwap) { + const transferActions = crossSwap.isOutputNative + ? // WETH unwrap to ETH + [ + { + target: crossSwap.outputToken.address, + callData: encodeWethWithdrawCalldata(crossSwap.amount), + value: "0", + }, + { + target: crossSwap.recipient, + callData: "0x", + value: crossSwap.amount.toString(), + }, + ] + : // ERC-20 token transfer + [ + { + target: crossSwap.outputToken.address, + callData: encodeTransferCalldata( + crossSwap.recipient, + crossSwap.amount + ), + value: "0", + }, + ]; + return buildMulticallHandlerMessage({ + // @TODO: handle fallback recipient for params `refundOnOrigin` and `refundAddress` + fallbackRecipient: crossSwap.depositor, + actions: [ + ...transferActions, + // drain remaining bridgeable output tokens from MultiCallHandler contract + { + target: getMultiCallHandlerAddress(crossSwap.outputToken.chainId), + callData: encodeDrainCalldata( + crossSwap.outputToken.address, + crossSwap.depositor + ), + value: "0", + }, + ], + }); +} + +/** + * This builds a cross-chain message for a (any/bridgeable)-to-bridgeable cross swap + * with a min. amount of output tokens that the recipient will receive. + */ +export function buildMinOutputBridgeTokenMessage( + crossSwap: CrossSwap, + unwrapAmount?: BigNumber +) { + const transferActions = crossSwap.isOutputNative + ? // WETH unwrap to ETH + [ + { + target: crossSwap.outputToken.address, + callData: encodeWethWithdrawCalldata( + unwrapAmount || crossSwap.amount + ), + value: "0", + }, + { + target: crossSwap.recipient, + callData: "0x", + value: crossSwap.amount.toString(), + }, + ] + : // ERC-20 token transfer + []; + return buildMulticallHandlerMessage({ + // @TODO: handle fallback recipient for params `refundOnOrigin` and `refundAddress` + fallbackRecipient: crossSwap.depositor, + actions: [ + ...transferActions, + // drain remaining bridgeable output tokens from MultiCallHandler contract + { + target: getMultiCallHandlerAddress(crossSwap.outputToken.chainId), + callData: encodeDrainCalldata( + crossSwap.outputToken.address, + crossSwap.recipient + ), + value: "0", + }, + ], + }); +} diff --git a/api/_multicall-handler.ts b/api/_multicall-handler.ts index 9bcb86a7b..a4c8ef6c1 100644 --- a/api/_multicall-handler.ts +++ b/api/_multicall-handler.ts @@ -46,3 +46,34 @@ export function buildMulticallHandlerMessage(params: { ] ); } + +export function encodeWethWithdrawCalldata(value: ethers.BigNumber) { + const withdrawFunction = "function withdraw(uint256 wad)"; + const wethInterface = new ethers.utils.Interface([withdrawFunction]); + return wethInterface.encodeFunctionData("withdraw", [value]); +} + +export function encodeApproveCalldata( + spender: string, + value: ethers.BigNumber +) { + const approveFunction = "function approve(address spender, uint256 value)"; + const erc20Interface = new ethers.utils.Interface([approveFunction]); + return erc20Interface.encodeFunctionData("approve", [spender, value]); +} + +export function encodeTransferCalldata(to: string, value: ethers.BigNumber) { + const approveFunction = "function transfer(address to, uint256 value)"; + const erc20Interface = new ethers.utils.Interface([approveFunction]); + return erc20Interface.encodeFunctionData("transfer", [to, value]); +} + +export function encodeDrainCalldata(token: string, destination: string) { + const drainFunction = + "function drainLeftoverTokens(address token, address payable destination)"; + const multicallHandlerInterface = new ethers.utils.Interface([drainFunction]); + return multicallHandlerInterface.encodeFunctionData("drainLeftoverTokens", [ + token, + destination, + ]); +} diff --git a/api/_typechain/SwapAndBridge.sol/SwapAndBridge.ts b/api/_typechain/SwapAndBridge.sol/SwapAndBridge.ts new file mode 100644 index 000000000..8909d98ba --- /dev/null +++ b/api/_typechain/SwapAndBridge.sol/SwapAndBridge.ts @@ -0,0 +1,345 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ +import type { + BaseContract, + BigNumber, + BigNumberish, + BytesLike, + CallOverrides, + ContractTransaction, + Overrides, + PopulatedTransaction, + Signer, + utils, +} from "ethers"; +import type { + FunctionFragment, + Result, + EventFragment, +} from "@ethersproject/abi"; +import type { Listener, Provider } from "@ethersproject/providers"; +import type { + TypedEventFilter, + TypedEvent, + TypedListener, + OnEvent, +} from "@across-protocol/contracts/dist/typechain/common"; + +export declare namespace SwapAndBridgeBase { + export type DepositDataStruct = { + outputToken: string; + outputAmount: BigNumberish; + depositor: string; + recipient: string; + destinationChainid: BigNumberish; + exclusiveRelayer: string; + quoteTimestamp: BigNumberish; + fillDeadline: BigNumberish; + exclusivityDeadline: BigNumberish; + message: BytesLike; + }; + + export type DepositDataStructOutput = [ + string, + BigNumber, + string, + string, + BigNumber, + string, + number, + number, + number, + string, + ] & { + outputToken: string; + outputAmount: BigNumber; + depositor: string; + recipient: string; + destinationChainid: BigNumber; + exclusiveRelayer: string; + quoteTimestamp: number; + fillDeadline: number; + exclusivityDeadline: number; + message: string; + }; +} + +export interface SwapAndBridgeInterface extends utils.Interface { + functions: { + "ACROSS_INPUT_TOKEN()": FunctionFragment; + "EXCHANGE()": FunctionFragment; + "SPOKE_POOL()": FunctionFragment; + "SWAP_TOKEN()": FunctionFragment; + "allowedSelectors(bytes4)": FunctionFragment; + "multicall(bytes[])": FunctionFragment; + "swapAndBridge(bytes,uint256,uint256,(address,uint256,address,address,uint256,address,uint32,uint32,uint32,bytes))": FunctionFragment; + }; + + getFunction( + nameOrSignatureOrTopic: + | "ACROSS_INPUT_TOKEN" + | "EXCHANGE" + | "SPOKE_POOL" + | "SWAP_TOKEN" + | "allowedSelectors" + | "multicall" + | "swapAndBridge" + ): FunctionFragment; + + encodeFunctionData( + functionFragment: "ACROSS_INPUT_TOKEN", + values?: undefined + ): string; + encodeFunctionData(functionFragment: "EXCHANGE", values?: undefined): string; + encodeFunctionData( + functionFragment: "SPOKE_POOL", + values?: undefined + ): string; + encodeFunctionData( + functionFragment: "SWAP_TOKEN", + values?: undefined + ): string; + encodeFunctionData( + functionFragment: "allowedSelectors", + values: [BytesLike] + ): string; + encodeFunctionData( + functionFragment: "multicall", + values: [BytesLike[]] + ): string; + encodeFunctionData( + functionFragment: "swapAndBridge", + values: [ + BytesLike, + BigNumberish, + BigNumberish, + SwapAndBridgeBase.DepositDataStruct, + ] + ): string; + + decodeFunctionResult( + functionFragment: "ACROSS_INPUT_TOKEN", + data: BytesLike + ): Result; + decodeFunctionResult(functionFragment: "EXCHANGE", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "SPOKE_POOL", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "SWAP_TOKEN", data: BytesLike): Result; + decodeFunctionResult( + functionFragment: "allowedSelectors", + data: BytesLike + ): Result; + decodeFunctionResult(functionFragment: "multicall", data: BytesLike): Result; + decodeFunctionResult( + functionFragment: "swapAndBridge", + data: BytesLike + ): Result; + + events: { + "SwapBeforeBridge(address,address,address,uint256,uint256,address,uint256)": EventFragment; + }; + + getEvent(nameOrSignatureOrTopic: "SwapBeforeBridge"): EventFragment; +} + +export interface SwapBeforeBridgeEventObject { + exchange: string; + swapToken: string; + acrossInputToken: string; + swapTokenAmount: BigNumber; + acrossInputAmount: BigNumber; + acrossOutputToken: string; + acrossOutputAmount: BigNumber; +} +export type SwapBeforeBridgeEvent = TypedEvent< + [string, string, string, BigNumber, BigNumber, string, BigNumber], + SwapBeforeBridgeEventObject +>; + +export type SwapBeforeBridgeEventFilter = + TypedEventFilter; + +export interface SwapAndBridge extends BaseContract { + connect(signerOrProvider: Signer | Provider | string): this; + attach(addressOrName: string): this; + deployed(): Promise; + + interface: SwapAndBridgeInterface; + + queryFilter( + event: TypedEventFilter, + fromBlockOrBlockhash?: string | number | undefined, + toBlock?: string | number | undefined + ): Promise>; + + listeners( + eventFilter?: TypedEventFilter + ): Array>; + listeners(eventName?: string): Array; + removeAllListeners( + eventFilter: TypedEventFilter + ): this; + removeAllListeners(eventName?: string): this; + off: OnEvent; + on: OnEvent; + once: OnEvent; + removeListener: OnEvent; + + functions: { + ACROSS_INPUT_TOKEN(overrides?: CallOverrides): Promise<[string]>; + + EXCHANGE(overrides?: CallOverrides): Promise<[string]>; + + SPOKE_POOL(overrides?: CallOverrides): Promise<[string]>; + + SWAP_TOKEN(overrides?: CallOverrides): Promise<[string]>; + + allowedSelectors( + arg0: BytesLike, + overrides?: CallOverrides + ): Promise<[boolean]>; + + multicall( + data: BytesLike[], + overrides?: Overrides & { from?: string } + ): Promise; + + swapAndBridge( + routerCalldata: BytesLike, + swapTokenAmount: BigNumberish, + minExpectedInputTokenAmount: BigNumberish, + depositData: SwapAndBridgeBase.DepositDataStruct, + overrides?: Overrides & { from?: string } + ): Promise; + }; + + ACROSS_INPUT_TOKEN(overrides?: CallOverrides): Promise; + + EXCHANGE(overrides?: CallOverrides): Promise; + + SPOKE_POOL(overrides?: CallOverrides): Promise; + + SWAP_TOKEN(overrides?: CallOverrides): Promise; + + allowedSelectors( + arg0: BytesLike, + overrides?: CallOverrides + ): Promise; + + multicall( + data: BytesLike[], + overrides?: Overrides & { from?: string } + ): Promise; + + swapAndBridge( + routerCalldata: BytesLike, + swapTokenAmount: BigNumberish, + minExpectedInputTokenAmount: BigNumberish, + depositData: SwapAndBridgeBase.DepositDataStruct, + overrides?: Overrides & { from?: string } + ): Promise; + + callStatic: { + ACROSS_INPUT_TOKEN(overrides?: CallOverrides): Promise; + + EXCHANGE(overrides?: CallOverrides): Promise; + + SPOKE_POOL(overrides?: CallOverrides): Promise; + + SWAP_TOKEN(overrides?: CallOverrides): Promise; + + allowedSelectors( + arg0: BytesLike, + overrides?: CallOverrides + ): Promise; + + multicall(data: BytesLike[], overrides?: CallOverrides): Promise; + + swapAndBridge( + routerCalldata: BytesLike, + swapTokenAmount: BigNumberish, + minExpectedInputTokenAmount: BigNumberish, + depositData: SwapAndBridgeBase.DepositDataStruct, + overrides?: CallOverrides + ): Promise; + }; + + filters: { + "SwapBeforeBridge(address,address,address,uint256,uint256,address,uint256)"( + exchange?: null, + swapToken?: string | null, + acrossInputToken?: string | null, + swapTokenAmount?: null, + acrossInputAmount?: null, + acrossOutputToken?: string | null, + acrossOutputAmount?: null + ): SwapBeforeBridgeEventFilter; + SwapBeforeBridge( + exchange?: null, + swapToken?: string | null, + acrossInputToken?: string | null, + swapTokenAmount?: null, + acrossInputAmount?: null, + acrossOutputToken?: string | null, + acrossOutputAmount?: null + ): SwapBeforeBridgeEventFilter; + }; + + estimateGas: { + ACROSS_INPUT_TOKEN(overrides?: CallOverrides): Promise; + + EXCHANGE(overrides?: CallOverrides): Promise; + + SPOKE_POOL(overrides?: CallOverrides): Promise; + + SWAP_TOKEN(overrides?: CallOverrides): Promise; + + allowedSelectors( + arg0: BytesLike, + overrides?: CallOverrides + ): Promise; + + multicall( + data: BytesLike[], + overrides?: Overrides & { from?: string } + ): Promise; + + swapAndBridge( + routerCalldata: BytesLike, + swapTokenAmount: BigNumberish, + minExpectedInputTokenAmount: BigNumberish, + depositData: SwapAndBridgeBase.DepositDataStruct, + overrides?: Overrides & { from?: string } + ): Promise; + }; + + populateTransaction: { + ACROSS_INPUT_TOKEN( + overrides?: CallOverrides + ): Promise; + + EXCHANGE(overrides?: CallOverrides): Promise; + + SPOKE_POOL(overrides?: CallOverrides): Promise; + + SWAP_TOKEN(overrides?: CallOverrides): Promise; + + allowedSelectors( + arg0: BytesLike, + overrides?: CallOverrides + ): Promise; + + multicall( + data: BytesLike[], + overrides?: Overrides & { from?: string } + ): Promise; + + swapAndBridge( + routerCalldata: BytesLike, + swapTokenAmount: BigNumberish, + minExpectedInputTokenAmount: BigNumberish, + depositData: SwapAndBridgeBase.DepositDataStruct, + overrides?: Overrides & { from?: string } + ): Promise; + }; +} diff --git a/api/_typechain/SwapAndBridge.sol/SwapAndBridgeBase.ts b/api/_typechain/SwapAndBridge.sol/SwapAndBridgeBase.ts new file mode 100644 index 000000000..bbbdf9bdb --- /dev/null +++ b/api/_typechain/SwapAndBridge.sol/SwapAndBridgeBase.ts @@ -0,0 +1,211 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ + +import type { + BaseContract, + BigNumber, + BytesLike, + CallOverrides, + ContractTransaction, + Overrides, + PopulatedTransaction, + Signer, + utils, +} from "ethers"; +import type { + FunctionFragment, + Result, + EventFragment, +} from "@ethersproject/abi"; +import type { Listener, Provider } from "@ethersproject/providers"; +import type { + TypedEventFilter, + TypedEvent, + TypedListener, + OnEvent, +} from "@across-protocol/contracts/dist/typechain/common"; + +export interface SwapAndBridgeBaseInterface extends utils.Interface { + functions: { + "EXCHANGE()": FunctionFragment; + "SPOKE_POOL()": FunctionFragment; + "allowedSelectors(bytes4)": FunctionFragment; + "multicall(bytes[])": FunctionFragment; + }; + + getFunction( + nameOrSignatureOrTopic: + | "EXCHANGE" + | "SPOKE_POOL" + | "allowedSelectors" + | "multicall" + ): FunctionFragment; + + encodeFunctionData(functionFragment: "EXCHANGE", values?: undefined): string; + encodeFunctionData( + functionFragment: "SPOKE_POOL", + values?: undefined + ): string; + encodeFunctionData( + functionFragment: "allowedSelectors", + values: [BytesLike] + ): string; + encodeFunctionData( + functionFragment: "multicall", + values: [BytesLike[]] + ): string; + + decodeFunctionResult(functionFragment: "EXCHANGE", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "SPOKE_POOL", data: BytesLike): Result; + decodeFunctionResult( + functionFragment: "allowedSelectors", + data: BytesLike + ): Result; + decodeFunctionResult(functionFragment: "multicall", data: BytesLike): Result; + + events: { + "SwapBeforeBridge(address,address,address,uint256,uint256,address,uint256)": EventFragment; + }; + + getEvent(nameOrSignatureOrTopic: "SwapBeforeBridge"): EventFragment; +} + +export interface SwapBeforeBridgeEventObject { + exchange: string; + swapToken: string; + acrossInputToken: string; + swapTokenAmount: BigNumber; + acrossInputAmount: BigNumber; + acrossOutputToken: string; + acrossOutputAmount: BigNumber; +} +export type SwapBeforeBridgeEvent = TypedEvent< + [string, string, string, BigNumber, BigNumber, string, BigNumber], + SwapBeforeBridgeEventObject +>; + +export type SwapBeforeBridgeEventFilter = + TypedEventFilter; + +export interface SwapAndBridgeBase extends BaseContract { + connect(signerOrProvider: Signer | Provider | string): this; + attach(addressOrName: string): this; + deployed(): Promise; + + interface: SwapAndBridgeBaseInterface; + + queryFilter( + event: TypedEventFilter, + fromBlockOrBlockhash?: string | number | undefined, + toBlock?: string | number | undefined + ): Promise>; + + listeners( + eventFilter?: TypedEventFilter + ): Array>; + listeners(eventName?: string): Array; + removeAllListeners( + eventFilter: TypedEventFilter + ): this; + removeAllListeners(eventName?: string): this; + off: OnEvent; + on: OnEvent; + once: OnEvent; + removeListener: OnEvent; + + functions: { + EXCHANGE(overrides?: CallOverrides): Promise<[string]>; + + SPOKE_POOL(overrides?: CallOverrides): Promise<[string]>; + + allowedSelectors( + arg0: BytesLike, + overrides?: CallOverrides + ): Promise<[boolean]>; + + multicall( + data: BytesLike[], + overrides?: Overrides & { from?: string } + ): Promise; + }; + + EXCHANGE(overrides?: CallOverrides): Promise; + + SPOKE_POOL(overrides?: CallOverrides): Promise; + + allowedSelectors( + arg0: BytesLike, + overrides?: CallOverrides + ): Promise; + + multicall( + data: BytesLike[], + overrides?: Overrides & { from?: string } + ): Promise; + + callStatic: { + EXCHANGE(overrides?: CallOverrides): Promise; + + SPOKE_POOL(overrides?: CallOverrides): Promise; + + allowedSelectors( + arg0: BytesLike, + overrides?: CallOverrides + ): Promise; + + multicall(data: BytesLike[], overrides?: CallOverrides): Promise; + }; + + filters: { + "SwapBeforeBridge(address,address,address,uint256,uint256,address,uint256)"( + exchange?: null, + swapToken?: string | null, + acrossInputToken?: string | null, + swapTokenAmount?: null, + acrossInputAmount?: null, + acrossOutputToken?: string | null, + acrossOutputAmount?: null + ): SwapBeforeBridgeEventFilter; + SwapBeforeBridge( + exchange?: null, + swapToken?: string | null, + acrossInputToken?: string | null, + swapTokenAmount?: null, + acrossInputAmount?: null, + acrossOutputToken?: string | null, + acrossOutputAmount?: null + ): SwapBeforeBridgeEventFilter; + }; + + estimateGas: { + EXCHANGE(overrides?: CallOverrides): Promise; + + SPOKE_POOL(overrides?: CallOverrides): Promise; + + allowedSelectors( + arg0: BytesLike, + overrides?: CallOverrides + ): Promise; + + multicall( + data: BytesLike[], + overrides?: Overrides & { from?: string } + ): Promise; + }; + + populateTransaction: { + EXCHANGE(overrides?: CallOverrides): Promise; + + SPOKE_POOL(overrides?: CallOverrides): Promise; + + allowedSelectors( + arg0: BytesLike, + overrides?: CallOverrides + ): Promise; + + multicall( + data: BytesLike[], + overrides?: Overrides & { from?: string } + ): Promise; + }; +} diff --git a/api/_typechain/SwapAndBridge.sol/UniversalSwapAndBridge.ts b/api/_typechain/SwapAndBridge.sol/UniversalSwapAndBridge.ts new file mode 100644 index 000000000..1612a08c3 --- /dev/null +++ b/api/_typechain/SwapAndBridge.sol/UniversalSwapAndBridge.ts @@ -0,0 +1,671 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ +/* eslint-disable */ +import type { + BaseContract, + BigNumber, + BigNumberish, + BytesLike, + CallOverrides, + ContractTransaction, + Overrides, + PayableOverrides, + PopulatedTransaction, + Signer, + utils, +} from "ethers"; +import type { + FunctionFragment, + Result, + EventFragment, +} from "@ethersproject/abi"; +import type { Listener, Provider } from "@ethersproject/providers"; +import type { + TypedEventFilter, + TypedEvent, + TypedListener, + OnEvent, +} from "@across-protocol/contracts/dist/typechain/common"; + +export declare namespace SwapAndBridgeBase { + export type DepositDataStruct = { + outputToken: string; + outputAmount: BigNumberish; + depositor: string; + recipient: string; + destinationChainid: BigNumberish; + exclusiveRelayer: string; + quoteTimestamp: BigNumberish; + fillDeadline: BigNumberish; + exclusivityDeadline: BigNumberish; + message: BytesLike; + }; + + export type DepositDataStructOutput = [ + string, + BigNumber, + string, + string, + BigNumber, + string, + number, + number, + number, + string, + ] & { + outputToken: string; + outputAmount: BigNumber; + depositor: string; + recipient: string; + destinationChainid: BigNumber; + exclusiveRelayer: string; + quoteTimestamp: number; + fillDeadline: number; + exclusivityDeadline: number; + message: string; + }; +} + +export interface UniversalSwapAndBridgeInterface extends utils.Interface { + functions: { + "EXCHANGE()": FunctionFragment; + "SPOKE_POOL()": FunctionFragment; + "allowedSelectors(bytes4)": FunctionFragment; + "depositWithAuthorization(address,uint256,(address,uint256,address,address,uint256,address,uint32,uint32,uint32,bytes),uint256,uint256,bytes32,uint8,bytes32,bytes32)": FunctionFragment; + "depositWithPermit(address,uint256,(address,uint256,address,address,uint256,address,uint32,uint32,uint32,bytes),uint256,uint8,bytes32,bytes32)": FunctionFragment; + "multicall(bytes[])": FunctionFragment; + "swapAndBridge(address,address,bytes,uint256,uint256,(address,uint256,address,address,uint256,address,uint32,uint32,uint32,bytes))": FunctionFragment; + "swapAndBridgeWithAuthorization(address,address,bytes,uint256,uint256,(address,uint256,address,address,uint256,address,uint32,uint32,uint32,bytes),uint256,uint256,bytes32,uint8,bytes32,bytes32)": FunctionFragment; + "swapAndBridgeWithPermit(address,address,bytes,uint256,uint256,(address,uint256,address,address,uint256,address,uint32,uint32,uint32,bytes),uint256,uint8,bytes32,bytes32)": FunctionFragment; + }; + + getFunction( + nameOrSignatureOrTopic: + | "EXCHANGE" + | "SPOKE_POOL" + | "allowedSelectors" + | "depositWithAuthorization" + | "depositWithPermit" + | "multicall" + | "swapAndBridge" + | "swapAndBridgeWithAuthorization" + | "swapAndBridgeWithPermit" + ): FunctionFragment; + + encodeFunctionData(functionFragment: "EXCHANGE", values?: undefined): string; + encodeFunctionData( + functionFragment: "SPOKE_POOL", + values?: undefined + ): string; + encodeFunctionData( + functionFragment: "allowedSelectors", + values: [BytesLike] + ): string; + encodeFunctionData( + functionFragment: "depositWithAuthorization", + values: [ + string, + BigNumberish, + SwapAndBridgeBase.DepositDataStruct, + BigNumberish, + BigNumberish, + BytesLike, + BigNumberish, + BytesLike, + BytesLike, + ] + ): string; + encodeFunctionData( + functionFragment: "depositWithPermit", + values: [ + string, + BigNumberish, + SwapAndBridgeBase.DepositDataStruct, + BigNumberish, + BigNumberish, + BytesLike, + BytesLike, + ] + ): string; + encodeFunctionData( + functionFragment: "multicall", + values: [BytesLike[]] + ): string; + encodeFunctionData( + functionFragment: "swapAndBridge", + values: [ + string, + string, + BytesLike, + BigNumberish, + BigNumberish, + SwapAndBridgeBase.DepositDataStruct, + ] + ): string; + encodeFunctionData( + functionFragment: "swapAndBridgeWithAuthorization", + values: [ + string, + string, + BytesLike, + BigNumberish, + BigNumberish, + SwapAndBridgeBase.DepositDataStruct, + BigNumberish, + BigNumberish, + BytesLike, + BigNumberish, + BytesLike, + BytesLike, + ] + ): string; + encodeFunctionData( + functionFragment: "swapAndBridgeWithPermit", + values: [ + string, + string, + BytesLike, + BigNumberish, + BigNumberish, + SwapAndBridgeBase.DepositDataStruct, + BigNumberish, + BigNumberish, + BytesLike, + BytesLike, + ] + ): string; + + decodeFunctionResult(functionFragment: "EXCHANGE", data: BytesLike): Result; + decodeFunctionResult(functionFragment: "SPOKE_POOL", data: BytesLike): Result; + decodeFunctionResult( + functionFragment: "allowedSelectors", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "depositWithAuthorization", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "depositWithPermit", + data: BytesLike + ): Result; + decodeFunctionResult(functionFragment: "multicall", data: BytesLike): Result; + decodeFunctionResult( + functionFragment: "swapAndBridge", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "swapAndBridgeWithAuthorization", + data: BytesLike + ): Result; + decodeFunctionResult( + functionFragment: "swapAndBridgeWithPermit", + data: BytesLike + ): Result; + + events: { + "SwapBeforeBridge(address,address,address,uint256,uint256,address,uint256)": EventFragment; + }; + + getEvent(nameOrSignatureOrTopic: "SwapBeforeBridge"): EventFragment; +} + +export interface SwapBeforeBridgeEventObject { + exchange: string; + swapToken: string; + acrossInputToken: string; + swapTokenAmount: BigNumber; + acrossInputAmount: BigNumber; + acrossOutputToken: string; + acrossOutputAmount: BigNumber; +} +export type SwapBeforeBridgeEvent = TypedEvent< + [string, string, string, BigNumber, BigNumber, string, BigNumber], + SwapBeforeBridgeEventObject +>; + +export type SwapBeforeBridgeEventFilter = + TypedEventFilter; + +export interface UniversalSwapAndBridge extends BaseContract { + connect(signerOrProvider: Signer | Provider | string): this; + attach(addressOrName: string): this; + deployed(): Promise; + + interface: UniversalSwapAndBridgeInterface; + + queryFilter( + event: TypedEventFilter, + fromBlockOrBlockhash?: string | number | undefined, + toBlock?: string | number | undefined + ): Promise>; + + listeners( + eventFilter?: TypedEventFilter + ): Array>; + listeners(eventName?: string): Array; + removeAllListeners( + eventFilter: TypedEventFilter + ): this; + removeAllListeners(eventName?: string): this; + off: OnEvent; + on: OnEvent; + once: OnEvent; + removeListener: OnEvent; + + functions: { + EXCHANGE(overrides?: CallOverrides): Promise<[string]>; + + SPOKE_POOL(overrides?: CallOverrides): Promise<[string]>; + + allowedSelectors( + arg0: BytesLike, + overrides?: CallOverrides + ): Promise<[boolean]>; + + depositWithAuthorization( + acrossInputToken: string, + acrossInputAmount: BigNumberish, + depositData: SwapAndBridgeBase.DepositDataStruct, + validAfter: BigNumberish, + validBefore: BigNumberish, + nonce: BytesLike, + v: BigNumberish, + r: BytesLike, + s: BytesLike, + overrides?: Overrides & { from?: string } + ): Promise; + + depositWithPermit( + acrossInputToken: string, + acrossInputAmount: BigNumberish, + depositData: SwapAndBridgeBase.DepositDataStruct, + deadline: BigNumberish, + v: BigNumberish, + r: BytesLike, + s: BytesLike, + overrides?: Overrides & { from?: string } + ): Promise; + + multicall( + data: BytesLike[], + overrides?: Overrides & { from?: string } + ): Promise; + + swapAndBridge( + swapToken: string, + acrossInputToken: string, + routerCalldata: BytesLike, + swapTokenAmount: BigNumberish, + minExpectedInputTokenAmount: BigNumberish, + depositData: SwapAndBridgeBase.DepositDataStruct, + overrides?: PayableOverrides & { from?: string } + ): Promise; + + swapAndBridgeWithAuthorization( + swapToken: string, + acrossInputToken: string, + routerCalldata: BytesLike, + swapTokenAmount: BigNumberish, + minExpectedInputTokenAmount: BigNumberish, + depositData: SwapAndBridgeBase.DepositDataStruct, + validAfter: BigNumberish, + validBefore: BigNumberish, + nonce: BytesLike, + v: BigNumberish, + r: BytesLike, + s: BytesLike, + overrides?: Overrides & { from?: string } + ): Promise; + + swapAndBridgeWithPermit( + swapToken: string, + acrossInputToken: string, + routerCalldata: BytesLike, + swapTokenAmount: BigNumberish, + minExpectedInputTokenAmount: BigNumberish, + depositData: SwapAndBridgeBase.DepositDataStruct, + deadline: BigNumberish, + v: BigNumberish, + r: BytesLike, + s: BytesLike, + overrides?: Overrides & { from?: string } + ): Promise; + }; + + EXCHANGE(overrides?: CallOverrides): Promise; + + SPOKE_POOL(overrides?: CallOverrides): Promise; + + allowedSelectors( + arg0: BytesLike, + overrides?: CallOverrides + ): Promise; + + depositWithAuthorization( + acrossInputToken: string, + acrossInputAmount: BigNumberish, + depositData: SwapAndBridgeBase.DepositDataStruct, + validAfter: BigNumberish, + validBefore: BigNumberish, + nonce: BytesLike, + v: BigNumberish, + r: BytesLike, + s: BytesLike, + overrides?: Overrides & { from?: string } + ): Promise; + + depositWithPermit( + acrossInputToken: string, + acrossInputAmount: BigNumberish, + depositData: SwapAndBridgeBase.DepositDataStruct, + deadline: BigNumberish, + v: BigNumberish, + r: BytesLike, + s: BytesLike, + overrides?: Overrides & { from?: string } + ): Promise; + + multicall( + data: BytesLike[], + overrides?: Overrides & { from?: string } + ): Promise; + + swapAndBridge( + swapToken: string, + acrossInputToken: string, + routerCalldata: BytesLike, + swapTokenAmount: BigNumberish, + minExpectedInputTokenAmount: BigNumberish, + depositData: SwapAndBridgeBase.DepositDataStruct, + overrides?: PayableOverrides & { from?: string } + ): Promise; + + swapAndBridgeWithAuthorization( + swapToken: string, + acrossInputToken: string, + routerCalldata: BytesLike, + swapTokenAmount: BigNumberish, + minExpectedInputTokenAmount: BigNumberish, + depositData: SwapAndBridgeBase.DepositDataStruct, + validAfter: BigNumberish, + validBefore: BigNumberish, + nonce: BytesLike, + v: BigNumberish, + r: BytesLike, + s: BytesLike, + overrides?: Overrides & { from?: string } + ): Promise; + + swapAndBridgeWithPermit( + swapToken: string, + acrossInputToken: string, + routerCalldata: BytesLike, + swapTokenAmount: BigNumberish, + minExpectedInputTokenAmount: BigNumberish, + depositData: SwapAndBridgeBase.DepositDataStruct, + deadline: BigNumberish, + v: BigNumberish, + r: BytesLike, + s: BytesLike, + overrides?: Overrides & { from?: string } + ): Promise; + + callStatic: { + EXCHANGE(overrides?: CallOverrides): Promise; + + SPOKE_POOL(overrides?: CallOverrides): Promise; + + allowedSelectors( + arg0: BytesLike, + overrides?: CallOverrides + ): Promise; + + depositWithAuthorization( + acrossInputToken: string, + acrossInputAmount: BigNumberish, + depositData: SwapAndBridgeBase.DepositDataStruct, + validAfter: BigNumberish, + validBefore: BigNumberish, + nonce: BytesLike, + v: BigNumberish, + r: BytesLike, + s: BytesLike, + overrides?: CallOverrides + ): Promise; + + depositWithPermit( + acrossInputToken: string, + acrossInputAmount: BigNumberish, + depositData: SwapAndBridgeBase.DepositDataStruct, + deadline: BigNumberish, + v: BigNumberish, + r: BytesLike, + s: BytesLike, + overrides?: CallOverrides + ): Promise; + + multicall(data: BytesLike[], overrides?: CallOverrides): Promise; + + swapAndBridge( + swapToken: string, + acrossInputToken: string, + routerCalldata: BytesLike, + swapTokenAmount: BigNumberish, + minExpectedInputTokenAmount: BigNumberish, + depositData: SwapAndBridgeBase.DepositDataStruct, + overrides?: CallOverrides + ): Promise; + + swapAndBridgeWithAuthorization( + swapToken: string, + acrossInputToken: string, + routerCalldata: BytesLike, + swapTokenAmount: BigNumberish, + minExpectedInputTokenAmount: BigNumberish, + depositData: SwapAndBridgeBase.DepositDataStruct, + validAfter: BigNumberish, + validBefore: BigNumberish, + nonce: BytesLike, + v: BigNumberish, + r: BytesLike, + s: BytesLike, + overrides?: CallOverrides + ): Promise; + + swapAndBridgeWithPermit( + swapToken: string, + acrossInputToken: string, + routerCalldata: BytesLike, + swapTokenAmount: BigNumberish, + minExpectedInputTokenAmount: BigNumberish, + depositData: SwapAndBridgeBase.DepositDataStruct, + deadline: BigNumberish, + v: BigNumberish, + r: BytesLike, + s: BytesLike, + overrides?: CallOverrides + ): Promise; + }; + + filters: { + "SwapBeforeBridge(address,address,address,uint256,uint256,address,uint256)"( + exchange?: null, + swapToken?: string | null, + acrossInputToken?: string | null, + swapTokenAmount?: null, + acrossInputAmount?: null, + acrossOutputToken?: string | null, + acrossOutputAmount?: null + ): SwapBeforeBridgeEventFilter; + SwapBeforeBridge( + exchange?: null, + swapToken?: string | null, + acrossInputToken?: string | null, + swapTokenAmount?: null, + acrossInputAmount?: null, + acrossOutputToken?: string | null, + acrossOutputAmount?: null + ): SwapBeforeBridgeEventFilter; + }; + + estimateGas: { + EXCHANGE(overrides?: CallOverrides): Promise; + + SPOKE_POOL(overrides?: CallOverrides): Promise; + + allowedSelectors( + arg0: BytesLike, + overrides?: CallOverrides + ): Promise; + + depositWithAuthorization( + acrossInputToken: string, + acrossInputAmount: BigNumberish, + depositData: SwapAndBridgeBase.DepositDataStruct, + validAfter: BigNumberish, + validBefore: BigNumberish, + nonce: BytesLike, + v: BigNumberish, + r: BytesLike, + s: BytesLike, + overrides?: Overrides & { from?: string } + ): Promise; + + depositWithPermit( + acrossInputToken: string, + acrossInputAmount: BigNumberish, + depositData: SwapAndBridgeBase.DepositDataStruct, + deadline: BigNumberish, + v: BigNumberish, + r: BytesLike, + s: BytesLike, + overrides?: Overrides & { from?: string } + ): Promise; + + multicall( + data: BytesLike[], + overrides?: Overrides & { from?: string } + ): Promise; + + swapAndBridge( + swapToken: string, + acrossInputToken: string, + routerCalldata: BytesLike, + swapTokenAmount: BigNumberish, + minExpectedInputTokenAmount: BigNumberish, + depositData: SwapAndBridgeBase.DepositDataStruct, + overrides?: PayableOverrides & { from?: string } + ): Promise; + + swapAndBridgeWithAuthorization( + swapToken: string, + acrossInputToken: string, + routerCalldata: BytesLike, + swapTokenAmount: BigNumberish, + minExpectedInputTokenAmount: BigNumberish, + depositData: SwapAndBridgeBase.DepositDataStruct, + validAfter: BigNumberish, + validBefore: BigNumberish, + nonce: BytesLike, + v: BigNumberish, + r: BytesLike, + s: BytesLike, + overrides?: Overrides & { from?: string } + ): Promise; + + swapAndBridgeWithPermit( + swapToken: string, + acrossInputToken: string, + routerCalldata: BytesLike, + swapTokenAmount: BigNumberish, + minExpectedInputTokenAmount: BigNumberish, + depositData: SwapAndBridgeBase.DepositDataStruct, + deadline: BigNumberish, + v: BigNumberish, + r: BytesLike, + s: BytesLike, + overrides?: Overrides & { from?: string } + ): Promise; + }; + + populateTransaction: { + EXCHANGE(overrides?: CallOverrides): Promise; + + SPOKE_POOL(overrides?: CallOverrides): Promise; + + allowedSelectors( + arg0: BytesLike, + overrides?: CallOverrides + ): Promise; + + depositWithAuthorization( + acrossInputToken: string, + acrossInputAmount: BigNumberish, + depositData: SwapAndBridgeBase.DepositDataStruct, + validAfter: BigNumberish, + validBefore: BigNumberish, + nonce: BytesLike, + v: BigNumberish, + r: BytesLike, + s: BytesLike, + overrides?: Overrides & { from?: string } + ): Promise; + + depositWithPermit( + acrossInputToken: string, + acrossInputAmount: BigNumberish, + depositData: SwapAndBridgeBase.DepositDataStruct, + deadline: BigNumberish, + v: BigNumberish, + r: BytesLike, + s: BytesLike, + overrides?: Overrides & { from?: string } + ): Promise; + + multicall( + data: BytesLike[], + overrides?: Overrides & { from?: string } + ): Promise; + + swapAndBridge( + swapToken: string, + acrossInputToken: string, + routerCalldata: BytesLike, + swapTokenAmount: BigNumberish, + minExpectedInputTokenAmount: BigNumberish, + depositData: SwapAndBridgeBase.DepositDataStruct, + overrides?: PayableOverrides & { from?: string } + ): Promise; + + swapAndBridgeWithAuthorization( + swapToken: string, + acrossInputToken: string, + routerCalldata: BytesLike, + swapTokenAmount: BigNumberish, + minExpectedInputTokenAmount: BigNumberish, + depositData: SwapAndBridgeBase.DepositDataStruct, + validAfter: BigNumberish, + validBefore: BigNumberish, + nonce: BytesLike, + v: BigNumberish, + r: BytesLike, + s: BytesLike, + overrides?: Overrides & { from?: string } + ): Promise; + + swapAndBridgeWithPermit( + swapToken: string, + acrossInputToken: string, + routerCalldata: BytesLike, + swapTokenAmount: BigNumberish, + minExpectedInputTokenAmount: BigNumberish, + depositData: SwapAndBridgeBase.DepositDataStruct, + deadline: BigNumberish, + v: BigNumberish, + r: BytesLike, + s: BytesLike, + overrides?: Overrides & { from?: string } + ): Promise; + }; +} diff --git a/api/_typechain/SwapAndBridge.sol/index.ts b/api/_typechain/SwapAndBridge.sol/index.ts new file mode 100644 index 000000000..c2a19dda2 --- /dev/null +++ b/api/_typechain/SwapAndBridge.sol/index.ts @@ -0,0 +1,6 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ + +export type { SwapAndBridge } from "./SwapAndBridge"; +export type { SwapAndBridgeBase } from "./SwapAndBridgeBase"; +export type { UniversalSwapAndBridge } from "./UniversalSwapAndBridge"; diff --git a/api/_typechain/factories/SwapAndBridge.sol/SwapAndBridgeBase__factory.ts b/api/_typechain/factories/SwapAndBridge.sol/SwapAndBridgeBase__factory.ts new file mode 100644 index 000000000..39c7908d8 --- /dev/null +++ b/api/_typechain/factories/SwapAndBridge.sol/SwapAndBridgeBase__factory.ts @@ -0,0 +1,153 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ + +import { Contract, Signer, utils } from "ethers"; +import type { Provider } from "@ethersproject/providers"; +import type { + SwapAndBridgeBase, + SwapAndBridgeBaseInterface, +} from "../../SwapAndBridge.sol/SwapAndBridgeBase"; + +const _abi = [ + { + inputs: [], + name: "InvalidFunctionSelector", + type: "error", + }, + { + inputs: [], + name: "LeftoverSrcTokens", + type: "error", + }, + { + inputs: [], + name: "MinimumExpectedInputAmount", + type: "error", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "exchange", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "swapToken", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "acrossInputToken", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "swapTokenAmount", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "acrossInputAmount", + type: "uint256", + }, + { + indexed: true, + internalType: "address", + name: "acrossOutputToken", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "acrossOutputAmount", + type: "uint256", + }, + ], + name: "SwapBeforeBridge", + type: "event", + }, + { + inputs: [], + name: "EXCHANGE", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "SPOKE_POOL", + outputs: [ + { + internalType: "contract V3SpokePoolInterface", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes4", + name: "", + type: "bytes4", + }, + ], + name: "allowedSelectors", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes[]", + name: "data", + type: "bytes[]", + }, + ], + name: "multicall", + outputs: [ + { + internalType: "bytes[]", + name: "results", + type: "bytes[]", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, +] as const; + +export class SwapAndBridgeBase__factory { + static readonly abi = _abi; + static createInterface(): SwapAndBridgeBaseInterface { + return new utils.Interface(_abi) as SwapAndBridgeBaseInterface; + } + static connect( + address: string, + signerOrProvider: Signer | Provider + ): SwapAndBridgeBase { + return new Contract(address, _abi, signerOrProvider) as SwapAndBridgeBase; + } +} diff --git a/api/_typechain/factories/SwapAndBridge.sol/SwapAndBridge__factory.ts b/api/_typechain/factories/SwapAndBridge.sol/SwapAndBridge__factory.ts new file mode 100644 index 000000000..770f17c74 --- /dev/null +++ b/api/_typechain/factories/SwapAndBridge.sol/SwapAndBridge__factory.ts @@ -0,0 +1,367 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ + +import { + Signer, + utils, + Contract, + ContractFactory, + BytesLike, + Overrides, +} from "ethers"; +import type { Provider, TransactionRequest } from "@ethersproject/providers"; +import type { + SwapAndBridge, + SwapAndBridgeInterface, +} from "../../SwapAndBridge.sol/SwapAndBridge"; + +const _abi = [ + { + inputs: [ + { + internalType: "contract V3SpokePoolInterface", + name: "_spokePool", + type: "address", + }, + { + internalType: "contract WETH9Interface", + name: "_wrappedNativeToken", + type: "address", + }, + { + internalType: "address", + name: "_exchange", + type: "address", + }, + { + internalType: "bytes4[]", + name: "_allowedSelectors", + type: "bytes4[]", + }, + { + internalType: "contract IERC20", + name: "_swapToken", + type: "address", + }, + { + internalType: "contract IERC20", + name: "_acrossInputToken", + type: "address", + }, + ], + stateMutability: "nonpayable", + type: "constructor", + }, + { + inputs: [], + name: "InvalidFunctionSelector", + type: "error", + }, + { + inputs: [], + name: "LeftoverSrcTokens", + type: "error", + }, + { + inputs: [], + name: "MinimumExpectedInputAmount", + type: "error", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "exchange", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "swapToken", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "acrossInputToken", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "swapTokenAmount", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "acrossInputAmount", + type: "uint256", + }, + { + indexed: true, + internalType: "address", + name: "acrossOutputToken", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "acrossOutputAmount", + type: "uint256", + }, + ], + name: "SwapBeforeBridge", + type: "event", + }, + { + inputs: [], + name: "ACROSS_INPUT_TOKEN", + outputs: [ + { + internalType: "contract IERC20", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "EXCHANGE", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "SPOKE_POOL", + outputs: [ + { + internalType: "contract V3SpokePoolInterface", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "SWAP_TOKEN", + outputs: [ + { + internalType: "contract IERC20", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes4", + name: "", + type: "bytes4", + }, + ], + name: "allowedSelectors", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes[]", + name: "data", + type: "bytes[]", + }, + ], + name: "multicall", + outputs: [ + { + internalType: "bytes[]", + name: "results", + type: "bytes[]", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes", + name: "routerCalldata", + type: "bytes", + }, + { + internalType: "uint256", + name: "swapTokenAmount", + type: "uint256", + }, + { + internalType: "uint256", + name: "minExpectedInputTokenAmount", + type: "uint256", + }, + { + components: [ + { + internalType: "address", + name: "outputToken", + type: "address", + }, + { + internalType: "uint256", + name: "outputAmount", + type: "uint256", + }, + { + internalType: "address", + name: "depositor", + type: "address", + }, + { + internalType: "address", + name: "recipient", + type: "address", + }, + { + internalType: "uint256", + name: "destinationChainid", + type: "uint256", + }, + { + internalType: "address", + name: "exclusiveRelayer", + type: "address", + }, + { + internalType: "uint32", + name: "quoteTimestamp", + type: "uint32", + }, + { + internalType: "uint32", + name: "fillDeadline", + type: "uint32", + }, + { + internalType: "uint32", + name: "exclusivityDeadline", + type: "uint32", + }, + { + internalType: "bytes", + name: "message", + type: "bytes", + }, + ], + internalType: "struct SwapAndBridgeBase.DepositData", + name: "depositData", + type: "tuple", + }, + ], + name: "swapAndBridge", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, +] as const; + +const _bytecode = + "0x604061012060405234620001d2576200133d803803806200002081620001ea565b92833981019160c082840312620001d25781516001600160a01b03908181168103620001d25760209283850151938385168503620001d25760408601519384168403620001d25760608601516001600160401b039790888111620001d25787019080601f83011215620001d2578151988911620001d6576005918960051b908480620000ae818501620001ea565b809d81520192820101928311620001d2578401905b828210620001b057505050620000ea60a0620000e260808a0162000210565b980162000210565b97600196879660ff19966001885f5416175f5560805260a05260c0525f955b62000174575b888860e05261010090815260405161111791826200022683396080518281816101da0152610faf015260a05182818161041c015281816109600152610d18015260c05182505060e05182818160c9015261082c01525181818161016c015261084e0152f35b8051861015620001aa5786809663ffffffff60e01b8582861b85010151165f52818552855f208288825416179055019562000109565b6200010f565b81516001600160e01b031981168103620001d2578152908401908401620000c3565b5f80fd5b634e487b7160e01b5f52604160045260245ffd5b6040519190601f01601f191682016001600160401b03811183821017620001d657604052565b51906001600160a01b0382168203620001d25756fe60806040526004361015610011575f80fd5b5f3560e01c8063393bb94314610084578063652fa4b91461007f5780638021fef71461007a57806385f168eb14610075578063ac9650d814610070578063b50e44b81461006b5763e65ae3ae14610066575f80fd5b61044f565b6103d2565b61034a565b6101fe565b610190565b610122565b34610114575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101145773ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166080527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8060a0016080f35b5f80fd5b5f91031261011457565b34610114575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261011457602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b34610114575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261011457602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b346101145760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610114576004357fffffffff000000000000000000000000000000000000000000000000000000008116809103610114575f526001602052602060ff60405f2054166040519015158152f35b5f5b8381106102865750505f910152565b8181015183820152602001610277565b602080820190808352835180925260408301928160408460051b8301019501935f915b8483106102c95750505050505090565b909192939495848080837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc086600196030187527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8c5161033681518092818752878088019101610275565b0116010198019301930191949392906102b9565b346101145760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101145767ffffffffffffffff6004358181116101145736602382011215610114578060040135918211610114573660248360051b83010111610114576103ce9160246103c2920161070a565b60405191829182610296565b0390f35b34610114575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261011457602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b90816101409103126101145790565b346101145760807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101145767ffffffffffffffff600435818111610114573660238201121561011457806004013582811161011457366024828401011161011457606435928311610114576104cf6104df933690600401610440565b91604435916024803592016107f1565b005b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b67ffffffffffffffff811161052257604052565b6104e1565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761052257604052565b67ffffffffffffffff81116105225760051b60200190565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610114570180359067ffffffffffffffff82116101145760200191813603831361011457565b90821015610619576106159160051b8101906105ad565b9091565b610580565b908092918237015f815290565b67ffffffffffffffff811161052257601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b3d1561068f573d906106768261062b565b916106846040519384610527565b82523d5f602084013e565b606090565b6020818303126101145780519067ffffffffffffffff8211610114570181601f820112156101145780516106c78161062b565b926106d56040519485610527565b81845260208284010111610114576106f39160208085019101610275565b90565b80518210156106195760209160051b010190565b91909161071683610568565b9060406107266040519384610527565b8483527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061075386610568565b015f5b8181106107e057505082945f5b818110610771575050505050565b5f8061077e8385886105fe565b9061078d87518093819361061e565b0390305af461079a610665565b90156107c057906001916107ae82886106f6565b526107b981876106f6565b5001610763565b604481511061011457806004610114920151602480918301019101610694565b806060602080938801015201610756565b9193909260ff5f5416156101145761082a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff005f54165f55565b7f0000000000000000000000000000000000000000000000000000000000000000927f0000000000000000000000000000000000000000000000000000000000000000946108bc6108b86108b16108818486610a73565b7fffffffff00000000000000000000000000000000000000000000000000000000165f52600160205260405f2090565b5460ff1690565b1590565b610a42576040517f70a082310000000000000000000000000000000000000000000000000000000080825230600483015273ffffffffffffffffffffffffffffffffffffffff98919260209182856024818c8f165afa948515610a1c575f95610a21575b506040519081523060048201529982908b9060249082908d165afa948515610a1c576109ac9a89935f976109dc575b50506109a7925f92838093610986887f00000000000000000000000000000000000000000000000000000000000000008096610afe565b6109956040518094819361061e565b03925af16109a1610665565b50610a6c565b610c29565b6109da60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff005f5416175f55565b565b5f809491819499506109a7969381610a0892903d10610a15575b610a008183610527565b810190610ab7565b989350509281945061094f565b503d6109f6565b610ac6565b83919550610a3b90823d8411610a1557610a008183610527565b9490610920565b60046040517f42868c9b000000000000000000000000000000000000000000000000000000008152fd5b1561011457565b7fffffffff000000000000000000000000000000000000000000000000000000009035818116939260048110610aa857505050565b60040360031b82901b16169150565b90816020910312610114575190565b6040513d5f823e3d90fd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b60449192602073ffffffffffffffffffffffffffffffffffffffff604051948580927fdd62ed3e000000000000000000000000000000000000000000000000000000008252306004830152808916602483015286165afa928315610a1c575f93610bda575b508201809211610bd5576040517f095ea7b300000000000000000000000000000000000000000000000000000000602082015273ffffffffffffffffffffffffffffffffffffffff9390931660248401526044808401929092529082526109da9190610bd0606483610527565b610e02565b610ad1565b610bf491935060203d602011610a1557610a008183610527565b915f610b63565b91908203918211610bd557565b3573ffffffffffffffffffffffffffffffffffffffff811681036101145790565b6040517f70a082310000000000000000000000000000000000000000000000000000000080825230600483015273ffffffffffffffffffffffffffffffffffffffff989697959695602095878b16959294939087826024818a5afa8015610a1c57610c9b925f91610de5575b50610bfb565b978810610dbb576040519384523060048501528916928581602481875afa8015610a1c578392610cd1925f92610d9c5750610bfb565b03610d72576109da977f646284e396b68ff4b4f34e0aa97bcdb9c100f5b44a20da5c475f62703985384191610d6a610d088a610c08565b918960405194859416988c0135917f0000000000000000000000000000000000000000000000000000000000000000859094939260609273ffffffffffffffffffffffffffffffffffffffff6080840197168352602083015260408201520152565b0390a4610f96565b60046040517fd6cf42f0000000000000000000000000000000000000000000000000000000008152fd5b610db4919250883d8a11610a1557610a008183610527565b905f610c95565b60046040517f0492ff87000000000000000000000000000000000000000000000000000000008152fd5b610dfc9150893d8b11610a1557610a008183610527565b5f610c95565b73ffffffffffffffffffffffffffffffffffffffff166040516040810181811067ffffffffffffffff82111761052257610e7d937f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656460205f948594604052818152015260208151910182855af1610e77610665565b916110b8565b8051908115918215610e93575b50501561011457565b819250906020918101031261011457602001518015158103610114575f80610e8a565b3563ffffffff811681036101145790565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe093818652868601375f8582860101520116010190565b989590946106f39d9b9792602095610f889a959c976101809d8d73ffffffffffffffffffffffffffffffffffffffff998a8096818096168452169101521660408d01521660608b015260808a015260a089015260c08801521660e086015263ffffffff8092166101008601521661012084015261014083019063ffffffff169052565b816101608201520191610ec7565b9073ffffffffffffffffffffffffffffffffffffffff807f00000000000000000000000000000000000000000000000000000000000000001692610fdb838583610afe565b610fe760408601610c08565b90610ff460608701610c08565b93610ffe87610c08565b9661100b60a08201610c08565b61101760c08301610eb6565b61102360e08401610eb6565b916110316101008501610eb6565b936110406101208201826105ad565b9790968c3b15610114576040519d8e809d819d7f7b939232000000000000000000000000000000000000000000000000000000008352608087013596602001359516916004019c6110909d610f05565b03815a5f948591f18015610a1c576110a55750565b806110b26109da9261050e565b80610118565b90156110d2578151156110c9575090565b3b156101145790565b50805190811561011457602001fdfea2646970667358221220026a7409d965bcdd82516120169821b365afc3acc0d52608453d28ca5160c46464736f6c63430008170033"; + +type SwapAndBridgeConstructorParams = + | [signer?: Signer] + | ConstructorParameters; + +const isSuperArgs = ( + xs: SwapAndBridgeConstructorParams +): xs is ConstructorParameters => xs.length > 1; + +export class SwapAndBridge__factory extends ContractFactory { + constructor(...args: SwapAndBridgeConstructorParams) { + if (isSuperArgs(args)) { + super(...args); + } else { + super(_abi, _bytecode, args[0]); + } + } + + override deploy( + _spokePool: string, + _wrappedNativeToken: string, + _exchange: string, + _allowedSelectors: BytesLike[], + _swapToken: string, + _acrossInputToken: string, + overrides?: Overrides & { from?: string } + ): Promise { + return super.deploy( + _spokePool, + _wrappedNativeToken, + _exchange, + _allowedSelectors, + _swapToken, + _acrossInputToken, + overrides || {} + ) as Promise; + } + override getDeployTransaction( + _spokePool: string, + _wrappedNativeToken: string, + _exchange: string, + _allowedSelectors: BytesLike[], + _swapToken: string, + _acrossInputToken: string, + overrides?: Overrides & { from?: string } + ): TransactionRequest { + return super.getDeployTransaction( + _spokePool, + _wrappedNativeToken, + _exchange, + _allowedSelectors, + _swapToken, + _acrossInputToken, + overrides || {} + ); + } + override attach(address: string): SwapAndBridge { + return super.attach(address) as SwapAndBridge; + } + override connect(signer: Signer): SwapAndBridge__factory { + return super.connect(signer) as SwapAndBridge__factory; + } + + static readonly bytecode = _bytecode; + static readonly abi = _abi; + static createInterface(): SwapAndBridgeInterface { + return new utils.Interface(_abi) as SwapAndBridgeInterface; + } + static connect( + address: string, + signerOrProvider: Signer | Provider + ): SwapAndBridge { + return new Contract(address, _abi, signerOrProvider) as SwapAndBridge; + } +} diff --git a/api/_typechain/factories/SwapAndBridge.sol/UniversalSwapAndBridge__factory.ts b/api/_typechain/factories/SwapAndBridge.sol/UniversalSwapAndBridge__factory.ts new file mode 100644 index 000000000..740fd1bcf --- /dev/null +++ b/api/_typechain/factories/SwapAndBridge.sol/UniversalSwapAndBridge__factory.ts @@ -0,0 +1,777 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ + +import { + Signer, + utils, + Contract, + ContractFactory, + BytesLike, + Overrides, +} from "ethers"; +import type { Provider, TransactionRequest } from "@ethersproject/providers"; +import type { + UniversalSwapAndBridge, + UniversalSwapAndBridgeInterface, +} from "../../SwapAndBridge.sol/UniversalSwapAndBridge"; + +const _abi = [ + { + inputs: [ + { + internalType: "contract V3SpokePoolInterface", + name: "_spokePool", + type: "address", + }, + { + internalType: "contract WETH9Interface", + name: "_wrappedNativeToken", + type: "address", + }, + { + internalType: "address", + name: "_exchange", + type: "address", + }, + { + internalType: "bytes4[]", + name: "_allowedSelectors", + type: "bytes4[]", + }, + ], + stateMutability: "nonpayable", + type: "constructor", + }, + { + inputs: [], + name: "InsufficientSwapValue", + type: "error", + }, + { + inputs: [], + name: "InvalidFunctionSelector", + type: "error", + }, + { + inputs: [], + name: "InvalidSwapToken", + type: "error", + }, + { + inputs: [], + name: "LeftoverSrcTokens", + type: "error", + }, + { + inputs: [], + name: "MinimumExpectedInputAmount", + type: "error", + }, + { + anonymous: false, + inputs: [ + { + indexed: false, + internalType: "address", + name: "exchange", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "swapToken", + type: "address", + }, + { + indexed: true, + internalType: "address", + name: "acrossInputToken", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "swapTokenAmount", + type: "uint256", + }, + { + indexed: false, + internalType: "uint256", + name: "acrossInputAmount", + type: "uint256", + }, + { + indexed: true, + internalType: "address", + name: "acrossOutputToken", + type: "address", + }, + { + indexed: false, + internalType: "uint256", + name: "acrossOutputAmount", + type: "uint256", + }, + ], + name: "SwapBeforeBridge", + type: "event", + }, + { + inputs: [], + name: "EXCHANGE", + outputs: [ + { + internalType: "address", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [], + name: "SPOKE_POOL", + outputs: [ + { + internalType: "contract V3SpokePoolInterface", + name: "", + type: "address", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes4", + name: "", + type: "bytes4", + }, + ], + name: "allowedSelectors", + outputs: [ + { + internalType: "bool", + name: "", + type: "bool", + }, + ], + stateMutability: "view", + type: "function", + }, + { + inputs: [ + { + internalType: "contract IERC20Auth", + name: "acrossInputToken", + type: "address", + }, + { + internalType: "uint256", + name: "acrossInputAmount", + type: "uint256", + }, + { + components: [ + { + internalType: "address", + name: "outputToken", + type: "address", + }, + { + internalType: "uint256", + name: "outputAmount", + type: "uint256", + }, + { + internalType: "address", + name: "depositor", + type: "address", + }, + { + internalType: "address", + name: "recipient", + type: "address", + }, + { + internalType: "uint256", + name: "destinationChainid", + type: "uint256", + }, + { + internalType: "address", + name: "exclusiveRelayer", + type: "address", + }, + { + internalType: "uint32", + name: "quoteTimestamp", + type: "uint32", + }, + { + internalType: "uint32", + name: "fillDeadline", + type: "uint32", + }, + { + internalType: "uint32", + name: "exclusivityDeadline", + type: "uint32", + }, + { + internalType: "bytes", + name: "message", + type: "bytes", + }, + ], + internalType: "struct SwapAndBridgeBase.DepositData", + name: "depositData", + type: "tuple", + }, + { + internalType: "uint256", + name: "validAfter", + type: "uint256", + }, + { + internalType: "uint256", + name: "validBefore", + type: "uint256", + }, + { + internalType: "bytes32", + name: "nonce", + type: "bytes32", + }, + { + internalType: "uint8", + name: "v", + type: "uint8", + }, + { + internalType: "bytes32", + name: "r", + type: "bytes32", + }, + { + internalType: "bytes32", + name: "s", + type: "bytes32", + }, + ], + name: "depositWithAuthorization", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "contract IERC20Permit", + name: "acrossInputToken", + type: "address", + }, + { + internalType: "uint256", + name: "acrossInputAmount", + type: "uint256", + }, + { + components: [ + { + internalType: "address", + name: "outputToken", + type: "address", + }, + { + internalType: "uint256", + name: "outputAmount", + type: "uint256", + }, + { + internalType: "address", + name: "depositor", + type: "address", + }, + { + internalType: "address", + name: "recipient", + type: "address", + }, + { + internalType: "uint256", + name: "destinationChainid", + type: "uint256", + }, + { + internalType: "address", + name: "exclusiveRelayer", + type: "address", + }, + { + internalType: "uint32", + name: "quoteTimestamp", + type: "uint32", + }, + { + internalType: "uint32", + name: "fillDeadline", + type: "uint32", + }, + { + internalType: "uint32", + name: "exclusivityDeadline", + type: "uint32", + }, + { + internalType: "bytes", + name: "message", + type: "bytes", + }, + ], + internalType: "struct SwapAndBridgeBase.DepositData", + name: "depositData", + type: "tuple", + }, + { + internalType: "uint256", + name: "deadline", + type: "uint256", + }, + { + internalType: "uint8", + name: "v", + type: "uint8", + }, + { + internalType: "bytes32", + name: "r", + type: "bytes32", + }, + { + internalType: "bytes32", + name: "s", + type: "bytes32", + }, + ], + name: "depositWithPermit", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "bytes[]", + name: "data", + type: "bytes[]", + }, + ], + name: "multicall", + outputs: [ + { + internalType: "bytes[]", + name: "results", + type: "bytes[]", + }, + ], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "contract IERC20", + name: "swapToken", + type: "address", + }, + { + internalType: "contract IERC20", + name: "acrossInputToken", + type: "address", + }, + { + internalType: "bytes", + name: "routerCalldata", + type: "bytes", + }, + { + internalType: "uint256", + name: "swapTokenAmount", + type: "uint256", + }, + { + internalType: "uint256", + name: "minExpectedInputTokenAmount", + type: "uint256", + }, + { + components: [ + { + internalType: "address", + name: "outputToken", + type: "address", + }, + { + internalType: "uint256", + name: "outputAmount", + type: "uint256", + }, + { + internalType: "address", + name: "depositor", + type: "address", + }, + { + internalType: "address", + name: "recipient", + type: "address", + }, + { + internalType: "uint256", + name: "destinationChainid", + type: "uint256", + }, + { + internalType: "address", + name: "exclusiveRelayer", + type: "address", + }, + { + internalType: "uint32", + name: "quoteTimestamp", + type: "uint32", + }, + { + internalType: "uint32", + name: "fillDeadline", + type: "uint32", + }, + { + internalType: "uint32", + name: "exclusivityDeadline", + type: "uint32", + }, + { + internalType: "bytes", + name: "message", + type: "bytes", + }, + ], + internalType: "struct SwapAndBridgeBase.DepositData", + name: "depositData", + type: "tuple", + }, + ], + name: "swapAndBridge", + outputs: [], + stateMutability: "payable", + type: "function", + }, + { + inputs: [ + { + internalType: "contract IERC20Auth", + name: "swapToken", + type: "address", + }, + { + internalType: "contract IERC20", + name: "acrossInputToken", + type: "address", + }, + { + internalType: "bytes", + name: "routerCalldata", + type: "bytes", + }, + { + internalType: "uint256", + name: "swapTokenAmount", + type: "uint256", + }, + { + internalType: "uint256", + name: "minExpectedInputTokenAmount", + type: "uint256", + }, + { + components: [ + { + internalType: "address", + name: "outputToken", + type: "address", + }, + { + internalType: "uint256", + name: "outputAmount", + type: "uint256", + }, + { + internalType: "address", + name: "depositor", + type: "address", + }, + { + internalType: "address", + name: "recipient", + type: "address", + }, + { + internalType: "uint256", + name: "destinationChainid", + type: "uint256", + }, + { + internalType: "address", + name: "exclusiveRelayer", + type: "address", + }, + { + internalType: "uint32", + name: "quoteTimestamp", + type: "uint32", + }, + { + internalType: "uint32", + name: "fillDeadline", + type: "uint32", + }, + { + internalType: "uint32", + name: "exclusivityDeadline", + type: "uint32", + }, + { + internalType: "bytes", + name: "message", + type: "bytes", + }, + ], + internalType: "struct SwapAndBridgeBase.DepositData", + name: "depositData", + type: "tuple", + }, + { + internalType: "uint256", + name: "validAfter", + type: "uint256", + }, + { + internalType: "uint256", + name: "validBefore", + type: "uint256", + }, + { + internalType: "bytes32", + name: "nonce", + type: "bytes32", + }, + { + internalType: "uint8", + name: "v", + type: "uint8", + }, + { + internalType: "bytes32", + name: "r", + type: "bytes32", + }, + { + internalType: "bytes32", + name: "s", + type: "bytes32", + }, + ], + name: "swapAndBridgeWithAuthorization", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, + { + inputs: [ + { + internalType: "contract IERC20Permit", + name: "swapToken", + type: "address", + }, + { + internalType: "contract IERC20", + name: "acrossInputToken", + type: "address", + }, + { + internalType: "bytes", + name: "routerCalldata", + type: "bytes", + }, + { + internalType: "uint256", + name: "swapTokenAmount", + type: "uint256", + }, + { + internalType: "uint256", + name: "minExpectedInputTokenAmount", + type: "uint256", + }, + { + components: [ + { + internalType: "address", + name: "outputToken", + type: "address", + }, + { + internalType: "uint256", + name: "outputAmount", + type: "uint256", + }, + { + internalType: "address", + name: "depositor", + type: "address", + }, + { + internalType: "address", + name: "recipient", + type: "address", + }, + { + internalType: "uint256", + name: "destinationChainid", + type: "uint256", + }, + { + internalType: "address", + name: "exclusiveRelayer", + type: "address", + }, + { + internalType: "uint32", + name: "quoteTimestamp", + type: "uint32", + }, + { + internalType: "uint32", + name: "fillDeadline", + type: "uint32", + }, + { + internalType: "uint32", + name: "exclusivityDeadline", + type: "uint32", + }, + { + internalType: "bytes", + name: "message", + type: "bytes", + }, + ], + internalType: "struct SwapAndBridgeBase.DepositData", + name: "depositData", + type: "tuple", + }, + { + internalType: "uint256", + name: "deadline", + type: "uint256", + }, + { + internalType: "uint8", + name: "v", + type: "uint8", + }, + { + internalType: "bytes32", + name: "r", + type: "bytes32", + }, + { + internalType: "bytes32", + name: "s", + type: "bytes32", + }, + ], + name: "swapAndBridgeWithPermit", + outputs: [], + stateMutability: "nonpayable", + type: "function", + }, +] as const; + +const _bytecode = + "0x604060e060405234620001905762001b2390813803806200002081620001a8565b9384398201608083820312620001905782516001600160a01b03929091908383168303620001905760209485810151958587168703620001905760408201519586168603620001905760608201516001600160401b03928382116200019057019380601f860112156200019057845192831162000194576005948360051b908380620000ae818501620001a8565b80978152019282010192831162000190578301905b8282106200016e57505050600196879660ff19966001885f5416175f5560805260a05260c0525f955b62000132575b6040516119549081620001cf82396080518181816102fb0152611418015260a05181818161053d015281816111d20152611757015260c051816106c70152f35b8151861015620001685786809663ffffffff60e01b8382881b86010151165f52818352845f2082888254161790550195620000ec565b620000f2565b81516001600160e01b03198116810362000190578152908301908301620000c3565b5f80fd5b634e487b7160e01b5f52604160045260245ffd5b6040519190601f01601f191682016001600160401b03811183821017620001945760405256fe60806040526004361015610011575f80fd5b5f3560e01c8063038f12ea146100a4578063277deffe1461009f5780638021fef71461009a57806385f168eb14610095578063ac9650d814610090578063b50e44b81461008b578063bdf52ad314610086578063c51e5eb9146100815763fdf152d31461007c575f80fd5b6107f6565b6105ee565b610561565b6104f3565b61046b565b61031f565b6102b1565b6101ff565b34610153576101807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610153576100dc610175565b6100e4610184565b67ffffffffffffffff919060443583811161015357610107903690600401610191565b9260a435948511610153576101236101519536906004016101bf565b9361012c6101ce565b9261016435956101443595610104359460e4359460c4359460843593606435936109d4565b005b5f80fd5b73ffffffffffffffffffffffffffffffffffffffff81160361015357565b6004359061018282610157565b565b6024359061018282610157565b9181601f840112156101535782359167ffffffffffffffff8311610153576020838186019501011161015357565b90816101409103126101535790565b610124359060ff8216820361015357565b60e4359060ff8216820361015357565b6084359060ff8216820361015357565b34610153576101407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101535760043561023b81610157565b610243610184565b67ffffffffffffffff919060443583811161015357610266903690600401610191565b919060a435948511610153576102836101519536906004016101bf565b61028b6101df565b926101243595610104359560c435946084359360643593610b86565b5f91031261015357565b34610153575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015357602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b346101535760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610153576004357fffffffff000000000000000000000000000000000000000000000000000000008116809103610153575f526001602052602060ff60405f2054166040519015158152f35b5f5b8381106103a75750505f910152565b8181015183820152602001610398565b602080820190808352835180925260408301928160408460051b8301019501935f915b8483106103ea5750505050505090565b909192939495848080837fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc086600196030187527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8c5161045781518092818752878088019101610396565b0116010198019301930191949392906103da565b346101535760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101535767ffffffffffffffff6004358181116101535736602382011215610153578060040135918211610153573660248360051b83010111610153576104ef9160246104e39201610eab565b604051918291826103b7565b0390f35b34610153575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261015357602060405173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b34610153576101207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101535760043561059d81610157565b60443567ffffffffffffffff8111610153576105bd9036906004016101bf565b9060c4359160ff831683036101535761015192610104359260e4359260a43591608435916064359160243590610f92565b60c07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc360112610153576004803561062581610157565b6024359061063282610157565b67ffffffffffffffff604435818111610153576106529036908601610191565b916064359060a4359081116101535761066e90369088016101bf565b92610677611089565b6106a27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff005f54165f55565b34156107e0578134036107b75773ffffffffffffffffffffffffffffffffffffffff807f000000000000000000000000000000000000000000000000000000000000000016809187160361078e57803b15610153575f90604051988980927fd0e30db000000000000000000000000000000000000000000000000000000000825234905af19687156107895761074297610770575b505b608435926110d9565b61015160017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff005f5416175f55565b8061077d61078392610b21565b806102a7565b5f610737565b610b7b565b876040517f3539a701000000000000000000000000000000000000000000000000000000008152fd5b866040517ff143e0da000000000000000000000000000000000000000000000000000000008152fd5b61074296506107f182303388611299565b610739565b346101535760e07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101535760043561083181610157565b60243560443567ffffffffffffffff8111610153576108549036906004016101bf565b9073ffffffffffffffffffffffffffffffffffffffff6108726101ef565b9361087b611089565b6108a67fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff005f54165f55565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152911690602081604481855afa80156107895783915f916109a5575b5010610910575b610742935061090b82303384611299565b6113ff565b803b15610153576040517fd505accf00000000000000000000000000000000000000000000000000000000815233600482015230602482015260448101839052606480359082015260ff94909416608485015260a480359085015260c48035908501525f8460e48183855af19384156107895761074294610992575b506108fa565b8061077d61099f92610b21565b5f61098c565b6109c7915060203d6020116109cd575b6109bf8183610b3a565b810190610cfa565b5f6108f3565b503d6109b5565b73ffffffffffffffffffffffffffffffffffffffff909c9a919b94979295989396999c6109ff611089565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff005f54165f5516998a3b15610153576040517fef55bec6000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018990526064810193909352608483019390935260a482019b909b5260ff909a1660c48b015260e48a01919091526101048901525f8861012481838a5af197881561078957610ab798610ae5575b506110d9565b61018260017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff005f5416175f55565b610aee90610b21565b5f610ab1565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b67ffffffffffffffff8111610b3557604052565b610af4565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117610b3557604052565b6040513d5f823e3d90fd5b73ffffffffffffffffffffffffffffffffffffffff909a9293949596979891999a610baf611089565b610bda7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff005f54165f55565b6040517fdd62ed3e000000000000000000000000000000000000000000000000000000008152336004820152306024820152911698906020816044818d5afa80156107895787915f91610cdb575b5010610c48575b505050610ab79750610c4383303389611299565b6110d9565b883b15610153576040517fd505accf00000000000000000000000000000000000000000000000000000000815233600482015230602482015260448101879052606481019190915260ff91909116608482015260a481019990995260c48901525f8860e481838a5af197881561078957610ab798610cc8575b8080610c2f565b8061077d610cd592610b21565b5f610cc1565b610cf4915060203d6020116109cd576109bf8183610b3a565b5f610c28565b90816020910312610153575190565b67ffffffffffffffff8111610b355760051b60200190565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe181360301821215610153570180359067ffffffffffffffff82116101535760200191813603831361015357565b90821015610dba57610db69160051b810190610d4e565b9091565b610d21565b908092918237015f815290565b67ffffffffffffffff8111610b3557601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b3d15610e30573d90610e1782610dcc565b91610e256040519384610b3a565b82523d5f602084013e565b606090565b6020818303126101535780519067ffffffffffffffff8211610153570181601f82011215610153578051610e6881610dcc565b92610e766040519485610b3a565b8184526020828401011161015357610e949160208085019101610396565b90565b8051821015610dba5760209160051b010190565b919091610eb783610d09565b906040610ec76040519384610b3a565b8483527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0610ef486610d09565b015f5b818110610f8157505082945f5b818110610f12575050505050565b5f80610f1f838588610d9f565b90610f2e875180938193610dbf565b0390305af4610f3b610e06565b9015610f615790600191610f4f8288610e97565b52610f5a8187610e97565b5001610f04565b604481511061015357806004610153920151602480918301019101610e35565b806060602080938801015201610ef7565b73ffffffffffffffffffffffffffffffffffffffff909895989794939297969196610fbb611089565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff005f54165f551694853b15610153576040517fef55bec6000000000000000000000000000000000000000000000000000000008152336004820152306024820152604481018890526064810193909352608483019390935260a482019790975260ff90961660c487015260e48601919091526101048501525f846101248183855af193841561078957610ab794611073575b506113ff565b61107c90610b21565b5f61106d565b1561015357565b60ff5f54161561015357565b7fffffffff0000000000000000000000000000000000000000000000000000000090358181169392600481106110ca57505050565b60040360031b82901b16169150565b9095949392919561112e61112a6111236110f38486611095565b7fffffffff00000000000000000000000000000000000000000000000000000000165f52600160205260405f2090565b5460ff1690565b1590565b61126f576040517f70a082310000000000000000000000000000000000000000000000000000000080825230600483015273ffffffffffffffffffffffffffffffffffffffff98919260209182856024818c8f165afa948515610789575f9561124e575b506040519081523060048201529982908b9060249082908d165afa948515610789576101829a89935f9761121e575b5050611219925f928380936111f8887f00000000000000000000000000000000000000000000000000000000000000008096611548565b61120760405180948193610dbf565b03925af1611213610e06565b50611082565b611668565b5f8094918194995061121996938161124192903d106109cd576109bf8183610b3a565b98935050928194506111c1565b8391955061126890823d84116109cd576109bf8183610b3a565b9490611192565b60046040517f42868c9b000000000000000000000000000000000000000000000000000000008152fd5b9290604051927f23b872dd00000000000000000000000000000000000000000000000000000000602085015273ffffffffffffffffffffffffffffffffffffffff809216602485015216604483015260648201526064815260a081019181831067ffffffffffffffff841117610b355761018292604052611841565b35610e9481610157565b3563ffffffff811681036101535790565b601f82602094937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe093818652868601375f8582860101520116010190565b98959094610e949d9b97926020956113f19a959c976101809d8d73ffffffffffffffffffffffffffffffffffffffff998a8096818096168452169101521660408d01521660608b015260808a015260a089015260c08801521660e086015263ffffffff8092166101008601521661012084015261014083019063ffffffff169052565b816101608201520191611330565b9073ffffffffffffffffffffffffffffffffffffffff807f00000000000000000000000000000000000000000000000000000000000000001692611444838583611548565b61145060408601611315565b9061145d60608701611315565b9361146787611315565b9661147460a08201611315565b61148060c0830161131f565b61148c60e0840161131f565b9161149a610100850161131f565b936114a9610120820182610d4e565b9790968c3b15610153576040519d8e809d819d7f7b939232000000000000000000000000000000000000000000000000000000008352608087013596602001359516916004019c6114f99d61136e565b03815a5f948591f180156107895761150e5750565b8061077d61018292610b21565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b6040517fdd62ed3e00000000000000000000000000000000000000000000000000000000815230600482015273ffffffffffffffffffffffffffffffffffffffff8316602482015291926020838060448101038173ffffffffffffffffffffffffffffffffffffffff86165afa928315610789575f9361163a575b508201809211611635576040517f095ea7b300000000000000000000000000000000000000000000000000000000602082015273ffffffffffffffffffffffffffffffffffffffff9390931660248401526044808401929092529082526101829190611630606483610b3a565b611841565b61151b565b61165491935060203d6020116109cd576109bf8183610b3a565b915f6115c3565b9190820391821161163557565b6040517f70a082310000000000000000000000000000000000000000000000000000000080825230600483015273ffffffffffffffffffffffffffffffffffffffff989697959695602095878b16959294939087826024818a5afa8015610789576116da925f91611824575b5061165b565b9788106117fa576040519384523060048501528916928581602481875afa8015610789578392611710925f926117db575061165b565b036117b157610182977f646284e396b68ff4b4f34e0aa97bcdb9c100f5b44a20da5c475f627039853841916117a96117478a611315565b918960405194859416988c0135917f0000000000000000000000000000000000000000000000000000000000000000859094939260609273ffffffffffffffffffffffffffffffffffffffff6080840197168352602083015260408201520152565b0390a46113ff565b60046040517fd6cf42f0000000000000000000000000000000000000000000000000000000008152fd5b6117f3919250883d8a116109cd576109bf8183610b3a565b905f6116d4565b60046040517f0492ff87000000000000000000000000000000000000000000000000000000008152fd5b61183b9150893d8b116109cd576109bf8183610b3a565b5f6116d4565b73ffffffffffffffffffffffffffffffffffffffff166040516040810181811067ffffffffffffffff821117610b35576118bc937f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656460205f948594604052818152015260208151910182855af16118b6610e06565b916118f5565b80519081159182156118d2575b50501561015357565b819250906020918101031261015357602001518015158103610153575f806118c9565b901561190f57815115611906575090565b3b156101535790565b50805190811561015357602001fdfea264697066735822122066b7197a155308805fbedee5c26980493cce360e5c829be686db3534152c74bf64736f6c63430008170033"; + +type UniversalSwapAndBridgeConstructorParams = + | [signer?: Signer] + | ConstructorParameters; + +const isSuperArgs = ( + xs: UniversalSwapAndBridgeConstructorParams +): xs is ConstructorParameters => xs.length > 1; + +export class UniversalSwapAndBridge__factory extends ContractFactory { + constructor(...args: UniversalSwapAndBridgeConstructorParams) { + if (isSuperArgs(args)) { + super(...args); + } else { + super(_abi, _bytecode, args[0]); + } + } + + override deploy( + _spokePool: string, + _wrappedNativeToken: string, + _exchange: string, + _allowedSelectors: BytesLike[], + overrides?: Overrides & { from?: string } + ): Promise { + return super.deploy( + _spokePool, + _wrappedNativeToken, + _exchange, + _allowedSelectors, + overrides || {} + ) as Promise; + } + override getDeployTransaction( + _spokePool: string, + _wrappedNativeToken: string, + _exchange: string, + _allowedSelectors: BytesLike[], + overrides?: Overrides & { from?: string } + ): TransactionRequest { + return super.getDeployTransaction( + _spokePool, + _wrappedNativeToken, + _exchange, + _allowedSelectors, + overrides || {} + ); + } + override attach(address: string): UniversalSwapAndBridge { + return super.attach(address) as UniversalSwapAndBridge; + } + override connect(signer: Signer): UniversalSwapAndBridge__factory { + return super.connect(signer) as UniversalSwapAndBridge__factory; + } + + static readonly bytecode = _bytecode; + static readonly abi = _abi; + static createInterface(): UniversalSwapAndBridgeInterface { + return new utils.Interface(_abi) as UniversalSwapAndBridgeInterface; + } + static connect( + address: string, + signerOrProvider: Signer | Provider + ): UniversalSwapAndBridge { + return new Contract( + address, + _abi, + signerOrProvider + ) as UniversalSwapAndBridge; + } +} diff --git a/api/_typechain/factories/SwapAndBridge.sol/index.ts b/api/_typechain/factories/SwapAndBridge.sol/index.ts new file mode 100644 index 000000000..74ba6aa0d --- /dev/null +++ b/api/_typechain/factories/SwapAndBridge.sol/index.ts @@ -0,0 +1,6 @@ +/* Autogenerated file. Do not edit manually. */ +/* tslint:disable */ + +export { SwapAndBridge__factory } from "./SwapAndBridge__factory"; +export { SwapAndBridgeBase__factory } from "./SwapAndBridgeBase__factory"; +export { UniversalSwapAndBridge__factory } from "./UniversalSwapAndBridge__factory"; diff --git a/api/_utils.ts b/api/_utils.ts index 7b43e9b08..3cb83e825 100644 --- a/api/_utils.ts +++ b/api/_utils.ts @@ -346,6 +346,14 @@ function getStaticIsContract(chainId: number, address: string) { return !!deployedAcrossContract; } +export function getWrappedNativeTokenAddress(chainId: number) { + if (chainId === CHAIN_IDs.POLYGON || chainId === CHAIN_IDs.POLYGON_AMOY) { + return TOKEN_SYMBOLS_MAP.WMATIC.addresses[chainId]; + } + + return TOKEN_SYMBOLS_MAP.WETH.addresses[chainId]; +} + /** * Utility function to resolve route details based on given `inputTokenAddress` and `destinationChainId`. * The optional parameter `originChainId` can be omitted if the `inputTokenAddress` is unique across all diff --git a/api/swap.ts b/api/swap.ts index 93b98e949..331725fcb 100644 --- a/api/swap.ts +++ b/api/swap.ts @@ -1,6 +1,6 @@ import { VercelResponse } from "@vercel/node"; import { assert, Infer, type, string, optional } from "superstruct"; -import { BigNumber } from "ethers"; +import { BigNumber, constants, utils } from "ethers"; import { TypedVercelRequest } from "./_types"; import { @@ -11,6 +11,7 @@ import { validAddress, boolStr, getCachedTokenInfo, + getWrappedNativeTokenAddress, } from "./_utils"; import { AMOUNT_TYPE, @@ -22,6 +23,7 @@ import { isValidIntegratorId } from "./_integrator-id"; const SwapQueryParamsSchema = type({ minOutputAmount: optional(positiveIntStr()), + exactOutputAmount: optional(positiveIntStr()), exactInputAmount: optional(positiveIntStr()), inputToken: validAddress(), outputToken: validAddress(), @@ -55,6 +57,7 @@ const handler = async ( outputToken: _outputTokenAddress, exactInputAmount: _exactInputAmount, minOutputAmount: _minOutputAmount, + exactOutputAmount: _exactOutputAmount, originChainId: _originChainId, destinationChainId: _destinationChainId, recipient, @@ -68,19 +71,34 @@ const handler = async ( const originChainId = Number(_originChainId); const destinationChainId = Number(_destinationChainId); const refundOnOrigin = _refundOnOrigin === "true"; - - if (!_minOutputAmount && !_exactInputAmount) { + const isInputNative = _inputTokenAddress === constants.AddressZero; + const isOutputNative = _outputTokenAddress === constants.AddressZero; + const inputTokenAddress = isInputNative + ? getWrappedNativeTokenAddress(originChainId) + : utils.getAddress(_inputTokenAddress); + const outputTokenAddress = isOutputNative + ? getWrappedNativeTokenAddress(destinationChainId) + : utils.getAddress(_outputTokenAddress); + + if (!_minOutputAmount && !_exactInputAmount && !_exactOutputAmount) { throw new MissingParamError({ - param: "minOutputAmount, exactInputAmount", - message: "One of 'minOutputAmount' or 'exactInputAmount' is required", + param: "minOutputAmount, exactInputAmount, exactOutputAmount", + message: + "One of 'minOutputAmount', 'exactInputAmount' or 'exactOutputAmount' is required", }); } - if (_minOutputAmount && _exactInputAmount) { + if (integratorId && !isValidIntegratorId(integratorId)) { throw new InvalidParamError({ - param: "minOutputAmount, exactInputAmount", - message: - "Only one of 'minOutputAmount' or 'exactInputAmount' is allowed", + param: "integratorId", + message: "Invalid integrator ID. Needs to be 2 bytes hex string.", + }); + } + + if (!inputTokenAddress || !outputTokenAddress) { + throw new InvalidParamError({ + param: "inputToken, outputToken", + message: "Invalid input or output token address", }); } @@ -93,21 +111,21 @@ const handler = async ( const amountType = _minOutputAmount ? AMOUNT_TYPE.MIN_OUTPUT - : AMOUNT_TYPE.EXACT_INPUT; + : _exactInputAmount + ? AMOUNT_TYPE.EXACT_INPUT + : AMOUNT_TYPE.EXACT_OUTPUT; const amount = BigNumber.from( - amountType === AMOUNT_TYPE.EXACT_INPUT - ? _exactInputAmount - : _minOutputAmount + _minOutputAmount || _exactInputAmount || _exactOutputAmount ); // 1. Get token details const [inputToken, outputToken] = await Promise.all([ getCachedTokenInfo({ - address: _inputTokenAddress, + address: inputTokenAddress, chainId: originChainId, }), getCachedTokenInfo({ - address: _outputTokenAddress, + address: outputTokenAddress, chainId: destinationChainId, }), ]); @@ -123,8 +141,8 @@ const handler = async ( type: amountType, refundOnOrigin, refundAddress, - // @TODO: Make this configurable via env var or query param - leftoverType: "bridgeableToken", + isInputNative, + isOutputNative, }); // 3. Build cross swap tx diff --git a/scripts/generate-routes.ts b/scripts/generate-routes.ts index af2bf0da3..fb6354cc2 100644 --- a/scripts/generate-routes.ts +++ b/scripts/generate-routes.ts @@ -97,10 +97,10 @@ const enabledRoutes = { [CHAIN_IDs.BASE]: "0x98285D11B9F7aFec2d475805E5255f26B4490167", }, uniswap: { - [CHAIN_IDs.POLYGON]: "0xa55490E20057BD4775618D0FC8D51F59f602FED0", - [CHAIN_IDs.OPTIMISM]: "0x04989eaF03547E6583f9d9e42aeD11D2b78A808b", - [CHAIN_IDs.ARBITRUM]: "0x2414A759d4EFF700Ad81e257Ab5187d07eCeEbAb", - [CHAIN_IDs.BASE]: "0xed8b9c9aE7aCEf12eb4650d26Eb876005a4752d2", + [CHAIN_IDs.POLYGON]: "0xC2dCB88873E00c9d401De2CBBa4C6A28f8A6e2c2", + [CHAIN_IDs.OPTIMISM]: "0x28249CD61170Ed200Db8988D7f69e21331AFFBD0", + [CHAIN_IDs.ARBITRUM]: "0x07b64BE6906A78fac5FaB47cD58d59D0A093B15e", + [CHAIN_IDs.BASE]: "0xef5a54BEeBDB4Ee98E2906e30e65AD53dA8D2b17", }, }, routes: transformChainConfigs(enabledMainnetChainConfigs), diff --git a/scripts/tests/swap.ts b/scripts/tests/swap.ts index e3f40fd34..e7a01ef20 100644 --- a/scripts/tests/swap.ts +++ b/scripts/tests/swap.ts @@ -13,58 +13,170 @@ const depositor = "0x9A8f92a830A5cB89a3816e3D267CB7791c16b04D"; const MIN_OUTPUT_CASES = [ // B2B { - label: "B2B", - minOutputAmount: ethers.utils.parseUnits("1", 6).toString(), - inputToken: TOKEN_SYMBOLS_MAP.USDC.addresses[CHAIN_IDs.BASE], - originChainId: CHAIN_IDs.BASE, - outputToken: TOKEN_SYMBOLS_MAP.USDC.addresses[CHAIN_IDs.ARBITRUM], - destinationChainId: CHAIN_IDs.ARBITRUM, - depositor, + labels: ["B2B", "MIN_OUTPUT", "Base USDC", "Arbitrum USDC"], + params: { + minOutputAmount: ethers.utils.parseUnits("1", 6).toString(), + inputToken: TOKEN_SYMBOLS_MAP.USDC.addresses[CHAIN_IDs.BASE], + originChainId: CHAIN_IDs.BASE, + outputToken: TOKEN_SYMBOLS_MAP.USDC.addresses[CHAIN_IDs.ARBITRUM], + destinationChainId: CHAIN_IDs.ARBITRUM, + depositor, + }, + }, + { + labels: ["B2B", "MIN_OUTPUT", "Base USDC", "Arbitrum ETH"], + params: { + minOutputAmount: ethers.utils.parseUnits("0.001", 18).toString(), + inputToken: TOKEN_SYMBOLS_MAP.USDC.addresses[CHAIN_IDs.BASE], + originChainId: CHAIN_IDs.BASE, + outputToken: ethers.constants.AddressZero, + destinationChainId: CHAIN_IDs.ARBITRUM, + depositor, + }, }, // B2A { - label: "B2A", - minOutputAmount: ethers.utils.parseUnits("1", 18).toString(), - inputToken: TOKEN_SYMBOLS_MAP.USDC.addresses[CHAIN_IDs.BASE], - originChainId: CHAIN_IDs.BASE, - outputToken: "0x74885b4D524d497261259B38900f54e6dbAd2210", // APE Coin - destinationChainId: CHAIN_IDs.ARBITRUM, - depositor, + labels: ["B2A", "MIN_OUTPUT", "Base USDC", "Arbitrum WETH"], + params: { + minOutputAmount: ethers.utils.parseUnits("0.001", 18).toString(), + inputToken: TOKEN_SYMBOLS_MAP.USDC.addresses[CHAIN_IDs.BASE], + originChainId: CHAIN_IDs.BASE, + outputToken: TOKEN_SYMBOLS_MAP.WETH.addresses[CHAIN_IDs.ARBITRUM], + destinationChainId: CHAIN_IDs.ARBITRUM, + depositor, + }, + }, + { + labels: ["B2A", "MIN_OUTPUT", "Base USDC", "Arbitrum ETH"], + params: { + minOutputAmount: ethers.utils.parseUnits("0.001", 18).toString(), + inputToken: TOKEN_SYMBOLS_MAP.USDC.addresses[CHAIN_IDs.BASE], + originChainId: CHAIN_IDs.BASE, + outputToken: ethers.constants.AddressZero, + destinationChainId: CHAIN_IDs.ARBITRUM, + depositor, + }, + }, + // A2B + { + labels: ["A2B", "MIN_OUTPUT", "Base USDbC", "Arbitrum USDC"], + params: { + minOutputAmount: ethers.utils.parseUnits("1", 6).toString(), + inputToken: TOKEN_SYMBOLS_MAP.USDbC.addresses[CHAIN_IDs.BASE], + originChainId: CHAIN_IDs.BASE, + outputToken: TOKEN_SYMBOLS_MAP.USDC.addresses[CHAIN_IDs.ARBITRUM], + destinationChainId: CHAIN_IDs.ARBITRUM, + depositor, + }, + }, + // A2A + { + labels: ["A2A", "MIN_OUTPUT", "Base USDbC", "Arbitrum APE"], + params: { + minOutputAmount: ethers.utils.parseUnits("1", 18).toString(), + inputToken: TOKEN_SYMBOLS_MAP.USDbC.addresses[CHAIN_IDs.BASE], + originChainId: CHAIN_IDs.BASE, + outputToken: "0x74885b4D524d497261259B38900f54e6dbAd2210", // APE Coin + destinationChainId: CHAIN_IDs.ARBITRUM, + depositor, + }, + }, +]; +const EXACT_OUTPUT_CASES = [ + // B2B + { + labels: ["B2B", "EXACT_OUTPUT", "Base USDC", "Arbitrum USDC"], + params: { + exactOutputAmount: ethers.utils.parseUnits("1", 6).toString(), + inputToken: TOKEN_SYMBOLS_MAP.USDC.addresses[CHAIN_IDs.BASE], + originChainId: CHAIN_IDs.BASE, + outputToken: TOKEN_SYMBOLS_MAP.USDC.addresses[CHAIN_IDs.ARBITRUM], + destinationChainId: CHAIN_IDs.ARBITRUM, + depositor, + }, + }, + { + labels: ["B2B", "EXACT_OUTPUT", "Base USDC", "Arbitrum ETH"], + params: { + exactOutputAmount: ethers.utils.parseUnits("0.001", 18).toString(), + inputToken: TOKEN_SYMBOLS_MAP.USDC.addresses[CHAIN_IDs.BASE], + originChainId: CHAIN_IDs.BASE, + outputToken: ethers.constants.AddressZero, + destinationChainId: CHAIN_IDs.ARBITRUM, + depositor, + }, + }, + // B2A + { + labels: ["B2A", "EXACT_OUTPUT", "Base USDC", "Arbitrum WETH"], + params: { + exactOutputAmount: ethers.utils.parseUnits("0.001", 18).toString(), + inputToken: TOKEN_SYMBOLS_MAP.USDC.addresses[CHAIN_IDs.BASE], + originChainId: CHAIN_IDs.BASE, + outputToken: TOKEN_SYMBOLS_MAP.WETH.addresses[CHAIN_IDs.ARBITRUM], + destinationChainId: CHAIN_IDs.ARBITRUM, + depositor, + }, + }, + { + labels: ["B2A", "EXACT_OUTPUT", "Base USDC", "Arbitrum ETH"], + params: { + exactOutputAmount: ethers.utils.parseUnits("0.001", 18).toString(), + inputToken: TOKEN_SYMBOLS_MAP.USDC.addresses[CHAIN_IDs.BASE], + originChainId: CHAIN_IDs.BASE, + outputToken: ethers.constants.AddressZero, + destinationChainId: CHAIN_IDs.ARBITRUM, + depositor, + }, }, // A2B { - label: "A2B", - minOutputAmount: ethers.utils.parseUnits("1", 6).toString(), - inputToken: TOKEN_SYMBOLS_MAP.USDbC.addresses[CHAIN_IDs.BASE], - originChainId: CHAIN_IDs.BASE, - outputToken: TOKEN_SYMBOLS_MAP.USDC.addresses[CHAIN_IDs.ARBITRUM], - destinationChainId: CHAIN_IDs.ARBITRUM, - depositor, + labels: ["A2B", "EXACT_OUTPUT", "Base USDbC", "Arbitrum USDC"], + params: { + minOutputAmount: ethers.utils.parseUnits("1", 6).toString(), + inputToken: TOKEN_SYMBOLS_MAP.USDbC.addresses[CHAIN_IDs.BASE], + originChainId: CHAIN_IDs.BASE, + outputToken: TOKEN_SYMBOLS_MAP.USDC.addresses[CHAIN_IDs.ARBITRUM], + destinationChainId: CHAIN_IDs.ARBITRUM, + depositor, + }, }, // A2A { - label: "A2A", - minOutputAmount: ethers.utils.parseUnits("1", 18).toString(), - inputToken: TOKEN_SYMBOLS_MAP.USDbC.addresses[CHAIN_IDs.BASE], - originChainId: CHAIN_IDs.BASE, - outputToken: "0x74885b4D524d497261259B38900f54e6dbAd2210", // APE Coin - destinationChainId: CHAIN_IDs.ARBITRUM, - depositor, - slippageTolerance: 1, + labels: ["A2A", "EXACT_OUTPUT", "Base USDbC", "Arbitrum APE"], + params: { + minOutputAmount: ethers.utils.parseUnits("1", 18).toString(), + inputToken: TOKEN_SYMBOLS_MAP.USDbC.addresses[CHAIN_IDs.BASE], + originChainId: CHAIN_IDs.BASE, + outputToken: "0x74885b4D524d497261259B38900f54e6dbAd2210", // APE Coin + destinationChainId: CHAIN_IDs.ARBITRUM, + depositor, + }, }, ]; async function swap() { - for (const testCase of MIN_OUTPUT_CASES) { - console.log("\nTest case:", testCase.label); + const filterString = process.argv[2]; + const testCases = [...MIN_OUTPUT_CASES, ...EXACT_OUTPUT_CASES]; + const labelsToFilter = filterString ? filterString.split(",") : []; + const filteredTestCases = testCases.filter((testCase) => { + const matches = labelsToFilter.filter((label) => + testCase.labels + .map((label) => label.toLowerCase()) + .includes(label.toLowerCase()) + ); + return matches.length === labelsToFilter.length; + }); + for (const testCase of filteredTestCases) { + console.log("\nTest case:", testCase.labels.join(" ")); const response = await axios.get(`http://localhost:3000/api/swap`, { - params: testCase, + params: testCase.params, }); console.log(response.data); if (process.env.DEV_WALLET_PK) { const wallet = new Wallet(process.env.DEV_WALLET_PK!).connect( - getProvider(testCase.originChainId) + getProvider(testCase.params.originChainId) ); try { const tx = await wallet.sendTransaction({ diff --git a/src/data/routes_1_0xc186fA914353c44b2E33eBE05f21846F1048bEda.json b/src/data/routes_1_0xc186fA914353c44b2E33eBE05f21846F1048bEda.json index fe47510b2..0ca1aaec2 100644 --- a/src/data/routes_1_0xc186fA914353c44b2E33eBE05f21846F1048bEda.json +++ b/src/data/routes_1_0xc186fA914353c44b2E33eBE05f21846F1048bEda.json @@ -15,10 +15,10 @@ "42161": "0x81C7601ac0c5825e89F967f9222B977CCD78aD77" }, "uniswap": { - "10": "0x04989eaF03547E6583f9d9e42aeD11D2b78A808b", - "137": "0xa55490E20057BD4775618D0FC8D51F59f602FED0", - "8453": "0xed8b9c9aE7aCEf12eb4650d26Eb876005a4752d2", - "42161": "0x2414A759d4EFF700Ad81e257Ab5187d07eCeEbAb" + "10": "0x28249CD61170Ed200Db8988D7f69e21331AFFBD0", + "137": "0xC2dCB88873E00c9d401De2CBBa4C6A28f8A6e2c2", + "8453": "0xef5a54BEeBDB4Ee98E2906e30e65AD53dA8D2b17", + "42161": "0x07b64BE6906A78fac5FaB47cD58d59D0A093B15e" } }, "routes": [