Omniscia Optimex Audit

AccountPositionManager Manual Review Findings

AccountPositionManager Manual Review Findings

APM-01M: Inexistent Loan-to-Value Ratio Validation

Description:

The AccountPositionManager::borrow function might be interacted with by multiple users simultaneously through different position IDs on the same AccountPositionManager instance.

The AccountPositionManager::borrow function does not impose any checks on the present borrow state of the APM, two distinct borrows to be authorized that might cumulatively breach the authorization loan-to-value thresholds.

Impact:

The expected LTV ratio that is meant to be maintained by off-chain signature processes might not ultimately be upheld by the system depending on when transactions are authorized.

Example:

contracts/AccountPositionManager.sol
244function borrow(
245 bytes32 positionId,
246 uint256 assets,
247 address recipient,
248 uint256 deadline,
249 MarketParams calldata marketParams,
250 bytes calldata signature
251) external whenAvailable(positionId) nonReentrant {
252 MarketAccess memory access = marketAccess[positionId];
253 bytes32 id = _validateMarketId(marketParams, access);
254 require(block.timestamp <= deadline, ErrorLib.DeadlineExpired());
255
256 /// Verify the authorizer has approved to borrow assets
257 require(
258 _verifyBorrowSig(
259 access.authorizer,
260 positionId,
261 assets,
262 recipient,
263 actionCounters[positionId],
264 deadline,
265 signature
266 ),
267 ErrorLib.InvalidAuthorizerSig()
268 );
269
270 /// Increment the action counter to prevent replay attacks
271 actionCounters[positionId]++;
272
273 /// @dev Invokes Morpho to borrow assets from the market
274 /// The assets will be sent directly to `recipient`
275 IMorpho(management.MORPHO()).borrow(
276 marketParams,
277 assets,
278 0,
279 address(this),
280 recipient
281 );
282
283 emit Borrowed(positionId, id, assets, recipient);
284}

Recommendation:

We advise each borrow authorization to be attached to a particular loan-to-value threshold.

Alleviation (c11bae0aacaeb7f4e4b53c864f96917ca574182f):

The Optimex team evaluated this exhibit and clarified that the off-chain systems impose adequate validations to ensure all pending actions will not result in an undesirable loan-to-value ratio.

While we cannot consider off-chain solutions as alleviations, we can consider this exhibit safely acknowledged based on properly functioning off-chain systems.

APM-02M: Incorrect Overwrite of Credits

Description:

The AccountPositionManager::forceClose function will overwrite any existing credits due for a particular position ID even though a position ID can have assets re-deposited to it.

Impact:

In the event that two forceful closures occur on the same position ID, any previously allocated credits will be overwritten and thus lost.

Example:

contracts/AccountPositionManager.sol
403function forceClose(
404 bytes32 positionId,
405 uint256 assets,
406 uint256 surplus,
407 MarketParams calldata marketParams
408) external nonReentrant {
409 address sender = msg.sender;
410 bytes32 id = _validateMarketId(marketParams, marketAccess[positionId]);
411 require(
412 management.isAuthorized(_MORPHO_LIQUIDATOR_ROLE, sender),
413 ErrorLib.Unauthorized(sender)
414 );
415 require(assets > 0, ErrorLib.ZeroAmount());
416
417 /// Withdraw collateral from the Morpho market, and transfer the amount
418 /// to the MorphoLiquidator contract for further processing
419 IMorpho morpho = IMorpho(management.MORPHO());
420 morpho.withdrawCollateral(marketParams, assets, address(this), sender);
421
422 /// User credit is updated if any amount remains after debt repayment
423 /// The credit amount can be claimed later via `claim`
424 if (surplus > 0) {
425 IERC20(marketParams.loanToken).safeTransferFrom(
426 sender,
427 address(this),
428 surplus
429 );
430
431 credits[positionId] = surplus;
432 }
433
434 emit ForceClosed(sender, positionId, id, assets, surplus);
435}

Recommendation:

We advise the code to increment the available credits rather than overwrite them, preventing potential fund loss of surplus amounts after debt repayments.

Alleviation (c11bae0aacaeb7f4e4b53c864f96917ca574182f):

The referenced credits assignment was updated to an assignment-and-increment (+=) operation, ensuring any previously established credits are preserved and thus alleviating this exhibit in full.