code-423n4 / 2024-03-dittoeth-findings

0 stars 0 forks source link

Disputants manipulate ShortRecord, claim undue penalties, disrupt redemption process. #226

Closed c4-bot-1 closed 5 months ago

c4-bot-1 commented 5 months ago

Lines of code

https://github.com/code-423n4/2024-03-dittoeth/blob/91faf46078bb6fe8ce9f55bcb717e5d2d302d22e/contracts/facets/RedemptionFacet.sol#L259 https://github.com/code-423n4/2024-03-dittoeth/blob/91faf46078bb6fe8ce9f55bcb717e5d2d302d22e/contracts/facets/RedemptionFacet.sol#L259 https://github.com/code-423n4/2024-03-dittoeth/blob/91faf46078bb6fe8ce9f55bcb717e5d2d302d22e/contracts/facets/RedemptionFacet.sol#L259

Vulnerability details

Vulnerability 1: Manipulated ShortRecord with Lower CR

The dispute mechanism in the redemption process is vulnerable to manipulation by disputants who provide a ShortRecord with a lower CR that may not necessarily be the lowest available CR.

Description

Vulnerability Details

  • The dispute mechanism is expected to allow disputants to provide a ShortRecord with the lowest available CR to challenge a proposed redemption.
  • The purpose is to ensure that the redemption process progresses from the lowest CR to the highest CR and prevents any incorrect or out-of-order redemptions.

Impact

Vulnerability 2: Timestamp Manipulation

dispute mechanism in the redemption process relies on the timeProposed and updatedAt timestamps, which are based on the protocol's time (LibOrders.getOffsetTime()). If these timestamps can be manipulated, it could impact the integrity of the dispute process.

Description

Vulnerability Details

Impact

Proof of Concept

Manipulated ShortRecord in Redemption Dispute

Scenario: Assume there are three ShortRecords in the system with the following collateral ratios (CRs):

A malicious disputer, Eve, wants to game the redemption dispute process to claim undue penalties.

Pace:

  1. Alice proposes a redemption for ShortRecord A with CR = 1.5.

  2. Eve creates a new ShortRecord, ShortRecord D, with a manipulated CR of 1.1.

    • Eve artificially lowers the collateral or increases the debt of ShortRecord D to achieve the manipulated CR.
  3. Eve calls the disputeRedemption function, providing ShortRecord D as the dispute ShortRecord.

  4. The disputeRedemption function compares the CR of ShortRecord D (1.1) with the CR of ShortRecord A (1.5) and finds that ShortRecord D has a lower CR.

  5. The function also checks if the updatedAt timestamp of ShortRecord D is earlier than the timeProposed of Alice's redemption proposal.

    • Eve ensures that the updatedAt timestamp of ShortRecord D is set to a value that satisfies this condition.
  6. Since the CR of ShortRecord D is lower than ShortRecord A and the timestamp condition is met, the dispute is considered valid.

  7. The function removes Alice's redemption proposal and imposes a penalty on Alice, transferring the penalty amount to Eve.

  8. Eve successfully games the system and claims undue penalties, even though ShortRecord B with CR = 1.2 should have been considered first for redemption.

  • The integrity of the redemption process is compromised, as the redemption order is not strictly followed from the lowest CR to the highest CR.
  • Alice, an honest redeemer, suffers financial losses due to the undue penalty imposed on her.
  • Eve, the malicious disputer, gains financial benefits by gaming the system and claiming undue penalties.
  • The fairness and reliability of the redemption mechanism are undermined, potentially leading to a loss of trust among users.

Code snippet demonstrating the disputeRedemption function:

function disputeRedemption(address asset, address redeemer, uint8 incorrectIndex, address disputeShorter, uint8 disputeShortId)
    external
{
    // ...

    STypes.ShortRecord storage disputeSR = s.shortRecords[asset][disputeShorter][disputeShortId];
    uint256 disputeCR = disputeSR.getCollateralRatio(redeemerAssetUser.oraclePrice);

    MTypes.ProposalData memory incorrectProposal = decodedProposalData[incorrectIndex];

    if (disputeCR < incorrectProposal.CR && disputeSR.updatedAt + C.DISPUTE_REDEMPTION_BUFFER <= redeemerAssetUser.timeProposed) {
        // Dispute is considered valid
        // Remove incorrect proposals and impose penalty on redeemer
        // ...
    }

    // ...
}

In the condition disputeCR < incorrectProposal.CR, which allows a manipulated ShortRecord with a lower CR to be used for disputing, even if it is not the lowest available CR in the system.

Tools Used

Manual Review

Recommended Mitigation Steps

Additional checks should be implemented to ensure that the dispute ShortRecord has the lowest CR among all ShortRecords in the system by iterating through all ShortRecords and comparing their CRs, as suggested in the mitigation section of the previous response.

     function disputeRedemption(address asset, address redeemer, uint8 incorrectIndex, address disputeShorter, uint8 disputeShortId)
         external
     {
         // ...

         uint256 lowestCR = type(uint256).max;
         for (uint256 i = 0; i < numShortRecords; i++) {
             STypes.ShortRecord storage currentSR = s.shortRecords[asset][shorters[i]][shortIds[i]];
             uint256 currentCR = currentSR.getCollateralRatio(redeemerAssetUser.oraclePrice);
             if (currentCR < lowestCR) {
                 lowestCR = currentCR;
             }
         }

         if (disputeCR == lowestCR && disputeSR.updatedAt + C.DISPUTE_REDEMPTION_BUFFER <= redeemerAssetUser.timeProposed) {
             // Valid dispute, proceed with the dispute logic
             // ...
         } else {
             revert Errors.InvalidRedemptionDispute();
         }

         // ...
     }

Assessed type

Governance

c4-pre-sort commented 5 months ago

raymondfam marked the issue as insufficient quality report

c4-pre-sort commented 5 months ago

raymondfam marked the issue as duplicate of #206

raymondfam commented 5 months ago

See #206.

c4-judge commented 4 months ago

hansfriese marked the issue as unsatisfactory: Insufficient proof