Submitted by cmichel
ScalingPriceOracle.sol#L136
ScalingPriceOracle.sol#L113
The oracle does not correctly compound the monthly APRs - it resets on fulfill.
Note that the oraclePrice storage variable is only set in _updateCPIData as part of the oracle fulfill callback.
Its set to the old price (price from 1 month ago) plus the interpolation from startTime to now.
However, startTime is reset in requestCPIData due to the afterTimeInit modifier, and therefore when Chainlink calls fulfill in response to the CPI request, the timeDelta = block.timestamp - startTime is close to zero again and oraclePrice is updated to itself again.
This breaks the core functionality of the protocol as the oracle does not track the CPI, it always resets to 1.0 after every fulfill instead of compounding it.
In addition, there should also be a way for an attacker to profit from the sudden drop of the oracle price to 1.0 again.
As an example, assume oraclePrice = 1.0 (1e18), monthlyAPR = 10%. The time elapsed is 14 days. Calling getCurrentOraclePrice() now would return 1.0 + 14/28 * 10% = 1.05.
The oraclePrice should be updated in requestCPIData() not in fulfill.
Cover this scenario of multi-month accumulation in tests.
ElliotFriedman (Volt) commented:
ElliotFriedman (Volt) confirmed and commented:
