diff --git a/.github/workflows/foundry.yml b/.github/workflows/foundry.yml index 4334bdbf6..99b493082 100644 --- a/.github/workflows/foundry.yml +++ b/.github/workflows/foundry.yml @@ -39,7 +39,7 @@ jobs: uses: foundry-rs/foundry-toolchain@v1 - name: Run Forge tests in ${{ matrix.type }} mode - run: forge test -vvv + run: yarn test:forge -vvv env: FOUNDRY_FUZZ_RUNS: ${{ matrix.fuzz-runs }} FOUNDRY_FUZZ_MAX_TEST_REJECTS: ${{ matrix.max-test-rejects }} diff --git a/src/Morpho.sol b/src/Morpho.sol index 7871519af..89d6db7d4 100644 --- a/src/Morpho.sol +++ b/src/Morpho.sol @@ -357,7 +357,6 @@ contract Morpho is IMorphoStaticTyping { _accrueInterest(marketParams, id); - uint256 repaidAssets; { uint256 collateralPrice = IOracle(marketParams.oracle).price(); @@ -370,15 +369,15 @@ contract Morpho is IMorphoStaticTyping { ); if (seizedAssets > 0) { - repaidAssets = + uint256 temp = seizedAssets.mulDivUp(collateralPrice, ORACLE_PRICE_SCALE).wDivUp(liquidationIncentiveFactor); - repaidShares = repaidAssets.toSharesDown(market[id].totalBorrowAssets, market[id].totalBorrowShares); + repaidShares = temp.toSharesDown(market[id].totalBorrowAssets, market[id].totalBorrowShares); } else { - repaidAssets = repaidShares.toAssetsUp(market[id].totalBorrowAssets, market[id].totalBorrowShares); - seizedAssets = - repaidAssets.wMulDown(liquidationIncentiveFactor).mulDivDown(ORACLE_PRICE_SCALE, collateralPrice); + seizedAssets = repaidShares.toAssetsDown(market[id].totalBorrowAssets, market[id].totalBorrowShares) + .wMulDown(liquidationIncentiveFactor).mulDivDown(ORACLE_PRICE_SCALE, collateralPrice); } } + uint256 repaidAssets = repaidShares.toAssetsUp(market[id].totalBorrowAssets, market[id].totalBorrowShares); position[id][borrower].borrowShares -= repaidShares.toUint128(); market[id].totalBorrowShares -= repaidShares.toUint128(); diff --git a/test/forge/integration/LiquidateIntegrationTest.sol b/test/forge/integration/LiquidateIntegrationTest.sol index f59223f37..874591d6a 100644 --- a/test/forge/integration/LiquidateIntegrationTest.sol +++ b/test/forge/integration/LiquidateIntegrationTest.sol @@ -206,8 +206,8 @@ contract LiquidateIntegrationTest is BaseTest { sharesRepaid = bound(sharesRepaid, 1, Math.min(borrowShares, maxSharesRepaid)); uint256 expectedRepaid = sharesRepaid.toAssetsUp(morpho.totalBorrowAssets(id), morpho.totalBorrowShares(id)); - uint256 expectedSeized = - expectedRepaid.wMulDown(liquidationIncentiveFactor).mulDivDown(ORACLE_PRICE_SCALE, params.priceCollateral); + uint256 expectedSeized = sharesRepaid.toAssetsDown(morpho.totalBorrowAssets(id), morpho.totalBorrowShares(id)) + .wMulDown(liquidationIncentiveFactor).mulDivDown(ORACLE_PRICE_SCALE, params.priceCollateral); loanToken.setBalance(LIQUIDATOR, params.amountBorrowed); @@ -354,4 +354,28 @@ contract LiquidateIntegrationTest is BaseTest { vm.prank(LIQUIDATOR); morpho.liquidate(marketParams, BORROWER, collateralAmount, 0, hex""); } + + function testSeizedAssetsRoundUp() public { + _setLltv(0.75e18); + _supply(100e18); + + uint256 amountCollateral = 400; + uint256 amountBorrowed = 300; + collateralToken.setBalance(BORROWER, amountCollateral); + + vm.startPrank(BORROWER); + morpho.supplyCollateral(marketParams, amountCollateral, BORROWER, hex""); + morpho.borrow(marketParams, amountBorrowed, 0, BORROWER, BORROWER); + vm.stopPrank(); + + oracle.setPrice(ORACLE_PRICE_SCALE - 0.01e18); + + loanToken.setBalance(LIQUIDATOR, amountBorrowed); + + vm.prank(LIQUIDATOR); + (uint256 seizedAssets, uint256 repaidAssets) = morpho.liquidate(marketParams, BORROWER, 0, 1, hex""); + + assertEq(seizedAssets, 0, "seizedAssets"); + assertEq(repaidAssets, 1, "repaidAssets"); + } }