Flash Swap 与正常 Swap 的区别

Flash Swap 与正常 Swap 的区别

Flash Swap(闪电交换)和正常 Swap(普通交换)是去中心化交易所(如 Uniswap)中的两种不同交易方式,它们的主要区别如下:

1. 交易流程不同
  • 正常 Swap

    • 用户直接支付代币A,立即获得代币B。
    • 交易流程:用户 → 支付代币A → 获得代币B
    • 必须先拥有代币A才能发起交易。
  • Flash Swap

    • 用户可以先借入代币B,使用代币B执行任意操作(如套利、清算),然后在同一笔交易中偿还代币B及手续费。
    • 交易流程:借入代币B → 使用代币B → 偿还代币B + 手续费
    • 无需预先持有代币,依赖智能合约的原子性保证还款。
2. 资金要求不同
  • 正常 Swap:需要预先拥有足够的代币A作为交易本金。
  • Flash Swap:无需预先持有任何代币,只需在交易结束前偿还借款及手续费。
3. 智能合约交互
  • 正常 Swap:直接调用交易所的 Router 合约的 Swap 函数(如 swapExactTokensForTokens) ,无需额外逻辑。
  • Flash Swap
    1. 调用 swap 函数时传入数据(如 data 参数)触发闪电贷款。
    2. 交易所会回调合约的 uniswapV2Call 函数,用户在此函数中执行自定义操作(如套利)。
    3. 必须在 uniswapV2Call 函数中偿还借款及手续费,否则整个交易回滚。
4. 风险与收益
  • 正常 Swap:风险低,只需承担市场价格波动风险。
  • Flash Swap
    • 高风险:若操作失败(如套利机会消失),交易回滚,仅损失 gas 费用。
    • 高收益:可利用市场价格差异进行无本金套利,或执行清算等复杂策略。
5. 手续费
  • 正常 Swap:支付交易手续费(Uniswap 的输入金额的 0.3%)。
  • Flash Swap:支付闪电贷款的利息(通常为借款金额的 3 / 997),因为他是确定的输出,来计算输入,但是所有的swap都是计算输入的0.3%。和swapTokensForExactTokens中要调用的getamountin一样,通过确定的输出求输入,但是公式不一样。

Flash Swap测试代码

// SPDX-License-Identifier: MIT
pragma solidity ^0.8;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./interfaces/Uniswap.sol";

// uniswap will call this function when we execute the flash swap
interface IUniswapV2Callee {
    function uniswapV2Call(
        address sender,
        uint256 amount0,
        uint256 amount1,
        bytes calldata data
    ) external;
}

// flash swap contract
contract flashSwap is IUniswapV2Callee {
    address private constant WETH = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
    address private constant UniswapV2Factory =
        0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f;


    // we'll call this function to call to call FLASHLOAN on uniswap
    function testFlashSwap(address _tokenBorrow, uint256 _amount) external {
        // check the pair contract for token borrow and weth exists
        address pair = IUniswapV2Factory(UniswapV2Factory).getPair(
            _tokenBorrow,
            WETH
        );
        require(pair != address(0), "!pair");

        // right now we dont know tokenborrow belongs to which token
        address token0 = IUniswapV2Pair(pair).token0();
        address token1 = IUniswapV2Pair(pair).token1();

        // as a result, either amount0out will be equal to 0 or amount1out will be
        uint256 amount0Out = _tokenBorrow == token0 ? _amount : 0;
        uint256 amount1Out = _tokenBorrow == token1 ? _amount : 0;

        // need to pass some data to trigger uniswapv2call
        bytes memory data = abi.encode(_tokenBorrow, _amount);
        // last parameter tells whether its a normal swap or a flash swap
        IUniswapV2Pair(pair).swap(amount0Out, amount1Out, address(this), data);
        // adding data triggers a flashloan
    }

    // in return of flashloan call, uniswap will return with this function
    // providing us the token borrow and the amount
    // we also have to repay the borrowed amt plus some fees
    function uniswapV2Call(
        address _sender,
        uint256 _amount0,
        uint256 _amount1,
        bytes calldata _data
    ) external override {
        // check msg.sender is the pair contract
        // take address of token0 n token1
        address token0 = IUniswapV2Pair(msg.sender).token0();
        address token1 = IUniswapV2Pair(msg.sender).token1();
        // call uniswapv2factory to getpair 
        address pair = IUniswapV2Factory(UniswapV2Factory).getPair(token0, token1);
        require(msg.sender == pair, "!pair");
        // check sender holds the address who initiated the flash loans
        require(_sender == address(this), "!sender");

        (address tokenBorrow, uint amount) = abi.decode(_data, (address, uint));

        // 0.3% fees
        uint fee = ((amount * 3) / 997) + 1;
        uint amountToRepay = amount + fee;

        IERC20(tokenBorrow).transfer(pair, amountToRepay);
    }
}

正常swap的调用流程

  1. 用户 → Router 合约

    • 用户调用 Router 合约的 Swap 函数(如 swapExactTokensForTokensswapTokensForExactTokens 等)。
    • Router 合约会根据用户输入计算最优路径,并调用相应 Pair 合约的 swap 函数。
  2. Router → Pair 合约

    • Router 合约内部调用目标 Pair 合约的 swap 函数完成实际交换。

总结

Flash Swap 与正常 Swap 的区别
特性正常 SwapFlash Swap
资金要求需要预先持有代币无需预先持有,依赖原子性还款
交易流程直接交换代币借款 → 操作 → 还款
风险低(仅市场风险)高(操作失败则交易回滚)
收益固定(代币兑换)潜在高收益(无本金套利)
智能合约逻辑简单调用 swap需要实现回调函数 uniswapV2Call
用户调用入口Router 合约的 Swap 函数(如 swapExactTokensForTokens直接调用 Pair 合约的 swap 函数,并传入非空 data
核心逻辑Router 计算路径 → 调用多个 Pair 合约的 swaptestFlashSwap调用Pair 合约的 swap先借款,swap再执行回调函数 uniswapV2Call还款,swap最后判断流动性是否减少

Flash Swap 的核心优势在于允许用户在无本金的情况下利用市场机会,但需要精确的策略和代码实现,否则可能导致交易失败。

在实际应用中,用户通常通过 Router 合约(如 UniswapV2Router02)发起 Swap 交易,而不是直接调用 Pair 合约。Router 合约封装了复杂的路径计算、多池交换,确定输入或者确定输出等逻辑,为用户提供更友好的接口。

  • 正常 Swap:用户通过 Router 合约 发起交易,Router 内部调用 Pair 合约完成交换。
  • Flash Swap:合约通过 Pair 合约swap 函数触发,但需传入 data 参数,且必须实现回调函数 uniswapV2Call
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值