Published on
【Free MEV系列】| AAVE V3 清算
Authors
  • avatar
    Name
    thinkingchaindotapp
    Twitter

AAVE-V3清算

原理

我们这次模拟清算了这笔交易。使用USDC清算,得到WETH。不算gas的情况下,WETH的利润是:0.085264572859541215WETH。

如今的清算,都是需要进行后跑,在债务情况更新之后,马上跟上清算的交易。比如在区块21218344,一笔交易0x51b477943b161e0ee0949502d3431e6f47861f0985fc7690d404e4063ae990d8调用了forward函数更新状态,然后此清算的交易紧随其后。

你可以发现其他的清算如出一辙:21228762212036872120778321194992等等。

这是输出的清算日志:

  [Before liquidation], usdc: 0.000000
  [Before liquidation], weth: 0.000000000000000000
  [Before liquidation],  healthFactor: 0.998328069365901610
     Let's make a flashloan and get some usdc, which would be used to do the liquidation
     [While liquidation],  usdc: 5887.364178
     [While liquidation],  weth: 0.000000000000000000
  [After liquidation],  usdc: 0.000000
  [After liquidation],  weth: 0.085264572859541215
  [After liquidation],  healthFactor: 1.125150230742895565

代码

//SPDX-License-Identifier: Unlicense
pragma solidity =0.8.19;

import "forge-std/Test.sol";
import "../interface.sol";

// @tx hash: 0x35240526c70a5bcfe2d7fd5bc5ba668ca3a490c4a135650fb892e70f1f0a0f1d
// Debt Asset: USDC
// DebtToCover: 5,887.3642
// Liquidation Asset: WETH
// Liquidation Amount: 1.9480

contract LiquidationOperator is Test {

    IERC20 public usdc = IERC20(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48);
    IWETH weth = IWETH(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2);
    IPancakeV3Pool public pancakeV3Pool = IPancakeV3Pool(0x1ac1A8FEaAEa1900C4166dEeed0C11cC10669D36);
    IAavePoolV3 public aavePoolV3 = IAavePoolV3(0x87870Bca3F3fD6335C3F4ce8392D69350B4fA4E2);
    address user = 0x3d025d18fbEC14e4A398bC5C5AF86d3C46DA1825;
    uint256 public DEBT_ASSET_USDC_AMOUNT = 5887364178;

    function setUp() public {
        vm.createSelectFork("mainnet", 21218344);
        // check: https://etherscan.io/txs?block=21218344&p=4
        // back run: 0x51b477943b161e0ee0949502d3431e6f47861f0985fc7690d404e4063ae990d8
        vm.rollFork(bytes32(0x35240526c70a5bcfe2d7fd5bc5ba668ca3a490c4a135650fb892e70f1f0a0f1d));
        deal(address(weth), address(this), 0);
    }

    function test_liquidation() public {
        emit log_named_decimal_uint(
            "[Before liquidation], usdc", usdc.balanceOf(address(this)), 6
        );
        emit log_named_decimal_uint(
            "[Before liquidation], weth", weth.balanceOf(address(this)), 18
        );

        (uint256 totalCollateralBase,
            uint256 totalDebtBase,
            uint256 availableBorrowsBase,
            uint256 currentLiquidationThreshold,
            uint256 ltv,
            uint256 healthFactor
        ) = aavePoolV3.getUserAccountData(user);

        emit log_named_decimal_uint(
            "[Before liquidation],  healthFactor", healthFactor, 18
        );

        pancakeV3Pool.swap(address(this), false, -int256(DEBT_ASSET_USDC_AMOUNT), 1461446703485210103287273052203988822378723970341, "");

        emit log_named_decimal_uint(
            "[After liquidation],  usdc", usdc.balanceOf(address(this)), 6
        );
        emit log_named_decimal_uint(
            "[After liquidation],  weth", weth.balanceOf(address(this)), 18
        );

        (totalCollateralBase,
            totalDebtBase,
            availableBorrowsBase,
            currentLiquidationThreshold,
            ltv,
            healthFactor
        ) = aavePoolV3.getUserAccountData(user);

        emit log_named_decimal_uint(
            "[After liquidation],  healthFactor", healthFactor, 18
        );
    }

    function pancakeV3SwapCallback(int256, int256 fee, bytes calldata) public {
        console.log("   Let's make a flashloan and get some usdc, which would be used to do the liquidation");
        emit log_named_decimal_uint(
            "   [While liquidation],  usdc", usdc.balanceOf(address(this)), 6
        );
        emit log_named_decimal_uint(
            "   [While liquidation],  weth", weth.balanceOf(address(this)), 18
        );

        usdc.approve(address(aavePoolV3), type(uint256).max);
        aavePoolV3.liquidationCall(address(weth), address(usdc), user, DEBT_ASSET_USDC_AMOUNT, false);
        weth.transfer(address(pancakeV3Pool), DEBT_ASSET_USDC_AMOUNT + uint256(fee));
        console.log("   Let's pay back flashloan");
    }

}

Tags