code-423n4 / 2023-12-ethereumcreditguild-findings

9 stars 5 forks source link

THE UNDERLYING TOKEN DUST AMOUNT IS STUCK IN THE `SimplePSM` CONTRACT WHILE EXECUTING THE `SimplePSM.redeem` TRANSACTION #1196

Closed c4-bot-5 closed 5 months ago

c4-bot-5 commented 6 months ago

Lines of code

https://github.com/code-423n4/2023-12-ethereumcreditguild/blob/main/src/loan/SimplePSM.sol#L134-L144 https://github.com/code-423n4/2023-12-ethereumcreditguild/blob/main/src/loan/SimplePSM.sol#L87-L93

Vulnerability details

Impact

The SimplePSM.redeem function is called to redeem amountIn CREDIT for amountOut underlying tokens and send to address to. The redeem function calls the SimplePSM.getRedeemAmountOut function as shown below:

    amountOut = getRedeemAmountOut(amountIn);

And the amountOut is calclualted in the getRedeemAmountOut function as shown below:

    uint256 creditMultiplier = ProfitManager(profitManager)
        .creditMultiplier(); //@audit-info - creditMultiplier = 1e18
    return (amountIn * creditMultiplier) / 1e18 / decimalCorrection;

The issue here is that the dust underlying asset amount is not accounted for in the amountOut calculation. As a result even though the entire credit amount is burnt from the msg.sender the received underlying asset amount to the to address will be less since the dust asset amount was leftover in the contract.

As a result this dust underlying asset amount will be stuck in the SimplePSM contract.

Proof of Concept

    function redeem(
        address to,
        uint256 amountIn
    ) external returns (uint256 amountOut) {
        require(!redemptionsPaused, "SimplePSM: redemptions paused");
        amountOut = getRedeemAmountOut(amountIn);
        CreditToken(credit).burnFrom(msg.sender, amountIn);
        pegTokenBalance -= amountOut;
        ERC20(pegToken).safeTransfer(to, amountOut);
        emit Redeem(block.timestamp, to, amountIn, amountOut);
    }

https://github.com/code-423n4/2023-12-ethereumcreditguild/blob/main/src/loan/SimplePSM.sol#L134-L144

    function getRedeemAmountOut(
        uint256 amountIn
    ) public view returns (uint256) {
        uint256 creditMultiplier = ProfitManager(profitManager)
            .creditMultiplier();
        return (amountIn * creditMultiplier) / 1e18 / decimalCorrection;
    }

https://github.com/code-423n4/2023-12-ethereumcreditguild/blob/main/src/loan/SimplePSM.sol#L87-L93

Tools Used

Manual Review and VSCode

Recommended Mitigation Steps

Hence it is recommended to calculate the leftover dust underlying asset amount in the SimplePSM.getRedeemAmountOut function by using the modulo operation and transfer that amount to the ProfitManager contract or to a treasury contract. Hence this underlying token dust amount will not be stuck in the SimplePSM contract.

Assessed type

Math

0xSorryNotSorry commented 5 months ago

Dust amount - QA

c4-pre-sort commented 5 months ago

0xSorryNotSorry marked the issue as insufficient quality report

c4-judge commented 5 months ago

Trumpero changed the severity to QA (Quality Assurance)

c4-judge commented 5 months ago

Trumpero marked the issue as grade-b

c4-judge commented 5 months ago

Trumpero marked the issue as grade-c