> ## Documentation Index
> Fetch the complete documentation index at: https://docs.enso.build/llms.txt
> Use this file to discover all available pages before exploring further.

# Flashloans

> Borrow tokens without upfront collateral using the Bundle API.

export const date_0 = "2026-05-13"

Flashloans let you borrow tokens from a lending protocol without upfront collateral, execute a series of DeFi actions, and repay the debt — all within a single atomic transaction. If any step fails, the entire transaction reverts and no tokens are moved.

<Tip>
  Flashloans are only available through the [Bundle
  API](/pages/build/get-started/bundling-actions). They are not available via
  the `/route` endpoint.
</Tip>

## How Flashloans Work

```mermaid theme={null}
sequenceDiagram
    participant User
    participant Enso API
    participant FlashloanAdapter
    participant Lending Protocol
    participant Wallet

    User->>Enso API: POST /bundle with flashloan action
    Enso API-->>User: Transaction data
    User->>Wallet: Submit transaction
    Wallet->>FlashloanAdapter: Execute flashloan
    FlashloanAdapter->>Lending Protocol: Request flash borrow
    Lending Protocol->>Wallet: Transfer borrowed tokens
    Wallet->>Wallet: Execute callback actions
    Wallet->>Lending Protocol: Repay borrowed amount + fee
```

1. You choose the flashloan protocol by setting the action's `protocol` field, for example `morpho`, `aave-v3`, or `balancer-v3`
2. You submit a `/bundle` request containing a `flashloan` action with callback actions
3. The API compiles the bundle into a single transaction
4. When executed, the FlashloanAdapter requests a flash borrow from the selected lending protocol
5. The lending protocol transfers the borrowed tokens to the wallet
6. The callback actions execute sequentially (swaps, deposits, borrows, etc.)
7. The borrowed amount plus any protocol fee is repaid to the lending protocol
8. The transaction completes — or reverts entirely if repayment cannot be satisfied

<Note>
  Flashloans are atomic: if any callback action fails or the repayment cannot be
  satisfied, the entire transaction reverts and no tokens are moved.
</Note>

## Parameters

| Parameter         | Type       | Description                                                           | Required |
| ----------------- | ---------- | --------------------------------------------------------------------- | -------- |
| `flashloanToken`  | `string`   | Address of the token to flash borrow                                  | Yes      |
| `flashloanAmount` | `string`   | Amount to flash borrow in wei (with full decimals)                    | Yes      |
| `tokenIn`         | `string[]` | Addresses of additional tokens provided by the user as input          | No       |
| `amountIn`        | `string`   | Amount of `tokenIn` provided by the user in wei                       | No       |
| `tokenOut`        | `string[]` | Addresses of tokens expected as output after callback execution       | No       |
| `callback`        | `Action[]` | Array of actions to execute after receiving the flash-borrowed tokens | Yes      |
| `receiver`        | `string`   | Address to receive output tokens if not the caller                    | No       |

<Warning>
  The callback actions must produce enough tokens to repay the flash-borrowed
  amount plus any protocol fee. If repayment cannot be satisfied, the entire
  transaction will revert.
</Warning>

## Supported Protocols

The user must select the flashloan protocol by using one of these slugs as the action's `protocol` value.

```json theme={null}
{
  "protocol": "morpho-markets-v1",
  "action": "flashloan",
  "args": {
    "flashloanToken": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
    "flashloanAmount": "1000000000",
    "tokenOut": ["0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48"],
    "callback": []
  }
}
```

| Protocol                 | Slug                | Fee                                                                  |
| ------------------------ | ------------------- | -------------------------------------------------------------------- |
| Morpho                   | `morpho-markets-v1` | 0%                                                                   |
| Bend (Morpho fork)       | `bend`              | 0%                                                                   |
| Dolomite                 | `dolomite`          | 0%                                                                   |
| Aave V3                  | `aave-v3`           | Dynamic (pool-specific, basis points from `FLASHLOAN_PREMIUM_TOTAL`) |
| Hyperlend (Aave V3 fork) | `hyperlend`         | Dynamic (pool-specific)                                              |
| Balancer V3              | `balancer-v3`       | Pool-specific fee                                                    |
| Uniswap V3               | `uniswap-v3`        | Pool-specific fee (0.05%, 0.3%, or 1% depending on pool tier)        |
| Kodiak (Uniswap V3 fork) | `kodiak`            | Pool-specific fee                                                    |

