Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wrong calculation of delinquent penalty time in updateTimeDelinquentAndGetPenaltyTime function #19

Closed
c4-bot-9 opened this issue Sep 18, 2024 · 3 comments
Labels
3 (High Risk) Assets can be stolen/lost/compromised directly bug Something isn't working primary issue Highest quality submission among a set of duplicates 🤖_primary AI based primary recommendation 🤖_17_group AI based duplicate group recommendation sponsor disputed Sponsor cannot duplicate the issue, or otherwise disagrees this is an issue sufficient quality report This report is of sufficient quality unsatisfactory does not satisfy C4 submission criteria; not eligible for awards

Comments

@c4-bot-9
Copy link
Contributor

Lines of code

https://github.com/code-423n4/2024-08-wildcat/blob/main/src/libraries/FeeMath.sol#L118

Vulnerability details

Impact

Because of the incorrect calculation of delinquent penalty time, a borrower gets charged much lower delinquency fee than intended.

Proof of Concept

Over time, as market operations occur, borrowers accumulate fees. This process is managed by the FeeMath.updateScaleFactorAndFees function. While this function updates the scaleFactor and applies the protocolFee, it also implements the delinquency fee based on the market's delinquency status. The calculation is performed by the updateDelinquency function, which then utilizes the updateTimeDelinquentAndGetPenaltyTime function to determine the duration for which the delinquencyFeeBips should be applied.

When state.isDelinquent is false, indicating that the current market is healthy, the return value is calculated as follows:

  function updateTimeDelinquentAndGetPenaltyTime(
    MarketState memory state,
    uint256 delinquencyGracePeriod,
    uint256 timeDelta
  ) internal pure returns (uint256 /* timeWithPenalty */) {
    // Seconds in delinquency at last update
    uint256 previousTimeDelinquent = state.timeDelinquent;

    if (state.isDelinquent) {
        ...
    }

    state.timeDelinquent = previousTimeDelinquent.satSub(timeDelta).toUint32();

    // Calculate the number of seconds the old timeDelinquent had remaining
    // outside the grace period, or zero if it was already in the grace period.
>>  uint256 secondsRemainingWithPenalty = previousTimeDelinquent.satSub(delinquencyGracePeriod);

    // Only apply penalties for the remaining time outside of the grace period.
    return MathUtils.min(secondsRemainingWithPenalty, timeDelta);
  }

In here, secondsRemainingWithPenalty is wrong because delinquent state remains active until previousTimeDelinquent drops down to zero.
It's also mentioned in wildcat doc: https://docs.wildcat.finance/using-wildcat/delinquency#how-delinquency-triggers

The penalty APR associated with a market activates once the grace tracker exceeds the grace period, and remains active until it drops below the same

Here's an example:

IF previousTimeDelinquent = 3 days and delinquencyGracePeriod = 5 days, then it should be: secondsRemainingWithPenalty = 3 days, but above code generates 0.

(IMPORTANT NOTE: The updateTimeDelinquentAndGetPenaltyTime function has another critical flaw; it assumes that state.isDelinquent is up-to-date and has remained unchanged from the last update to the present. This assumption is incorrect and will be addressed as a separate issue submission.)

Tools Used

Manual Review

Recommended Mitigation Steps

Update the calculation as follows:

-    uint256 secondsRemainingWithPenalty = previousTimeDelinquent.satSub(delinquencyGracePeriod);
+    uint256 secondsRemainingWithPenalty = MathUtils.min(previousTimeDelinquent, delinquencyGracePeriod);

Assessed type

Error

@c4-bot-9 c4-bot-9 added 3 (High Risk) Assets can be stolen/lost/compromised directly bug Something isn't working labels Sep 18, 2024
c4-bot-9 added a commit that referenced this issue Sep 18, 2024
@c4-bot-11 c4-bot-11 added 🤖_17_group AI based duplicate group recommendation 🤖_primary AI based primary recommendation labels Sep 18, 2024
@howlbot-integration howlbot-integration bot added primary issue Highest quality submission among a set of duplicates sufficient quality report This report is of sufficient quality labels Sep 20, 2024
@d1ll0n
Copy link

d1ll0n commented Sep 20, 2024

IF previousTimeDelinquent = 3 days and delinquencyGracePeriod = 5 days, then it should be: secondsRemainingWithPenalty = 3 days, but above code generates 0.

This is incorrect. If the previous time delinquent is 3 days and the grace period is 5 days, that means the borrower still has 2 days before they begin accruing penalties. This is documented in the repo and throughout the codebase.

image

If we used your suggestion of

uint256 secondsRemainingWithPenalty = MathUtils.min(previousTimeDelinquent, delinquencyGracePeriod);

That would completely break this mechanism. That would mean there is always some amount of time with penalties if the delinquency timer is above zero.

@d1ll0n d1ll0n added the sponsor disputed Sponsor cannot duplicate the issue, or otherwise disagrees this is an issue label Sep 20, 2024
@3docSec
Copy link

3docSec commented Oct 3, 2024

As per sponsor's comment, what was reported is intended behavior.

@c4-judge
Copy link
Contributor

c4-judge commented Oct 3, 2024

3docSec marked the issue as unsatisfactory:
Invalid

@c4-judge c4-judge closed this as completed Oct 3, 2024
@c4-judge c4-judge added the unsatisfactory does not satisfy C4 submission criteria; not eligible for awards label Oct 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
3 (High Risk) Assets can be stolen/lost/compromised directly bug Something isn't working primary issue Highest quality submission among a set of duplicates 🤖_primary AI based primary recommendation 🤖_17_group AI based duplicate group recommendation sponsor disputed Sponsor cannot duplicate the issue, or otherwise disagrees this is an issue sufficient quality report This report is of sufficient quality unsatisfactory does not satisfy C4 submission criteria; not eligible for awards
Projects
None yet
Development

No branches or pull requests

5 participants