code-423n4 / 2024-06-size-findings

3 stars 1 forks source link

Protocol Fee isn't collected in liquidate with replacement #305

Closed howlbot-integration[bot] closed 4 months ago

howlbot-integration[bot] commented 4 months ago

Lines of code

https://github.com/code-423n4/2024-06-size/blob/8850e25fb088898e9cf86f9be1c401ad155bea86/src/libraries/actions/LiquidateWithReplacement.sol#L146-L147

Vulnerability details

Impact

Impact on protocol earnings

Proof of Concept

By definition, from the docs the Protocol fee(swapFeeApr) is defined as 0.5% per year on all credit for cash operations and the recipient of the cash pays the fee. However, during a liquidateWithReplacement operation which is also a credit for cash operation as a borrow limit order(BorrowOffer) is filled, the cash repcipient(borrower) does does not pay any fees. As seen from the code the profit extracted is only dependent on the loans interest/rate. image

Tools Used

Manual Review

Recommended Mitigation Steps


function executeLiquidateWithReplacement(State storage state, LiquidateWithReplacementParams calldata params)
        external
        returns (uint256 issuanceValue, uint256 liquidatorProfitCollateralToken, uint256 liquidatorProfitBorrowToken)
    {
        emit Events.LiquidateWithReplacement(params.debtPositionId, params.borrower, params.minimumCollateralProfit);

        DebtPosition storage debtPosition = state.getDebtPosition(params.debtPositionId);
        DebtPosition memory debtPositionCopy = debtPosition;
        BorrowOffer storage borrowOffer = state.data.users[params.borrower].borrowOffer;
        uint256 tenor = debtPositionCopy.dueDate - block.timestamp;

        //...code omitted for brevity...

-       issuanceValue = Math.mulDivDown(debtPositionCopy.futureValue, PERCENT, PERCENT + ratePerTenor);
+       issuanceValue = Math.mulDivDown(debtPositionCopy.futureValue, PERCENT - state.getSwapFeePercent(tenor), PERCENT + ratePerTenor);
        liquidatorProfitBorrowToken = debtPositionCopy.futureValue - issuanceValue;

        //...omitted code...

        state.data.debtToken.mint(params.borrower, debtPosition.futureValue);
        state.data.borrowAToken.transferFrom(address(this), params.borrower, issuanceValue);
        state.data.borrowAToken.transferFrom(address(this), state.feeConfig.feeRecipient, liquidatorProfitBorrowToken);
    }

Assessed type

Other

c4-judge commented 4 months ago

hansfriese marked the issue as satisfactory