Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add return values liquidate #295

Merged
merged 4 commits into from
Aug 14, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 12 additions & 9 deletions src/Morpho.sol
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,10 @@ contract Morpho is IMorpho {
/* LIQUIDATION */

/// @inheritdoc IMorpho
function liquidate(Market memory market, address borrower, uint256 seized, bytes calldata data) external {
function liquidate(Market memory market, address borrower, uint256 seized, bytes calldata data)
external
returns (uint256 assetsRepaid, uint256 sharesRepaid)
{
Id id = market.id();
require(lastUpdate[id] != 0, ErrorsLib.MARKET_NOT_CREATED);
require(seized != 0, ErrorsLib.ZERO_ASSETS);
Expand All @@ -338,13 +341,13 @@ contract Morpho is IMorpho {

require(!_isHealthy(market, id, borrower, collateralPrice), ErrorsLib.HEALTHY_POSITION);

uint256 repaid =
assetsRepaid =
seized.mulDivUp(collateralPrice, ORACLE_PRICE_SCALE).wDivUp(liquidationIncentiveFactor(market.lltv));
uint256 repaidShares = repaid.toSharesDown(totalBorrow[id], totalBorrowShares[id]);
sharesRepaid = assetsRepaid.toSharesDown(totalBorrow[id], totalBorrowShares[id]);

borrowShares[id][borrower] -= repaidShares;
totalBorrowShares[id] -= repaidShares;
totalBorrow[id] -= repaid;
borrowShares[id][borrower] -= sharesRepaid;
totalBorrowShares[id] -= sharesRepaid;
totalBorrow[id] -= assetsRepaid;

collateral[id][borrower] -= seized;

Expand All @@ -361,11 +364,11 @@ contract Morpho is IMorpho {

IERC20(market.collateralToken).safeTransfer(msg.sender, seized);

emit EventsLib.Liquidate(id, msg.sender, borrower, repaid, repaidShares, seized, badDebtShares);
emit EventsLib.Liquidate(id, msg.sender, borrower, assetsRepaid, sharesRepaid, seized, badDebtShares);

if (data.length > 0) IMorphoLiquidateCallback(msg.sender).onMorphoLiquidate(repaid, data);
if (data.length > 0) IMorphoLiquidateCallback(msg.sender).onMorphoLiquidate(assetsRepaid, data);

IERC20(market.borrowableToken).safeTransferFrom(msg.sender, address(this), repaid);
IERC20(market.borrowableToken).safeTransferFrom(msg.sender, address(this), assetsRepaid);
}

/* FLASH LOANS */
Expand Down
8 changes: 6 additions & 2 deletions src/interfaces/IMorpho.sol
Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,12 @@ interface IMorpho is IFlashLender {
/// @param market The market of the position.
/// @param borrower The owner of the position.
/// @param seized The assets of collateral to seize.
/// @param data Arbitrary data to pass to the `onMorphoLiquidate` callback. Pass empty data if not needed
function liquidate(Market memory market, address borrower, uint256 seized, bytes memory data) external;
/// @param data Arbitrary data to pass to the `onMorphoLiquidate` callback. Pass empty data if not needed.
/// @return assetsRepaid The amount of assets repaid.
/// @return sharesRepaid The amount of shares repaid.
function liquidate(Market memory market, address borrower, uint256 seized, bytes memory data)
external
returns (uint256 assetsRepaid, uint256 sharesRepaid);

/// @notice Sets the authorization for `authorized` to manage `msg.sender`'s positions.
/// @param authorized The authorized address.
Expand Down
6 changes: 4 additions & 2 deletions test/forge/Morpho.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -641,7 +641,7 @@ contract MorphoTest is

// Liquidate
vm.prank(LIQUIDATOR);
morpho.liquidate(market, BORROWER, toSeize, hex"");
(uint256 assetsRepaid,) = morpho.liquidate(market, BORROWER, toSeize, hex"");

uint256 liquidatorNetWorthAfter = netWorth(LIQUIDATOR);
uint256 collateralPrice = IOracle(market.oracle).price();
Expand All @@ -650,6 +650,7 @@ contract MorphoTest is
toSeize.mulDivUp(collateralPrice, ORACLE_PRICE_SCALE).wDivUp(liquidationIncentiveFactor);
uint256 expectedNetWorthAfter =
liquidatorNetWorthBefore + toSeize.mulDivDown(collateralPrice, ORACLE_PRICE_SCALE) - expectedRepaid;
assertEq(assetsRepaid, expectedRepaid, "wrong return repaid value");
assertEq(liquidatorNetWorthAfter, expectedNetWorthAfter, "LIQUIDATOR net worth");
assertApproxEqAbs(borrowBalance(BORROWER), assetsBorrowed - expectedRepaid, 100, "BORROWER balance");
assertEq(morpho.collateral(id, BORROWER), assetsCollateral - toSeize, "BORROWER collateral");
Expand Down Expand Up @@ -686,7 +687,7 @@ contract MorphoTest is

// Liquidate
vm.prank(LIQUIDATOR);
morpho.liquidate(market, BORROWER, toSeize, hex"");
(uint256 assetsRepaid,) = morpho.liquidate(market, BORROWER, toSeize, hex"");

uint256 liquidatorNetWorthAfter = netWorth(LIQUIDATOR);
uint256 collateralPrice = IOracle(market.oracle).price();
Expand All @@ -695,6 +696,7 @@ contract MorphoTest is
toSeize.mulDivUp(collateralPrice, ORACLE_PRICE_SCALE).wDivUp(liquidationIncentiveFactor);
uint256 expectedNetWorthAfter =
liquidatorNetWorthBefore + toSeize.mulDivDown(collateralPrice, ORACLE_PRICE_SCALE) - expectedRepaid;
assertEq(assetsRepaid, expectedRepaid, "wrong return repaid value");
assertEq(liquidatorNetWorthAfter, expectedNetWorthAfter, "LIQUIDATOR net worth");
assertEq(borrowBalance(BORROWER), 0, "BORROWER balance");
assertEq(morpho.collateral(id, BORROWER), 0, "BORROWER collateral");
Expand Down