## Chain Availability

Not all flashloan protocols are deployed on every chain. The table below shows which protocols are available on each supported chain.

| Chain     | Aave V3       | Morpho   | Balancer V3 | Dolomite | Uniswap V3 |
| --------- | ------------- | -------- | ----------- | -------- | ---------- |
| Ethereum  | ✅             | ✅        | ✅           | ✅        | ✅          |
| Arbitrum  | ✅             | ✅        | ✅           | ✅        | ✅          |
| Base      | ✅             | ✅        | ✅           | ✅        | ✅          |
| HyperEVM  | ✅ (Hyperlend) | ✅        | ✅           | ❌        | ❌          |
| Optimism  | ✅             | ✅        | ❌           | ❌        | ✅          |
| Polygon   | ✅             | ✅        | ❌           | ❌        | ✅          |
| Berachain | ❌             | ✅ (Bend) | ❌           | ✅        | ✅ (Kodiak) |
| Sonic     | ✅             | ✅        | ❌           | ❌        | ❌          |
| Binance   | ✅             | ❌        | ❌           | ❌        | ✅          |
| Avalanche | ✅             | ❌        | ❌           | ❌        | ❌          |
| Plasma    | ✅             | ❌        | ❌           | ❌        | ❌          |
| Ink       | ❌             | ❌        | ❌           | ✅        | ❌          |
| Unichain  | ❌             | ✅        | ❌           | ❌        | ❌          |
| World     | ❌             | ✅        | ❌           | ❌        | ✅          |
| Soneium   | ❌             | ✅        | ❌           | ❌        | ❌          |
| Plume     | ❌             | ✅        | ❌           | ❌        | ❌          |
| Katana    | ❌             | ✅        | ❌           | ❌        | ❌          |
| Monad     | ❌             | ✅        | ❌           | ❌        | ❌          |

Where a variant is noted (e.g. Hyperlend, Bend, Kodiak), the flashloan uses a fork or alternative deployment of the underlying protocol on that chain.

## Routing Strategies

Flashloans are supported across three routing strategies. Each strategy uses a dedicated adapter contract:

| Strategy        | Description                                                 | Adapter Contract           |
| --------------- | ----------------------------------------------------------- | -------------------------- |
| `ensowallet-v2` | Smart contract wallet — tokens stay in the user's wallet    | EnsoWalletFlashloanAdapter |
| `router`        | EOA via EnsoRouter — intermediate tokens held by the router | EnsoRouterFlashloanAdapter |
| `safe`          | Gnosis Safe multisig wallet                                 | EnsoSafeFlashloanAdapter   |

See the [Routing Strategies](/pages/build/reference/routing-strategies) reference for details on choosing a strategy.

## Examples

### Morpho WETH/USDC Leveraged Position (Open Loop)

Open a leveraged WETH long against a Morpho Markets V1 (Morpho Blue) market in a single atomic transaction. The user starts with 1 ETH and ends with a Morpho position holding \~1.45 WETH as collateral and 1,800 USDC of debt. The flashloan provides the temporary USDC to swap into extra collateral; the Morpho borrow at the end repays the flashloan from the freshly opened debt position.

```mermaid theme={null}
sequenceDiagram
    participant User
    participant Morpho
    User->>User: Wrap 1 ETH → 1 WETH
    User->>Morpho: Flashloan 1,800 USDC
    Note over User,Morpho: callback runs here
    User->>User: Swap 1,800 USDC → ~0.45 WETH
    User->>Morpho: Deposit ~1.45 WETH as collateral
    User->>Morpho: Borrow 1,800 USDC against the position
    User->>Morpho: Repay flashloan with the borrowed 1,800 USDC
```

