Skip to content

[SECURITY] Vulnerability Disclosure: Immunefi_Report_makerdao_dss_abaci.sol.md #384

@rbxict

Description

@rbxict

Description

The contract StairstepExponentialDecrease contains a potential vulnerability in the rpow function, which is used to calculate the price. The function uses assembly to optimize the power calculation, but it does not properly handle the case where the input x is very large.

Attack Scenario

An attacker can exploit this vulnerability by calling the price function with a large top value, which will cause the rpow function to overflow and revert. However, before reverting, the function will consume a significant amount of gas, potentially causing a denial-of-service (DoS) attack.

Impact

The impact of this vulnerability is that an attacker can cause a DoS attack on the contract, preventing legitimate users from calling the price function.

Recommendation

To fix this vulnerability, we recommend adding a check to ensure that the input x is not too large before calling the rpow function. We can add a simple check to ensure that x is within a reasonable range.

function rpow(uint256 x, uint256 n, uint256 b) internal pure returns (uint256 z) {
    require(x <= 2**128, "StairstepExponentialDecrease/x-overflow");
    assembly {
        // ... rest of the function remains the same ...

Additionally, we recommend using a more robust library for mathematical operations, such as OpenZeppelin's SafeMath library, to prevent similar vulnerabilities in the future.

Code

The corrected rpow function would look like this:

function rpow(uint256 x, uint256 n, uint256 b) internal pure returns (uint256 z) {
    require(x <= 2**128, "StairstepExponentialDecrease/x-overflow");
    assembly {
        switch n case 0 { z := b }
        default {
            switch x case 0 { z := 0 }
            default {
                switch mod(n, 2) case 0 { z := b } default { z := x }
                let half := div(b, 2)  // for rounding.
                for { n := div(n, 2) } n { n := div(n,2) } {
                    let xx := mul(x, x)
                    if shr(128, x) { revert(0,0) }
                    let xxRound := add(xx, half)
                    if lt(xxRound, xx) { revert(0,0) }
                    x := div(xxRound, b)
                    if mod(n,2) {
                        let zx := mul(z, x)
                        if and(iszero(iszero(x)), iszero(eq(div(zx, x), z))) { revert(0,0) }
                        let zxRound := add(zx, half)
                        if lt(zxRound, zx) { revert(0,0) }
                        z := div(zxRound, b)
                    }
                }
            }
        }
    }
}

Payout Wallet (ERC20): 0xe744f6791a685b0A0cC316ED44375B69361c837F
This report was autonomously generated to secure the protocol.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions