The contract OndoPriceOracleV2 allows for the owner to set an association between an fToken and a Chainlink oracle for price retrieval. The contract also allows the owner to set a maxmum amount of time delay that it will tolerate from all Chainlink oracles. However, there is no check in place to ensure that the time delay returned by a Chainlink oracle does not exceed this maximum.
Impact
An attacker could manipulate the time delay returned by a Chainlink oracle to be greater than the maximum amount of time delay set in the contract. This could cause the contract to use an outdated or malicious price for an fToken.
To fix this vulnerability, the contract should include a check to ensure that the time delay returned by a Chainlink oracle does not exceed the maximum amount of time delay set in the contract. If it does, the contract should not use the oracle's price for the fToken.
example :
function getUnderlyingPrice(address fToken) external view override returns
(uint256) {
uint256 price;
// Get price of fToken depending on OracleType
OracleType oracleType = fTokenToOracleType[fToken];
if (oracleType == OracleType.MANUAL) {
// Get price stored in contract storage
price = fTokenToUnderlyingPrice[fToken];
} else if (oracleType == OracleType.COMPOUND) {
// Get associated cToken and call Compound oracle
address cTokenAddress = fTokenToCToken[fToken];
price = cTokenOracle.getUnderlyingPrice(cTokenAddress);
} else if (oracleType == OracleType.CHAINLINK) {
ChainlinkOracleInfo oracleInfo = fTokenToChainlinkOracle[fToken];
ruby uint256 timeDelay = oracleInfo.oracle.getLatestRoundData().timestamp - block.timestamp;
require(timeDelay <= maxChainlinkOracleTimeDelay, "Chainlink oracle time delay exceeded maximum allowed");
price = oracleInfo.oracle.getLatestRoundData().result.mul(oracleInfo.scaleFactor).div(1e18);
}
// Check if a price cap has been set
if (fTokenToUnderlyingPriceCap[fToken] != 0) {
price = min(price, fTokenToUnderlyingPriceCap[fToken]);
}
return price;
}
This example code checks if the time delay returned by the Chainlink oracle is less than or equal to the maximum amount of time delay set in the contract. If it is not, the contract will not use the oracle's price for the fToken.
Lines of code
https://github.com/code-423n4/2023-01-ondo/blob/main/contracts/lending/OndoPriceOracleV2.sol#L92
Vulnerability details
Summary
The contract OndoPriceOracleV2 allows for the owner to set an association between an fToken and a Chainlink oracle for price retrieval. The contract also allows the owner to set a maxmum amount of time delay that it will tolerate from all Chainlink oracles. However, there is no check in place to ensure that the time delay returned by a Chainlink oracle does not exceed this maximum.
Impact
An attacker could manipulate the time delay returned by a Chainlink oracle to be greater than the maximum amount of time delay set in the contract. This could cause the contract to use an outdated or malicious price for an fToken.
Proof of Concept
https://github.com/code-423n4/2023-01-ondo/blob/main/contracts/lending/OndoPriceOracleV2.sol
Tools Used
Manual.
Recommended Mitigation Steps
To fix this vulnerability, the contract should include a check to ensure that the time delay returned by a Chainlink oracle does not exceed the maximum amount of time delay set in the contract. If it does, the contract should not use the oracle's price for the fToken.
example :
This example code checks if the time delay returned by the Chainlink oracle is less than or equal to the maximum amount of time delay set in the contract. If it is not, the contract will not use the oracle's price for the fToken.