```typescript morphoWethUsdcLoop.ts theme={null}
import { EnsoClient } from "@ensofinance/sdk";

const ETHEREUM_ID = 1;
const WALLET_ADDRESS = "0xd8da6bf26964af9d7eed9e03e53415d37aa96045";

// Tokens
const NATIVE_TOKEN = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE";
const WETH = "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2";
const USDC = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48";

// Morpho Blue WETH/USDC market on Ethereum
const MORPHO_BLUE = "0xBBBBBbbBBb9cC5e90e3b3Af64bdAF62C37EEFFCb";
const WETH_USDC_MARKET_ID =
  "0x94b823e6bd8ea533b4e33fbc307faea0b307301bc48763acc4d4aa4def7636cd";

const client = new EnsoClient({ apiKey: process.env.ENSO_API_KEY! });

const bundle = await client.getBundleData(
  {
    chainId: ETHEREUM_ID,
    fromAddress: WALLET_ADDRESS,
    receiver: WALLET_ADDRESS,
    routingStrategy: "ensowallet-v2",
  },
  [
    // Step 1: Wrap 1 ETH → WETH (will be combined with the swapped flashloan amount)
    {
      protocol: "wrapped-native",
      action: "deposit",
      args: {
        primaryAddress: WETH,
        tokenIn: NATIVE_TOKEN,
        amountIn: "1000000000000000000", // 1 ETH
        tokenOut: WETH,
      },
    },
    // Step 2: Flashloan 1,800 USDC from Morpho and use it to open the leveraged position
    {
      protocol: "morpho-markets-v1",
      action: "flashloan",
      args: {
        flashloanToken: USDC,
        flashloanAmount: "1800000000", // 1,800 USDC (6 decimals)
        tokenIn: WETH,
        amountIn: { useOutputOfCallAt: 0 }, // 1 WETH from the wrap above
        tokenOut: USDC,
        callback: [
          // 2a: Swap the flashloaned 1,800 USDC into WETH
          {
            protocol: "enso",
            action: "route",
            args: {
              tokenIn: USDC,
              amountIn: "1800000000",
              tokenOut: WETH,
              slippage: 300, // 3%
            },
          },
          // 2b: Read the combined WETH balance (user's 1 WETH + swapped WETH)
          {
            protocol: "enso",
            action: "balance",
            args: { token: WETH },
          },
          // 2c: Deposit all WETH as collateral in the Morpho WETH/USDC market
          {
            protocol: "morpho-markets-v1",
            action: "deposit",
            args: {
              primaryAddress: MORPHO_BLUE,
              positionId: WETH_USDC_MARKET_ID,
              tokenIn: WETH,
              amountIn: { useOutputOfCallAt: 1 },
              onBehalfOf: WALLET_ADDRESS,
            },
          },
          // 2d: Borrow 1,800 USDC against the new collateral — this repays the flashloan
          {
            protocol: "morpho-markets-v1",
            action: "borrow",
            args: {
              primaryAddress: MORPHO_BLUE,
              positionId: WETH_USDC_MARKET_ID,
              collateral: WETH,
              tokenOut: USDC,
              amountOut: "1800000000",
              onBehalfOf: WALLET_ADDRESS,
            },
          },
        ],
      },
    },
  ],
);
```

<Note>
  **Pick the flashloan asset to match the final borrow.** Flashloaning USDC and
  ending the callback with a USDC borrow lets the borrowed USDC repay the
  flashloan directly — no extra swap needed at the end of the callback.
</Note>

### Alchemix AlchemistV3 alUSD Loop (Morpho Flashloan)

Open an AlchemistV3 alUSD position using a Morpho USDC flashloan. The user contributes 10 MIXUSD; the flashloan brings in 15 USDC of "synthetic" collateral that gets wrapped into 15 MIXUSD inside the callback. The combined 25 MIXUSD becomes AlchemistV3 collateral, against which 17 alUSD is minted and swapped back into the USDC needed to repay the flashloan.

```mermaid theme={null}
sequenceDiagram
    participant User
    participant Morpho
    participant Alchemix
    User->>Morpho: Flashloan 15 USDC (user adds 10 MIXUSD)
    User->>Alchemix: Wrap 15 USDC → 15 MIXUSD (alchemix-myts)
    User->>Alchemix: Deposit ~25 MIXUSD → mint AlchemistV3 NFT
    User->>Alchemix: Borrow 17 alUSD against the new NFT position
    User->>User: Swap 17 alUSD → USDC
    User->>Morpho: Repay flashloan with USDC
```

