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

0 stars 0 forks source link

Unfair rewards or penalties from manipulated collateral ratios in dispute resolutions. #206

Closed c4-bot-2 closed 4 months ago

c4-bot-2 commented 5 months ago

Lines of code

https://github.com/code-423n4/2024-03-dittoeth/blob/91faf46078bb6fe8ce9f55bcb717e5d2d302d22e/contracts/facets/RedemptionFacet.sol#L224-L272 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#L289-L291

Vulnerability details

Detailed Description

The calculation of the penalty for a successful dispute is performed in the disputeRedemption function. This allows users to dispute an invalid redemption proposal and rewards them with a portion of the disputed collateral as a penalty paid by the proposer.

RedemptionFacet.sol#disputeRedemption

function disputeRedemption(address asset, address redeemer, uint8 incorrectIndex, address disputeShorter, uint8 disputeShortId)
    external
    isNotFrozen(asset)
    nonReentrant
{
    // ...
    uint256 disputeCR = disputeSR.getCollateralRatio(redeemerAssetUser.oraclePrice);

    if (disputeCR < incorrectProposal.CR && disputeSR.updatedAt + C.DISPUTE_REDEMPTION_BUFFER <= redeemerAssetUser.timeProposed) {
        // ...
        uint256 penaltyPct = LibOrders.min(
            LibOrders.max(LibAsset.callerFeePct(d.asset), (currentProposal.CR - disputeCR).div(currentProposal.CR)), 0.33 ether
        );

        uint88 penaltyAmt = d.incorrectErcDebt.mulU88(penaltyPct);

        redeemerAssetUser.ercEscrowed += (d.incorrectErcDebt - penaltyAmt);
        s.assetUser[d.asset][msg.sender].ercEscrowed += penaltyAmt;
    } else {
        revert Errors.InvalidRedemptionDispute();
    }
}

Key inputs to this function are asset (the asset being disputed), redeemer (the address of the redeemer), incorrectIndex (the index of the incorrect proposal), disputeShorter (the address of the disputed ShortRecord), and disputeShortId (the ID of the disputed ShortRecord).

The comparison of the collateral ratios between the disputed ShortRecord (disputeCR) and the incorrect proposal (incorrectProposal.CR). The penalty calculation relies on the accuracy of these collateral ratios.

Code responsible: RedemptionFacet.sol#L259, RedemptionFacet.sol#L289-L290

if (disputeCR < incorrectProposal.CR && disputeSR.updatedAt + C.DISPUTE_REDEMPTION_BUFFER <= redeemerAssetUser.timeProposed) {
    // ...
    uint256 penaltyPct = LibOrders.min(
        LibOrders.max(LibAsset.callerFeePct(d.asset), (currentProposal.CR - disputeCR).div(currentProposal.CR)), 0.33 ether
    );
    // ...
}

If there are any vulnerabilities or ways to manipulate the collateral ratio calculation, an attacker could potentially exploit this to gain unfair rewards or penalties.

The disputeRedemption function is expected to calculate the penalty accurately based on the difference between the collateral ratios of the disputed ShortRecord and the incorrect proposal. The penalty should be proportional to the severity of the incorrect proposal and incentivize users to identify and dispute invalid redemptions.

An attacker could potentially exploit this to their advantage. They could manipulate the collateral ratios to make the disputed ShortRecord appear to have a significantly lower collateral ratio than the incorrect proposal, resulting in a higher penalty percentage and unfair rewards for the disputer.

Alternatively, an attacker could manipulate the collateral ratios to make a valid ShortRecord appear to have a higher collateral ratio than the incorrect proposal, leading to an invalid dispute and potential penalties for the honest disputer.

Impact

Proof of Concept

To develop a clear proof-of-concept (PoC) that demonstrates the issue with the collateral ratio calculation in the dispute process and its potential impact on the protocol and users, we can create a test scenario that exploits the vulnerability. Here's a step-by-step PoC:

  1. Setup:

    • Assume there is a valid redemption proposal with an incorrect ShortRecord at index incorrectIndex.
    • The incorrect proposal has a collateral ratio of 1.5 (150%).
  2. Exploit:

    • An attacker identifies a vulnerable ShortRecord that they can manipulate to have a lower collateral ratio than the incorrect proposal.
    • The attacker manipulates the collateral and debt values of the vulnerable ShortRecord to achieve a collateral ratio of 1.2 (120%).
    • The attacker calls the disputeRedemption function with the following inputs:
      • asset: The address of the asset being disputed.
      • redeemer: The address of the redeemer who made the incorrect proposal.
      • incorrectIndex: The index of the incorrect proposal.
      • disputeShorter: The address of the manipulated ShortRecord.
      • disputeShortId: The ID of the manipulated ShortRecord.
   // Assume the incorrect proposal has a collateral ratio of 1.5 (150%)
   uint256 incorrectProposalCR = 1.5 ether;

   // Attacker manipulates the collateral and debt values of the vulnerable ShortRecord
   STypes.ShortRecord storage vulnerableShortRecord = s.shortRecords[asset][disputeShorter][disputeShortId];
   vulnerableShortRecord.collateral = 100 ether;
   vulnerableShortRecord.ercDebt = 83.33 ether;

   // Attacker calls the disputeRedemption function
   disputeRedemption(asset, redeemer, incorrectIndex, disputeShorter, disputeShortId);
  1. Expected Result:

    • The disputeRedemption function should accurately compare the collateral ratios of the disputed ShortRecord and the incorrect proposal.
    • Since the disputed ShortRecord has a collateral ratio of 1.2 (120%), which is lower than the incorrect proposal's collateral ratio of 1.5 (150%), the dispute should be considered valid.
    • The penalty percentage should be calculated based on the difference between the collateral ratios, and the penalty amount should be deducted from the redeemer's escrowed balance and added to the disputer's escrowed balance.
  2. Actual Result:

    • The disputeRedemption function compares the manipulated collateral ratio of the disputed ShortRecord (1.2) with the incorrect proposal's collateral ratio (1.5).
    • Since the manipulated collateral ratio is lower than the incorrect proposal's collateral ratio, the dispute is considered valid.
    • The penalty percentage is calculated based on the manipulated collateral ratios, resulting in a higher penalty percentage than expected.
    • The redeemer's escrowed balance is reduced by the penalty amount, and the attacker (disputer) receives an unfairly high reward.
  • The attacker can manipulate the collateral ratios to their advantage, leading to unfair rewards and penalties in the dispute process.
  • Honest redeemers may face excessive penalties due to manipulated collateral ratios, even if their proposals are valid.
  • The integrity of the dispute process is compromised, as attackers can exploit the vulnerability to game the system and obtain undeserved rewards.
  • The protocol's reputation and user trust may be damaged, as the fairness of the redemption and dispute mechanisms is called into question.

Tools Used

Vs Code

Recommended Mitigation Steps

function disputeRedemption(address asset, address redeemer, uint8 incorrectIndex, address disputeShorter, uint8 disputeShortId)
    external
    isNotFrozen(asset)
    nonReentrant
{
    // ...
    uint256 disputeCR = disputeSR.getCollateralRatio(redeemerAssetUser.oraclePrice);

    @// Verify that the disputed ShortRecord is valid and meets the criteria for disputing
    if (!isValidDisputeShortRecord(disputeSR)) {
        revert Errors.InvalidDisputeShortRecord();
    }

    @// Ensure that the disputed ShortRecord has a significantly lower collateral ratio than the incorrect proposal
    if (disputeCR < incorrectProposal.CR && disputeCR + C.MIN_CR_DIFFERENCE <= incorrectProposal.CR &&
        disputeSR.updatedAt + C.DISPUTE_REDEMPTION_BUFFER <= redeemerAssetUser.timeProposed) {
        // ...
    } else {
        revert Errors.InvalidRedemptionDispute();
    }
}

Assessed type

Invalid Validation

c4-pre-sort commented 5 months ago

raymondfam marked the issue as sufficient quality report

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 primary issue

raymondfam commented 5 months ago

The described POC isn't as discrete as it should be in #32, #33, and #34.

c4-judge commented 4 months ago

hansfriese marked the issue as unsatisfactory: Insufficient proof