2021-11-26Uniswap v3 詳解(六):閃電貸

本文copy自https://liaoph.com/uniswap-v3-6/

Flash swap

1637903779(1).png

Uniswap v3 的 flash swap

Uniswap v3 版本中,和 v2 一樣也有兩種閃電貸的方式,但是是通過不同的函數(shù)接口來完成的。

第一種是普通的閃電貸,即借入 token 和還貸 token 相同,通過 UniswapV3Pool.flash() 完成
第二種是類似 v2 的 flash swap,即借入 token 和還貸 token 不同,這個是通過 UniswapV3Pool.swap() 來完成的。

flash

普通閃電貸的接口為交易池合約的 UniswapV3Pool.flash() 函數(shù),它的實現(xiàn)也比較簡單:

function flash(
    address recipient,   // 借貸方地址,用于調(diào)用回調(diào)函數(shù)
    uint256 amount0,     // 借貸的 token0 的數(shù)量
    uint256 amount1,     // 借貸的 token1 的數(shù)量
    bytes calldata data  // 回調(diào)函數(shù)的參數(shù)
) external override lock noDelegateCall {
    uint128 _liquidity = liquidity;
    require(_liquidity > 0, 'L');

    // 計算借貸所需要扣除的手續(xù)費(fèi)
    uint256 fee0 = FullMath.mulDivRoundingUp(amount0, fee, 1e6);
    uint256 fee1 = FullMath.mulDivRoundingUp(amount1, fee, 1e6);
    // 記錄下當(dāng)前的余額
    uint256 balance0Before = balance0();
    uint256 balance1Before = balance1();

    // 將所需 token 發(fā)送給借貸方
    if (amount0 > 0) TransferHelper.safeTransfer(token0, recipient, amount0);
    if (amount1 > 0) TransferHelper.safeTransfer(token1, recipient, amount1);

    // 調(diào)用借貸方地址的回調(diào)函數(shù),將函數(shù)用戶傳入的 data 參數(shù)傳給這個回調(diào)函數(shù)
    IUniswapV3FlashCallback(msg.sender).uniswapV3FlashCallback(fee0, fee1, data);

    // 記錄調(diào)用完成后的余額
    uint256 balance0After = balance0();
    uint256 balance1After = balance1();

    // 比對借出代幣前和回調(diào)函數(shù)調(diào)用完成后余額的數(shù)量,對于每個 token,余額只能多不能少
    require(balance0Before.add(fee0) <= balance0After, 'F0');
    require(balance1Before.add(fee1) <= balance1After, 'F1');

    // 手續(xù)費(fèi)相關(guān)的計算
    uint256 paid0 = balance0After - balance0Before;
    uint256 paid1 = balance1After - balance1Before;

    if (paid0 > 0) {
        uint8 feeProtocol0 = slot0.feeProtocol % 16;
        uint256 fees0 = feeProtocol0 == 0 ? 0 : paid0 / feeProtocol0;
        if (uint128(fees0) > 0) protocolFees.token0 += uint128(fees0);
        feeGrowthGlobal0X128 += FullMath.mulDiv(paid0 - fees0, FixedPoint128.Q128, _liquidity);
    }
    if (paid1 > 0) {
        uint8 feeProtocol1 = slot0.feeProtocol >> 4;
        uint256 fees1 = feeProtocol1 == 0 ? 0 : paid1 / feeProtocol1;
        if (uint128(fees1) > 0) protocolFees.token1 += uint128(fees1);
        feeGrowthGlobal1X128 += FullMath.mulDiv(paid1 - fees1, FixedPoint128.Q128, _liquidity);
    }

    emit Flash(msg.sender, recipient, amount0, amount1, paid0, paid1);
}

flash swap

通過 UniswapV3Pool.swap() 函數(shù),可以完成 flashswap 的功能,這個函數(shù)在Uniswap v3 詳解(三):交易過程已經(jīng)有過詳細(xì)的描述。

在使用 flashswap 時,需要實現(xiàn)其 IUniswapV3SwapCallback 接口,完成閃電貸的還貸即可,這里不再贅述具體實現(xiàn)。

理解閃電貸

理解閃電貸,你才能理解 DeFi. 雖然 DeFi 領(lǐng)域一直有著大大小小的創(chuàng)新,號稱顛覆傳統(tǒng)金融。但是在我看來,只有閃電貸才是真正的顛覆者,它是 DeFi 的精髓。它區(qū)塊鏈和智能合約的特性發(fā)揮到了極致,使得借貸資金的使用效率在短時間內(nèi)提升到了前所未有的高度。引用 DODO 文檔里一段話:

Once you have a deep understanding of flash swap, you will realize the superiority of the DeFi world over the centralized world. The composability of smart contracts has elevated the fund utilization of DeFi to an unprecedented level. Thanks to trustlessness, the cost of credit in DeFi is incredibly low. Once this financial system is integrated into the real world, its potential for improving our society and productivity will be truly boundless. The DODO team hopes that flash swap serves as a primer for DeFi builders and beginners alike to gain an appreciation for the power of DeFi.

至此,關(guān)于 Uniswap v3 的所有內(nèi)容就介紹完畢了。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容