Skip to content

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

@rbxict

Description

@rbxict

Description

The contract StairstepExponentialDecrease has 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 handle the case where the base x is very large and the exponent n is also large. This can lead to an overflow in the xx variable, causing the function to revert.

Attack Scenario

An attacker can exploit this vulnerability by calling the price function with a large top value and a large dur value, causing the rpow function to overflow and revert. This can lead to a denial-of-service (DoS) attack, where the attacker can prevent the contract from functioning correctly.

Impact

The impact of this vulnerability is a denial-of-service (DoS) attack, where an attacker can prevent the contract from functioning correctly by causing the rpow function to overflow and revert.

Recommendation

To fix this vulnerability, we can add a check to ensure that the base x is not too large before calculating the power. We can also consider using a more robust library for mathematical operations.

Here is the patched code:

function rpow(uint256 x, uint256 n, uint256 b) internal pure returns (uint256 z) {
    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 or(shr(128, x), gt(xx, type(uint256).max)) { 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)
                    }
                }
            }
        }
    }
}

Note that we added a check gt(xx, type(uint256).max) to ensure that the xx variable does not overflow.


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