```typescript alUsdLoopMorphoFlashloan.ts theme={null}
import { EnsoClient } from "@ensofinance/sdk";

const ETHEREUM_ID = 1;
const WALLET_ADDRESS = "0xd8da6bf26964af9d7eed9e03e53415d37aa96045";

const USDC = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48";
const MIXUSD = "0x9B44efCa3e2a707B63Dc00CE79d646E5E5D24bA5"; // alchemix-myts USDC
const ALUSD = "0xbc6da0fe9ad5f3b0d58160288917aa56653660e9";
const ALCHEMIST_V3_USD = "0xeB83112d925268BeDe86654C13D423a987587e3E";

const client = new EnsoClient({ apiKey: process.env.ENSO_API_KEY! });

const bundle = await client.getBundleData(
  {
    chainId: ETHEREUM_ID,
    fromAddress: WALLET_ADDRESS,
    routingStrategy: "router",
  },
  [
    {
      protocol: "morpho-markets-v1",
      action: "flashloan",
      args: {
        flashloanToken: USDC,
        flashloanAmount: "15000000", // 15 USDC (6 decimals)
        tokenIn: [MIXUSD],
        amountIn: ["10000000000000000000"], // 10 MIXUSD provided by the user
        tokenOut: [USDC],
        callback: [
          // 1: Wrap the 15 flashloaned USDC into MIXUSD via alchemix-myts
          {
            protocol: "alchemix-myts",
            action: "deposit",
            args: {
              primaryAddress: MIXUSD,
              tokenIn: USDC,
              tokenOut: MIXUSD,
              amountIn: "15000000",
            },
          },
          // 2: Read total MIXUSD (user's 10 + freshly minted 15)
          {
            protocol: "enso",
            action: "balance",
            args: { token: MIXUSD },
          },
          // 3: Open an AlchemistV3 NFT position with the combined MIXUSD
          {
            protocol: "alchemix-vaults-v3",
            action: "deposit",
            args: {
              primaryAddress: ALCHEMIST_V3_USD,
              tokenIn: MIXUSD,
              tokenOut: ALCHEMIST_V3_USD,
              amountIn: { useOutputOfCallAt: 1 },
              tokenId: "0", // 0 = mint a new position
              receiver: "0x0000000000000000000000000000000000000000",
            },
          },
          // 4: Borrow 17 alUSD against the newly minted NFT
          {
            protocol: "alchemix-vaults-v3",
            action: "borrow",
            args: {
              primaryAddress: ALCHEMIST_V3_USD,
              collateral: ALUSD,
              tokenOut: ALUSD,
              amountOut: "17000000000000000000", // 17 alUSD
              tokenId: { useOutputOfCallAt: 2, index: 0 },
            },
          },
          // 5: Swap 17 alUSD → USDC to repay the flashloan
          {
            protocol: "enso",
            action: "route",
            args: {
              tokenIn: [ALUSD],
              amountIn: { useOutputOfCallAt: 3 },
              tokenOut: [USDC],
              slippage: "100", // 1%
            },
          },
        ],
      },
    },
  ],
);
```

<Note>
  **`tokenIn` / `amountIn` on the flashloan action**: these are user-contributed
  assets that flow into the callback alongside the flashloaned funds — `tokenIn`
  accepts a single address or an array, and `amountIn` accepts a single amount,
  an array, or a `useOutputOfCallAt` reference to an earlier action's output.
</Note>

### Uniswap V3 Flashloan Opening an Aave V3 Leveraged Position (eMode)

Open a leveraged Aave V3 position inside a Uniswap V3 flashloan callback on MegaETH. The user contributes 1 USDm collateral and flashloans 1 USDe from a specific Uniswap V3 pool; inside the callback the flashloan is swapped to USDm, deposited as collateral, and Aave V3 mints 1.503 USDe debt (slightly more than 1 to cover the pool fee) to repay the flashloan.

```mermaid theme={null}
sequenceDiagram
    participant User
    participant UniswapV3
    participant Aave V3
    User->>UniswapV3: Flashloan 1 USDe (user adds 1 USDm)
    User->>User: Swap 1 USDe → USDm
    User->>Aave V3: Deposit combined USDm as collateral
    User->>Aave V3: Borrow 1.503 USDe (eMode category 7)
    User->>UniswapV3: Repay flashloan + pool fee with the 1.503 USDe
```

