-
Notifications
You must be signed in to change notification settings - Fork 4
Open
Labels
3 (High Risk)Assets can be stolen/lost/compromised directlyAssets can be stolen/lost/compromised directly🤖_primaryAI based primary recommendationAI based primary recommendationH-01bugSomething isn't workingSomething isn't workingprimary issueHighest quality submission among a set of duplicatesHighest quality submission among a set of duplicatesselected for reportThis submission will be included/highlighted in the audit reportThis submission will be included/highlighted in the audit reportsponsor confirmedSponsor agrees this is a problem and intends to fix it (OK to use w/ "disagree with severity")Sponsor agrees this is a problem and intends to fix it (OK to use w/ "disagree with severity")
Description
Lines of code
Vulnerability details
Vulnerability details
in ETHOracle.sol
getPrecision() is defined as 10 ** 18, but the actual oracle used is 8-decimals
https://data.chain.link/feeds/arbitrum/mainnet/eth-usd
this data feeds 's decimals` is 8
/**
* ETH/USD Oracle using chainlink data feeds
*
* For more information about the feed go to
@> * https://data.chain.link/feeds/arbitrum/mainnet/eth-usd
*
**/
contract ETHOracle is IOracle {
IChainlinkAggregator private immutable _ethPriceFeed;
@> uint256 private constant _PRECISION = 10 ** 18;
....
function getLatestPrice() public view override returns (IOracle.Price memory price) {
(, int256 answer, uint256 startedAt, uint256 updatedAt,) = _ethPriceFeed.latestRoundData();
if ( answer<= 0 ) revert InvalidPriceFromOracle();
if ( startedAt ==0 || updatedAt == 0 ) revert InvalidPriceUpdatedAt();
@> price.price = uint256(answer); //@audit 8 decimals
price.lastUpdate = updatedAt;
}PythOracle is used to get prices for other tokens, also getPrecision() == 18
contract PythOracle is IOracle {
...
uint256 private constant _PRECISION = 18;
function _getPriceInternal(uint256 age) private view returns (IOracle.Price memory outPrice) {
PythStructs.Price memory price = age == 0 ?
_pyth.getPriceUnsafe(_priceID):
_pyth.getPriceNoOlderThan(_priceID, age);
if (price.expo >= 0) {
outPrice.price =
uint64(price.price) *
uint256(10 ** (_PRECISION + uint32(price.expo)));
} else {
outPrice.price =
uint64(price.price) *
uint256(10 ** (_PRECISION - uint32(-price.expo)));
}
outPrice.lastUpdate = price.publishTime;
}Since a different precision is used, then the calculation of totalCollateralInEth at StrategyLeverage will be wrong.
function _getPosition(
uint256 priceMaxAge
) internal view returns (uint256 totalCollateralInEth, uint256 totalDebtInEth) {
...
totalCollateralInEth = 0;
totalDebtInEth = 0;
(uint256 collateralBalance, uint256 debtBalance ) = _getMMPosition();
if (collateralBalance != 0) {
IOracle.Price memory ethPrice = priceMaxAge == 0 ?
_ethUSDOracle.getLatestPrice():
_ethUSDOracle.getSafeLatestPrice(priceMaxAge);
IOracle.Price memory collateralPrice = priceMaxAge == 0 ?
_collateralOracle.getLatestPrice():
_collateralOracle.getSafeLatestPrice(priceMaxAge);
if (
!(priceMaxAge == 0 ||
(priceMaxAge > 0 && (ethPrice.lastUpdate >= (block.timestamp - priceMaxAge))) ||
(priceMaxAge > 0 &&
(collateralPrice.lastUpdate >= (block.timestamp - priceMaxAge))))
) {
revert PriceOutdated();
}
@> totalCollateralInEth = (collateralBalance * collateralPrice.price) / ethPrice.price;
}
if (debtBalance != 0) {
totalDebtInEth = debtBalance;
}
}Impact
Incorrect calculation of totalCollateralInEth, affecting borrowing judgment, e.g. overvaluation overborrowing, etc.
Recommended Mitigation
convert to 18 decimals
Assessed type
Context
Metadata
Metadata
Assignees
Labels
3 (High Risk)Assets can be stolen/lost/compromised directlyAssets can be stolen/lost/compromised directly🤖_primaryAI based primary recommendationAI based primary recommendationH-01bugSomething isn't workingSomething isn't workingprimary issueHighest quality submission among a set of duplicatesHighest quality submission among a set of duplicatesselected for reportThis submission will be included/highlighted in the audit reportThis submission will be included/highlighted in the audit reportsponsor confirmedSponsor agrees this is a problem and intends to fix it (OK to use w/ "disagree with severity")Sponsor agrees this is a problem and intends to fix it (OK to use w/ "disagree with severity")