DeFiHardhat
35,000 USDC
View results
Submission Details
Severity: low
Invalid

Inaccurate Precision Adjustment in Chainlink Oracle Integration

Summary

In the integration of Chainlink oracles for price data retrieval, a vulnerability has been identified related to the adjustment of precision. This vulnerability could lead to inaccurate price conversions, potentially resulting in financial losses or incorrect system behavior. The vulnerability arises from the lack of proper adjustment for precision differences between the initial precision received from the Chainlink oracle (8 decimals) and the desired precision for the token (6 decimals).

Vulnerability Details

The vulnerability stems from the code’s assumption regarding the precision received from the Chainlink oracle and its subsequent adjustment. In the provided code snippet, the adjustment factor calculation is based solely on the assumption of an initial precision of 8 decimals, without explicit consideration for the precision difference between 8 and the desired precision of 6 decimals. This oversight may lead to inaccurate precision adjustment, resulting in incorrect price conversions.
When minting fertilizer, fertilizer is gotten out with the amountIn of barn raise token which is used to calculate the min fertilizer and min fertilizer out… To get the usdPrice of barnRaiseToken which is with WETH/STETH using lookback for instantaneous price. The getPrice will not favour tokens WETH/STETH of 18 decimals since the goal of the getPrice of ETHUSD is to return a 6 decimal value but In the case when chain link variable varies they will be loss of precision or loss exact value returned to calculate to get use price of tokens(WETH/STETH)

Exploitation Scenario:

Chainlink Oracle Integration:
The system integrates Chainlink oracles to retrieve price data for token conversion. The oracle response includes
both the price and the decimal precision, with the precision being 8 decimals for the ETH/USD pair to return a
price against the bean stalk token which is 6 decimals.
if (token == C.WETH) {
uint256 ethUsdPrice = LibEthUsdOracle.getEthUsdPrice(lookback);
if (ethUsdPrice == 0) return 0;
return uint256(1e24).div(ethUsdPrice);
}
Affects

function _getMintFertilizerOut(
uint256 tokenAmountIn,
address barnRaiseToken
) public view returns (uint256 fertilizerAmountOut) {
fertilizerAmountOut = tokenAmountIn.div(
LibUsdOracle.getUsdPrice(barnRaiseToken)
);
}

Vulnerability Exploitation:

function getPrice(
address priceAggregatorAddress,
uint256 maxTimeout
) internal view returns (uint256 price) {
IChainlinkAggregator priceAggregator = IChainlinkAggregator(priceAggregatorAddress);
// First, try to get current decimal precision:
uint8 decimals;
try priceAggregator.decimals() returns (uint8 _decimals) {
// If call to Chainlink succeeds, record the current decimal precision
decimals = _decimals;
} catch {
// If call to Chainlink aggregator reverts, return a price of 0 indicating failure
return 0;
}
// Secondly, try to get latest price data:
try priceAggregator.latestRoundData() returns (
uint80 roundId,
int256 answer,
uint256 /* startedAt /,
uint256 timestamp,
uint80 /
answeredInRound */
) {
// Check for an invalid roundId that is 0
if (roundId == 0) return 0;
if (checkForInvalidTimestampOrAnswer(timestamp, answer, block.timestamp, maxTimeout)) {
return 0;
}
// Adjust to 6 decimal precision.
return uint256(answer).mul(PRECISION).div(10 ** decimals);
} catch {
// If call to Chainlink aggregator reverts, return a price of 0 indicating failure
return 0;
}
}
The chainlink decimal is 8, and can vary depending on the oracle. We scale it to a constant 6 to make it easier to implement with the bean token (which also has 6 decimals).
The system attempts to adjust the received price to the desired precision of 6 decimals using a fixed adjustment factor. However, the adjustment factor calculation does not directly account for the precision difference between 8 and 6 decimals. As a result, the adjusted price will not accurately reflect the desired precision, leading to potential precision loss or incorrect price conversions

Impact

Inaccurate precision adjustment may lead to incorrect price conversions during token swaps or financial transactions. Users relying on the converted prices may experience financial losses or make incorrect decisions
based on inaccurate price data

Tools Used

Manual Review

Recommendations

Dynamically calculate the adjustment factor based on the difference between the initial precision and the desired precision to accurately scale the price.
try priceAggregator.latestRoundData() returns (
uint80 roundId,
int256 answer,
uint256 /* startedAt /,
uint256 timestamp,
uint80 /
answeredInRound */
) {
// Check for an invalid roundId that is 0
if (roundId == 0) return 0;
if (checkForInvalidTimestampOrAnswer(timestamp, answer, block.timestamp, maxTimeout)) {
return 0;
}
// Adjust to 6 decimal precision.
uint256 adjustmentFactor = 10 ** (8 - 6); // Adjusting from 8 to 6 decimals
return uint256(answer).mul(PRECISION).div(adjustmentFactor);
} catch {
// If call to Chainlink aggregator reverts, return a price of 0 indicating failure
return 0;
}

A past report https://medium.com/@JohnnyTime/breaking-down-high-severity-decimals-issue-in-codehawks-sta
blecoin-contest-c81c041780ea

Updates

Lead Judging Commences

giovannidisiena Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement
Assigned finding tags:

Informational/Invalid

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.