# Flash Swaps

## ⚡ Flash Swaps on Zealous Swap

Flash swaps are a native feature of Zealous Swap pairs. All swaps, under the hood, are flash swaps — meaning tokens are sent **before** the pair enforces repayment. Thanks to atomic transactions on the blockchain, the entire operation can be safely reverted if repayment conditions are not met.

This allows for powerful use cases like arbitrage, liquidations, or cross-protocol logic — all without upfront capital.

***

### 🧠 How Flash Swaps Work

The `swap` function in a Zealous Swap pair looks like this:

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

If you call `swap()` with a non-empty `data` field, the pair assumes you're doing a **flash swap** and sends the tokens *before* collecting payment.

It then invokes a callback on the recipient address:

```solidity
function zealousSwapCall(address sender, uint amount0, uint amount1, bytes calldata data) external;
```

Your contract receives the tokens, performs any logic (e.g., arbitrage, on-chain liquidation, flash loan interaction), and must repay the correct amount *within the same transaction*.

***

### 🔄 Example: Flash Swap USDT, Return WKAS

Let’s say the USDT/WKAS pool has USDT as token0 and WKAS as token1.

You call:

```solidity
pair.swap(
  1000e6, // amount0Out: 1000 USDT
  0,      // amount1Out: 0 WKAS
  address(this),
  abi.encode(someData), // triggers flash logic
  address(this)
);
```

The pair sends 1000 USDT to your contract, then calls:

```solidity
function zealousSwapCall(address sender, uint amount0, uint amount1, bytes calldata data)
```

Inside that function, you might:

1. Use the USDT in a lending protocol.
2. Swap borrowed assets for WKAS.
3. Repay the USDT flash loan (plus fee) to the pair.

***

### ✅ Required Checks in `zealousSwapCall`

Always ensure:

```solidity
function zealousSwapCall(address sender, uint amount0, uint amount1, bytes calldata data) external {
  address token0 = IZealousPair(msg.sender).token0();
  address token1 = IZealousPair(msg.sender).token1();

  address expectedPair = IZealousFactory(factory).getPair(token0, token1);
  require(msg.sender == expectedPair, "Unauthorized caller");

  // ... your logic goes here
}
```

This prevents spoofing or unexpected callbacks.

***

### 💸 Flash Swap Repayment Rules

At the end of your function, the pair must receive enough tokens to satisfy the invariant, accounting for the pair **swap fee** (let's assume 0.3%).

#### If you're returning the **same token**:

```solidity
returnedAmount >= withdrawnAmount / 0.997;
```

This reflects the effective **\~0.3009%** fee applied on the output.

#### If you're returning a **different token**:

Use the router's `getAmountIn()` function to calculate how much of token B must be returned for token A withdrawn. This mirrors a typical swap calculation.

***

### 🧰 Flash Swap Interface

To use flash swaps, implement this interface:

```solidity
pragma solidity >=0.5.0;

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

The pair will call this function automatically during the swap if the `data` field is non-empty.

***

### 🛠 Practical Use Cases

* Arbitrage across different DEXes
* Leveraged liquidity provisioning
* Flash collateralized borrowing
* Liquidations and collateral swaps

No upfront funds are needed — as long as you repay the flash loan (with fee) within the same transaction.

***

### ✅ Summary

* Flash swaps allow token withdrawal *before* repayment.
* The recipient must implement `zealousSwapCall` and return enough tokens.
* The operation reverts if repayment fails — no partial execution.
* Enables capital-efficient DeFi strategies without trust assumptions.
