DeFiHardhatFoundry
250,000 USDC
View results
Submission Details
Severity: low
Valid

`LibWell.getWellTwaUsdLiquidityFromReserves()` returns liquidity with incorrect precision

Summary

Any Well can be whitelisted according to docs:
https://docs.bean.money/almanac/farm/sun#minting-whitelist

LibWell.getWellTwaUsdLiquidityFromReserves() uses uncached prices when is called from SeasonGettersFacet.sol. In this case it returns result with precision of nonBeanToken instead of expected 1e18. It becomes problem when token is non-18 decimals.

Vulnerability Details

LibUsdOracle returns price with 1e6 precision, so this line just returns how much USD is in nonBeanToken reserve. Note that result has precision of token decimals:

function getWellTwaUsdLiquidityFromReserves(
address well,
uint256[] memory twaReserves
) internal view returns (uint256 usdLiquidity) {
...
// if the function reaches here, then this is called outside the sunrise function
// (i.e, seasonGetterFacet.getLiquidityToSupplyRatio()).We use LibUsdOracle
// to get the price. This should never be reached during sunrise and thus
// should not impact gas.
@> return LibUsdOracle.getTokenPrice(token).mul(twaReserves[j]).div(1e6);
}

Function is used in LibEvaluate.calcLPToSupplyRatio() to calculate nonBeanToken USD liquidity in all Wells. So for different tokens result has different precision, but they are all summed up:

function calcLPToSupplyRatio(
uint256 beanSupply
)
internal
view
returns (Decimal.D256 memory lpToSupplyRatio, address largestLiqWell, bool oracleFailure)
{
...
for (uint256 i; i < pools.length; i++) {
...
// calculate the non-bean usd liquidity value.
@> uint256 usdLiquidity = LibWell.getWellTwaUsdLiquidityFromReserves(
pools[i],
twaReserves
);
...
// calculate the scaled, non-bean liquidity in the pool.
@> wellLiquidity = getLiquidityWeight(pools[i]).mul(usdLiquidity).div(1e18);
...
@> totalUsdLiquidity = totalUsdLiquidity.add(wellLiquidity);
...
}
...
// USD liquidity is scaled down from 1e18 to match Bean precision (1e6).
@> lpToSupplyRatio = Decimal.ratio(totalUsdLiquidity.div(LIQUIDITY_PRECISION), beanSupply);
}

Impact

SeasonGettersFacet.sol will return incorrect values in case Well with non-18 decimals is whitelisted.

Tools Used

Manual Review

Recommendations

getWellTwaUsdLiquidityFromReserves() must return result with 1e18 precision, so add up to 18 in case token decimals is less.

Updates

Lead Judging Commences

inallhonesty Lead Judge 12 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Appeal created

T1MOH Submitter
12 months ago
T1MOH Submitter
12 months ago
inallhonesty Lead Judge
12 months ago
inallhonesty Lead Judge 11 months ago
Submission Judgement Published
Validated
Assigned finding tags:

`LibWell.getWellTwaUsdLiquidityFromReserves()` returns liquidity with incorrect precision

Support

FAQs

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