# Flash Swaps

Flash swaps are an integral feature of Swipeswap. In fact, under the hood, all swaps are actually flash swaps! This simply means that pair contracts send output tokens to the recipient *before* enforcing that enough input tokens have been received. This is slightly atypical, as one might expect a pair to ensure it’s received payment before delivery. However, because Ethereum transactions are *atomic*, we can roll back the entire swap if it turns out that the contract hasn’t received enough tokens to make itself whole by the end of the transaction.

To see how this all works, let’s start by examining the interface of the `swap` function:

```
function swap(uint amount0Out, uint amount1Out, address to, bytes calldata data);
```

For the sake of example, let’s assume that we’re dealing with a DAI/WETH pair, where DAI is `token0` and WETH is `token1`. `amount0Out` and `amount1Out` specify the amount of DAI and WETH that the `msg.sender` wants the pair to send to the `to` address (one of these amounts may be 0). At this point you may be wondering how the contract *receives* tokens. For a typical (non-flash) swap, it’s actually the responsibility of `msg.sender` to ensure that enough WETH or DAI has *already been sent* to the pair before `swap` is called (in the context of trading, this is all handled neatly by a router contract). But when executing a flash swap, *tokens do not need to be sent to the contract before calling `swap`*. Instead, they must be sent from within a *callback function* that the pair triggers on the `to` address.

## Triggering a Flash Swap <a href="#triggering-a-flash-swap" id="triggering-a-flash-swap"></a>

To differentiate between the “typical” trading case and the flash swap case, pairs use the `data` parameter. Specifically, if `data.length` equals 0, the contract assumes that payment has already been received, and simply transfers the tokens to the `to` address. But, if `data.length` is greater than 0, the contract transfers the tokens and then calls the following function on the `to` address:

```
function uniswapV2Call(address sender, uint amount0, uint amount1, bytes calldata data);
```

The logic behind this identification strategy is simple: the vast majority of valid flash swap use cases involve interactions with external protocols. The best way to pass information dictating how these interactions happen (function arguments, safety parameters, addresses, etc.) is via the `data` parameter. It’s expected that `data` will be `abi.decode`d from within `uniswapV2Call`. In the rare case where no data is required, callers should ensure that `data.length` equals 1 (i.e. encode a single junk byte as `bytes`), and then ignore this argument in `uniswapV2Call`.

Pairs call `uniswapV2Call` with the `sender` argument set to the `msg.sender` of the `swap`. `amount0` and `amount1` are simply `amount0Out` and `amount1Out`.

## Using uniswapV2Call <a href="#using-uniswapv2call" id="using-uniswapv2call"></a>

There are several conditions that should be checked in all `uniswapV2Call` functions:

```
function uniswapV2Call(address sender, uint amount0, uint amount1, bytes calldata data) {
  address token0 = IUniswapV2Pair(msg.sender).token0(); // fetch the address of token0
  address token1 = IUniswapV2Pair(msg.sender).token1(); // fetch the address of token1
  assert(msg.sender == IUniswapV2Factory(factoryV2).getPair(token0, token1)); // ensure that msg.sender is a V2 pair
  // rest of the function goes here!
}
```

The first 2 lines simply fetch the token addresses from the pair, and the 3rd ensures that the `msg.sender` is an actual Swipeswap pair address.

## Repayment <a href="#repayment" id="repayment"></a>

At the end of `uniswapV2Call`, contracts must return enough tokens to the pair to make it whole. Specifically, this means that the product of the pair reserves after the swap, discounting all token amounts sent by 0.3% LP fee, must be greater than before.

### Multi-Token <a href="#multi-token" id="multi-token"></a>

In the case where the token withdrawn is *not* the token returned (i.e. DAI was requested in the flash swap, and WETH was returned, or vice versa), the fee simplifies to the simple swap case. This means that the standard `getAmountIn` pricing function should be used to calculate e.g., the amount of WETH that must be returned in exchange for the amount of DAI that was requested out.

This type of fee calculation gives a slight advantage to the caller, as the fee derived from repayment in a corresponding token will always be slightly less than the fee derived from a direct token repayment, as a result of the difference between the amount required to pay back a swap, versus the amount withdrawn and then directly returned. The approximate comparison of fees is \~ 30 bps for a swap fee vs. 30.09 bps for a direct repayment.

### Single-Token <a href="#single-token" id="single-token"></a>

In the case where the token withdrawn is the *same* as the token returned (i.e. DAI was requested in the flash swap, used, then returned, or vice versa with WETH), the following condition must be satisfied:

`DAIReservePre - DAIWithdrawn + (DAIReturned * .997) >= DAIReservePre`

It may be more intuitive to rewrite this formula in terms of a “fee” levied on the *withdrawn* amount (despite the fact that Swipeswap always levies fees on input amounts, in this case the *returned* amount, here we can simplify to an effective fee on the *withdrawn* amount). If we rearrange, the formula looks like:

`(DAIReturned * .997) - DAIWithdrawn >= 0`

`DAIReturned >= DAIWithdrawn / .997`

So, the effective fee on the withdrawn amount is `.003 / .997 ≈ 0.3009027%`.

## Interface <a href="#interface" id="interface"></a>

```
import '@uniswap/v2-core/contracts/interfaces/IUniswapV2Callee.sol';
```

```
pragma solidity >=0.5.0;

interface IUniswapV2Callee {
  function uniswapV2Call(address sender, uint amount0, uint amount1, bytes calldata data) external;
}
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.swipe.org/swap/smart-contract/flash-swaps.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
