Omniscia Optimex Audit

MorphoLiquidator Manual Review Findings

MorphoLiquidator Manual Review Findings

MLR-01M: Potentially Outdated Position Information

Description:

THe MorphoLiquidator::payment function invokes the MorphoLiquidator::_precheck function before accruing interest for a particular market, yielding an inaccurate position.supplyShares data point if the apm is also a fee recipient for the specified market ID.

Impact:

This issue represents a latent vulnerability in the codebase that can manifest in a future iteration.

Example:

contracts/MorphoLiquidator.sol
233(
234 IMorpho morpho,
235 bytes32 marketId,
236 Id id,
237 address validator,
238 MarketParams memory marketParams,
239 Position memory position
240) = _precheck(apm, positionId);
241require(amount > 0, ErrorLib.ZeroAmount());
242
243/// Transfer the payment from the liquidator to this contract
244address sender = msg.sender;
245address loanToken = marketParams.loanToken;
246IERC20(loanToken).safeTransferFrom(sender, address(this), amount);
247
248/// Accrue the interest and retrieve the position's status from Morpho
249morpho.accrueInterest(marketParams);
250uint256 totalCollateral = position.collateral;
251uint256 borrowShares = position.borrowShares;

Recommendation:

Although this particular data point remains unused within the code, we believe that the code should either retrieve the only data points it requires in the MorphoLiquidator::_precheck function, document this caveat in the function itself, or accrue interest before invoking it.

Alleviation (c11bae0aacaeb7f4e4b53c864f96917ca574182f):

The Optimex team assessed this exhibit and opted to acknowledge it, introducing documentation to avoid future updates from resulting in misbehaviours.

MLR-02M: Profit Capture in Bad Debt Scenarios

Description:

The MorphoLiquidator::_liquidate function effectively disincentivizes bad debt to be repaid due to capturing profit at the expense of the liquidator instead of crediting it to the surplus yielded back to them.

Impact:

Bad debt positions will not be properly incentivized for liquidation due to unfair profit capture toward the Optimex treasury.

Example:

contracts/MorphoLiquidator.sol
501} else {
502 /// @dev For a bad debt, the `seizedCollateral` and `repaidDebt` are calculated using the `totalCollateral`.
503 /// The `surplus` is set to `0`.
504 /// Any leftover amount after covering debt is recorded as `profit`.
505 (result.seizedCollateral, result.repaidDebt) = morpho.liquidate(
506 marketParams,
507 apm,
508 totalCollateral,
509 0,
510 data
511 );
512 result.profit = amount - result.repaidDebt;
513}

Recommendation:

We advise the code to forfeit any profit in bad debt scenarios to ensure such positions are liquidated in a timely manner.

Alleviation (c11bae0aacaeb7f4e4b53c864f96917ca574182f):

The Optimex team evaluated this exhibit and clarified that the off-chain processes of Optimex rely on agreements between Optimex and liquidators with proceeds being split between them.

As profit is meant to be redirected to liquidators through secondary transactional channels, we consider this exhibit as safely acknowledged.