Skip to content

Mitigation Confirmed for M-03 #21

Open
@code423n4

Description

@code423n4

Mitigation of M-03: Fully Alleviated

The sponsor introduced numerous changes to the MCAGRateFeed to support the new price staleness threshold mechanism. In detail, they introduced a _stalenessThreshold variable that is set during the contract's constructor and can be adjusted by the contract's KUMA_MANAGER_ROLE role via its dedicated MCAGRateFeed::setStalenessThreshold function.

The MCAGRateFeed::getRate function was updated to utilize this variable by storing the updatedAt variable yielded by the MCAGAggregator::latestRoundDate function, subtracting it from the current block.timestamp, and ultimately yielding an error if the delta is greater than the threshold.

The changes were introduced in an exemplary manner, introducing a new event that signifies when the threshold has been changed, sanitizing its value as non-zero at all times, and containing an explicit getter function for it.

As a matter of optimization, the code of MCAGRateFeed::setStalenessThreshold could be refactored to an internal underscore-prefixed function that is used by the contract's constructor as well, minimizing code duplication.

A snippet of the contract with the remediated code showcased can be found below:

/**
 * @param riskCategory Unique risk category identifier computed with keccack256(abi.encode(currency, country, term))
 * @return rate Oracle rate in 27 decimals.
 */
function getRate(bytes32 riskCategory) external view override returns (uint256) {
    MCAGAggregatorInterface oracle = _oracles[riskCategory];

   /**
    * MITIGATION BLOCK OF M-03 START
    */

    (, int256 answer,, uint256 updatedAt,) = oracle.latestRoundData();

    if (block.timestamp - updatedAt > _stalenessThreshold) {
        revert Errors.ORACLE_ANSWER_IS_STALE();
    }

    /**
     * MITIGATION BLOCK END
     */

    if (answer < 0) {
        return _MIN_RATE_COUPON;
    }
    uint256 rate = uint256(answer);
    uint8 oracleDecimal = oracle.decimals();
    if (_DECIMALS < oracleDecimal) {
        rate = uint256(answer) / (10 ** (oracleDecimal - _DECIMALS));
    } else if (_DECIMALS > oracleDecimal) {
        rate = uint256(answer) * 10 ** (_DECIMALS - oracleDecimal);
    }
    if (rate < _MIN_RATE_COUPON) {
        return _MIN_RATE_COUPON;
    }
    return rate;
}

We consider this change sufficient to protect against outdated prices based on the fact that the KUMA Protocol team adequately configures the contract's _stalenessThreshold value.

The tests of the KUMA Protocol had to be updated to support the new construction mechanism of MCAGRateFeed and two new tests were introduced to the codebase's MCAGRateFeedTest.t.sol file that validate the setter function of the MCAGRateFeed::setStalenessThreshold as well as the getRate function behave as expected.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions