Summary
setSoilAbovePeg
from Sun.sol
contains two instances of precision loss due to division before multiplication which lowers the newSoil
issued both when Pod Rate is high and Pod Rate is low.
Vulnerability Details
The setSoilAbovePeg
function first computes the newSoil
by multiplying the newHarvestable
with 100 and dividing it by (100 + s.w.t)
, then depending on the caseId
this is again multiplied by the appropriate SOIL_COEFFICIENT
(be it HIGH or LOW) then again it's divided by the C.PRECISION
.
The newSoil
ends up truncated twice, resulting in a lower overall value.
function setSoilAbovePeg(uint256 newHarvestable, uint256 caseId) internal {
uint256 newSoil = newHarvestable.mul(100).div(100 + s.w.t);
if (caseId >= 24) {
newSoil = newSoil.mul(SOIL_COEFFICIENT_HIGH).div(C.PRECISION);
} else if (caseId < 8) {
newSoil = newSoil.mul(SOIL_COEFFICIENT_LOW).div(C.PRECISION);
}
setSoil(newSoil);
}
Impact
This has various consequences. The inline comments describe the following mechanism:
`* When the Pod Rate is high, Beanstalk issues less Soil.` - even less soil will be issued
`* When the Pod Rate is low, Beanstalk issues more Soil.` - it won't be that `more` because it's truncated twice.
Likelihood is High because it happens everytime.
Impact is low/medium because the truncated amount is small, but still, it happens very often.
Tools Used
Manual review
Recommendations
Perform the following changes:
function setSoilAbovePeg(uint256 newHarvestable, uint256 caseId) internal {
-- uint256 newSoil = newHarvestable.mul(100).div(100 + s.w.t);
-- if (caseId >= 24) {
-- newSoil = newSoil.mul(SOIL_COEFFICIENT_HIGH).div(C.PRECISION); // high podrate
-- } else if (caseId < 8) {
-- newSoil = newSoil.mul(SOIL_COEFFICIENT_LOW).div(C.PRECISION); // low podrate
-- }
++ uint256 newSoil;
++ if (caseId >= 24) {
++ newSoil = newHarvestable.mul(100).mul(SOIL_COEFFICIENT_HIGH).div(100 + s.w.t).div(C.PRECISION); // high podrate
++ } else if (caseId < 8) {
++ newSoil = newHarvestable.mul(100).mul(SOIL_COEFFICIENT_LOW).div(100 + s.w.t).div(C.PRECISION); // low podrate
++ }
setSoil(newSoil);
}