Flash Swap

什么是闪电贷

闪电贷 是一种 无需抵押的贷款机制,主要出现在 DeFi(去中心化金融)协议里。
它的核心特点是:

  1. 用户可以瞬间借到大量资金(几乎没有上限,只受池子流动性限制)。
  2. 必须在同一个交易(同一个区块内)还清
    • 如果没有还清,整个交易会直接被回滚(就像从没发生过一样)。
    • 所以协议提供者不会有风险。

闪电贷有什么用?

  1. 套利
    • 不同交易所(比如 Uniswap、SushiSwap、Curve)之间价格差异,瞬间搬运套利。
  2. 清算
    • 在借贷协议(比如 Aave、Compound)里,当有人抵押物不足时,你可以用闪电贷借钱去清算,然后赚取奖励。
  3. 抵押物替换
    • 假如你在 MakerDAO 抵押 ETH 借了 DAI,但想换成 WBTC 抵押,可以用闪电贷无缝替换,不需要先卖掉 ETH 再买 BTC。
  4. 高杠杆操作
    • 利用瞬时借贷,把本金放大很多倍,进行投机或策略。

为什么 Uniswap V2 也能提供闪电贷?

  • Uniswap V2 引入了一个机制:你可以拿走池子里的代币,只要在交易结束前归还相同数量的代币(或等值代币)
  • 这正好可以被用来实现 闪电贷

假设:

  • Uniswap V2,1 ETH = 2000 USDC。
  • SushiSwap,1 ETH = 2100 USDC。

操作步骤:

  1. 通过闪电贷借 100 ETH(不需要抵押)。
  2. 在 SushiSwap 卖掉 100 ETH,得到 210,000 USDC。
  3. 在 Uniswap 买回 100 ETH,只花 200,000 USDC。
  4. 归还闪电贷 100 ETH(或等值 USDC)。
  5. 赚到差价 10,000 USDC,手续费可能只有千分之一左右。

image.png

课上笔记

00aa6c7c3b745f8156d4096f0b9d5978.jpg

梁老师的教学合约 : https://github.com/liangpeili/defi-2024/blob/main/Flash_swap/contracts/FlashSwap.sol

代码设计

项目代码地址: https://github.com/Uniswap/v2-core/blob/master/contracts/UniswapV2Pair.sol

  • data.length > 0则启动闪电贷

  • UniswapV2Call()有什么用?

​ 答:当你调用 swap() 时,如果你传入的 to 地址是一个合约,并且带有数据(bytes calldata data 非空),Uniswap V2 会在交易过程中 回调该合约的 uniswapV2Call 方法

​ 这个函数就是你实现“如何使用借来的代币再赚回来手续费”的逻辑的地方。

总结

​ 闪电贷的主要用途就是套利,其运用体现就是DeFI产品的可组合性。

​ 更多的学习可以结合现有案例查看。

TWAP

5804a872aa79d19ac37674457dce45ea.jpg

基于时间权重的平均价格

代码地址: https://github.com/Uniswap/v2-core/blob/master/contracts/UniswapV2Pair.sol

核心函数:_update( )

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// update reserves and, on the first call per block, price accumulators
function _update(uint balance0, uint balance1, uint112 _reserve0, uint112 _reserve1) private {
require(balance0 <= uint112(-1) && balance1 <= uint112(-1), 'UniswapV2: OVERFLOW');
uint32 blockTimestamp = uint32(block.timestamp % 2**32);
uint32 timeElapsed = blockTimestamp - blockTimestampLast; // overflow is desired
if (timeElapsed > 0 && _reserve0 != 0 && _reserve1 != 0) {
// * never overflows, and + overflow is desired
price0CumulativeLast += uint(UQ112x112.encode(_reserve1).uqdiv(_reserve0)) * timeElapsed;
price1CumulativeLast += uint(UQ112x112.encode(_reserve0).uqdiv(_reserve1)) * timeElapsed;
}
reserve0 = uint112(balance0);
reserve1 = uint112(balance1);
blockTimestampLast = blockTimestamp;
emit Sync(reserve0, reserve1);
}
  • 在每次发生交易(mint/burn/swap)时被调用

  • 负责更新储备量(reserve0/reserve1)

  • 计算并累积价格累加器(price0CumulativeLast, price1CumulativeLast

  • 时间差由 block.timestamp 控制

  • TWAP 的实现方式:

    • 使用「累计价格」机制(cumulative price)记录价格随时间的累积值

    • 外部合约(比如喂价器/预言机)调用时,通过两个时刻的差值除以时间间隔得到平均价格:

image.png