DeFiHardhatOracleProxyUpdates
100,000 USDC
View results
Submission Details
Severity: low
Invalid

Divide before multiply

Summary

Division before multiplication or Multiplication on a result of a division will result in loss of precision and wrong results.

Vulnerability Details

File: contracts/libraries/LibFertilizer.sol
/// @audit ******************* Issue Detail *******************
LibFertilizer.addUnderlying(uint256,uint256) (contracts/libraries/LibFertilizer.sol#80-124) performs a multiplication on the result of a division:
- percentToFill = usdAmount.mul(C.precision()).div(remainingRecapitalization()) (contracts/libraries/LibFertilizer.sol#83-85)
- newDepositedBeans = newDepositedBeans.mul(percentToFill).div(C.precision()) (contracts/libraries/LibFertilizer.sol#92-94)
/// @audit ************** Possible Issue Line(s) **************
L#83-85, L#92-94,
/// @audit ****************** Affected Code *******************
83: uint256 percentToFill = usdAmount.mul(C.precision()).div(
84: remainingRecapitalization()
85: );
92: newDepositedBeans = newDepositedBeans.mul(percentToFill).div(
93: C.precision()
94: );

GitHub : 80-124

File: contracts/beanstalk/sun/SeasonFacet/Sun.sol
/// @audit ******************* Issue Detail *******************
Sun.rewardToFertilizer(uint256) (contracts/beanstalk/sun/SeasonFacet/Sun.sol#109-149) performs a multiplication on the result of a division:
- newBpf = maxNewFertilized.div(s.activeFertilizer) (contracts/beanstalk/sun/SeasonFacet/Sun.sol#117)
- newFertilized = newFertilized.add(newBpf.mul(s.activeFertilizer)) (contracts/beanstalk/sun/SeasonFacet/Sun.sol#128)
/// @audit ************** Possible Issue Line(s) **************
L#117, L#128,
/// @audit ****************** Affected Code *******************
117: uint256 newBpf = maxNewFertilized.div(s.activeFertilizer);
128: newFertilized = newFertilized.add(newBpf.mul(s.activeFertilizer));

GitHub : 109-149

File: contracts/libraries/LibGauge.sol
/// @audit ******************* Issue Detail *******************
LibGauge.updateGrownStalkEarnedPerSeason(uint256,LibGauge.LpGaugePointData[],uint256,uint256) (contracts/libraries/LibGauge.sol#214-271) performs a multiplication on the result of a division:
- beanGpPerBdv = maxLpGpPerBdv.mul(beanToMaxLpGpPerBdvRatio).div(100e18) (contracts/libraries/LibGauge.sol#235)
- totalGaugePoints = totalGaugePoints.add(beanGpPerBdv.mul(beanDepositedBdv).div(BDV_PRECISION)) (contracts/libraries/LibGauge.sol#237-239)
/// @audit ************** Possible Issue Line(s) **************
L#235, L#237-239,
/// @audit ****************** Affected Code *******************
235: uint256 beanGpPerBdv = maxLpGpPerBdv.mul(beanToMaxLpGpPerBdvRatio).div(100e18);
237: totalGaugePoints = totalGaugePoints.add(
238: beanGpPerBdv.mul(beanDepositedBdv).div(BDV_PRECISION)
239: );

GitHub : 214-271

File: contracts/beanstalk/sun/SeasonFacet/Sun.sol
/// @audit ******************* Issue Detail *******************
Sun.setSoilAbovePeg(uint256,uint256) (contracts/beanstalk/sun/SeasonFacet/Sun.sol#216-224) performs a multiplication on the result of a division:
- newSoil = newSoil.mul(SOIL_COEFFICIENT_HIGH).div(C.PRECISION) (contracts/beanstalk/sun/SeasonFacet/Sun.sol#219)
- newSoil = newSoil.mul(SOIL_COEFFICIENT_LOW).div(C.PRECISION) (contracts/beanstalk/sun/SeasonFacet/Sun.sol#221)
/// @audit ************** Possible Issue Line(s) **************
L#219, L#221,
/// @audit ****************** Affected Code *******************
216: function setSoilAbovePeg(uint256 newHarvestable, uint256 caseId) internal {
217: uint256 newSoil = newHarvestable.mul(100).div(100 + s.w.t);
218: if (caseId >= 24) {
219: newSoil = newSoil.mul(SOIL_COEFFICIENT_HIGH).div(C.PRECISION); // high podrate
220: } else if (caseId < 8) {
221: newSoil = newSoil.mul(SOIL_COEFFICIENT_LOW).div(C.PRECISION); // low podrate
222: }
223: setSoil(newSoil);
224: }

GitHub : 216-224

File: contracts/libraries/LibGauge.sol
/// @audit ******************* Issue Detail *******************
LibGauge.updateGrownStalkEarnedPerSeason(uint256,LibGauge.LpGaugePointData[],uint256,uint256) (contracts/libraries/LibGauge.sol#214-271) performs a multiplication on the result of a division:
- newGrownStalk = uint256(s.seedGauge.averageGrownStalkPerBdvPerSeason).mul(totalGaugeBdv).div(BDV_PRECISION) (contracts/libraries/LibGauge.sol#248-250)
- newGrownStalkPerGp = newGrownStalk.mul(GP_PRECISION).div(totalGaugePoints) (contracts/libraries/LibGauge.sol#253)
/// @audit ************** Possible Issue Line(s) **************
L#248-250, L#253,
/// @audit ****************** Affected Code *******************
248: uint256 newGrownStalk = uint256(s.seedGauge.averageGrownStalkPerBdvPerSeason)
249: .mul(totalGaugeBdv)
250: .div(BDV_PRECISION);
253: uint256 newGrownStalkPerGp = newGrownStalk.mul(GP_PRECISION).div(totalGaugePoints);

GitHub : 214-271

File: contracts/beanstalk/sun/SeasonFacet/Sun.sol
/// @audit ******************* Issue Detail *******************
Sun.rewardToFertilizer(uint256) (contracts/beanstalk/sun/SeasonFacet/Sun.sol#109-149) performs a multiplication on the result of a division:
- newBpf = maxNewFertilized.div(s.activeFertilizer) (contracts/beanstalk/sun/SeasonFacet/Sun.sol#117)
- newFertilized = newFertilized.add(newBpf.mul(s.activeFertilizer)) (contracts/beanstalk/sun/SeasonFacet/Sun.sol#147)
/// @audit ************** Possible Issue Line(s) **************
L#117, L#147,
/// @audit ****************** Affected Code *******************
117: uint256 newBpf = maxNewFertilized.div(s.activeFertilizer);
147: newFertilized = newFertilized.add(newBpf.mul(s.activeFertilizer));

GitHub : 109-149

File: contracts/libraries/LibFertilizer.sol
/// @audit ******************* Issue Detail *******************
LibFertilizer.remainingRecapitalization() (contracts/libraries/LibFertilizer.sol#155-168) performs a multiplication on the result of a division:
- totalDollars = totalDollars / 1e6 * 1e6 (contracts/libraries/LibFertilizer.sol#165)
/// @audit ************** Possible Issue Line(s) **************
L#165,
/// @audit ****************** Affected Code *******************
155: function remainingRecapitalization()
156: internal
157: view
158: returns (uint256 remaining)
159: {
160: AppStorage storage s = LibAppStorage.diamondStorage();
161: uint256 totalDollars = C
162: .dollarPerUnripeLP()
163: .mul(C.unripeLP().totalSupply())
164: .div(DECIMALS);
165: totalDollars = totalDollars / 1e6 * 1e6; // round down to nearest USDC
166: if (s.recapitalized >= totalDollars) return 0;
167: return totalDollars.sub(s.recapitalized);
168: }

GitHub : 155-168

Impact

Possible loss of funds due to precision loss.

Tools Used

Manual Aided Review

Recommendations

Use multiplication before division.

Updates

Lead Judging Commences

giovannidisiena Lead Judge over 1 year ago
Submission Judgement Published
Invalidated
Reason: Too generic
Assigned finding tags:

Informational/Invalid

Support

FAQs

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