```typescript uniswapV3FlashloanAaveLeverage.ts theme={null}
import { EnsoClient } from "@ensofinance/sdk";

const MEGAETH_ID = 4326;
const WALLET_ADDRESS = "0xc95E8A0c36aBCFB7f436417DF2f1875e6642ad7D";

// Tokens on MegaETH
const USDE = "0xFAfDdbb3FC7688494971a79cc65DCa3EF82079E7"; // flashloan asset (= Aave debt asset)
const USDM = "0x5d3a1Ff2b6BAb83b63cd9AD0787074081a52ef34"; // user input + Aave collateral
const AUSDM = "0x78f2cB75D664d6f71433174056c25A5958B4016F"; // Aave aToken receipt

// Uniswap V3 pool used as the flashloan source and the Aave V3 pool
const UNI_V3_POOL = "0x587F6eeAfc7Ad567e96eD1B62775fA6402164b22";
const AAVE_V3_POOL = "0x7e324AbC5De01d112AfC03a584966ff199741C28";

const client = new EnsoClient({ apiKey: process.env.ENSO_API_KEY! });

const bundle = await client.getBundleData(
  {
    chainId: MEGAETH_ID,
    fromAddress: WALLET_ADDRESS,
    receiver: WALLET_ADDRESS,
    spender: WALLET_ADDRESS,
    routingStrategy: "ensowallet-v2",
  },
  [
    {
      protocol: "uniswap-v3",
      action: "flashloan",
      args: {
        primaryAddress: UNI_V3_POOL, // Uniswap V3 pool to flashloan from
        flashloanToken: USDE,
        flashloanAmount: "1000000000000000000", // 1 USDe
        tokenIn: USDM,
        amountIn: "1000000000000000000", // 1 USDm contributed by the user
        tokenOut: USDE,
        receiver: WALLET_ADDRESS,
        callback: [
          // 1: Swap the flashloaned 1 USDe into USDm
          {
            protocol: "enso",
            action: "route",
            args: {
              tokenIn: USDE,
              tokenOut: USDM,
              amountIn: "1000000000000000000",
            },
          },
          // 2: Read combined USDm balance (user's 1 + swapped)
          {
            protocol: "enso",
            action: "balance",
            args: { token: USDM },
          },
          // 3: Deposit USDm as collateral into Aave V3
          {
            protocol: "aave-v3",
            action: "deposit",
            args: {
              primaryAddress: AAVE_V3_POOL,
              tokenIn: USDM,
              tokenOut: AUSDM,
              amountIn: { useOutputOfCallAt: 1 },
              onBehalfOf: WALLET_ADDRESS,
            },
          },
          // 4: Borrow 1.503 USDe — repays the flashloan + Uniswap V3 pool fee
          {
            protocol: "aave-v3",
            action: "borrow",
            args: {
              primaryAddress: AAVE_V3_POOL,
              collateral: USDM,
              tokenOut: USDE,
              amountOut: "1503000000000000000", // 1.503 USDe
              onBehalfOf: WALLET_ADDRESS,
              args: {
                eModeCategoryId: "7", // required by Aave V3 for this borrow path
              },
            },
          },
        ],
      },
    },
  ],
);
```

<Note>
  **Uniswap V3 flashloans require `primaryAddress`**: unlike Morpho or Aave V3
  (where the lender is global), Uniswap V3 flashloans borrow from a specific
  pool. Pass the pool address as `primaryAddress` and pay the pool's fee tier
  (0.05% / 0.3% / 1%) when repaying — over-borrow slightly in the final borrow
  action to cover it.
</Note>

<Note>
  **Aave V3 eMode**: when the borrow target sits in an eMode category, pass
  `args.eModeCategoryId` on the `aave-v3.borrow` action. Enso emits the matching
  `setUserEMode` approval automatically.
</Note>

<div className="text-right text-xs gray-200 font-semibold w-full" style={{marginTop: '0'}}>
  <p style={{
        color: "#b2b2b2"  
    }}>Updated {date_0}</p>
</div>
