DeFiHardhatFoundry
250,000 USDC
View results
Submission Details
Severity: high
Invalid

The current implementation of morningTemperature() is very inefficient for na L2

Summary

The current implementation of morningTemperature() is very inefficient for na L2

Vulnerability Details

To cater for the L2 smaller block time following new code is added into morningTemperature function

uint256 delta = block.number.sub(s.sys.season.sunriseBlock).mul(L2_BLOCK_TIME).div(
L1_BLOCK_TIME
);

Which basically converts the L2 changes in block in terms of L1, for example if the 12 second have passed on L2 which is 6 blocks, it will return back 1, because in terms of L1 only 1 block has passed.

Now based on the number of blocks, the scaling is done in following way where hard coded values are passed in for certain deltas where maximum scaling happens for delta grater than or equal to 24

if (delta < 13) {
if (delta < 7) {
if (delta < 4) {
if (delta < 2) {
// delta == 0, same block as sunrise
if (delta < 1) {
return TEMPERATURE_PRECISION;
}
// delta == 1
else {
return _scaleTemperature(279415312704);
}
}
if (delta == 2) {
return _scaleTemperature(409336034395);
} else {
// delta == 3
return _scaleTemperature(494912626048);
}
}
if (delta < 6) {
if (delta == 4) {
return _scaleTemperature(558830625409);
} else {
// delta == 5
return _scaleTemperature(609868162219);
}
} else {
// delta == 6
// there is around 3 percent difference in 6 and 7u
return _scaleTemperature(652355825780);
}
}
if (delta < 10) {
if (delta < 9) {
if (delta == 7) {
return _scaleTemperature(688751347100);
} else {
// delta == 8
return _scaleTemperature(720584687295);
}
} else {
// delta == 9
return _scaleTemperature(748873234524);
}
}
if (delta < 12) {
if (delta == 10) {
return _scaleTemperature(774327938752);
} else {
// delta == 11
return _scaleTemperature(797465225780);
}
} else {
// delta == 12
return _scaleTemperature(818672068791);
}
}
if (delta < 19) {
if (delta < 16) {
if (delta < 15) {
if (delta == 13) {
return _scaleTemperature(838245938114);
} else {
// delta == 14
return _scaleTemperature(856420437864);
}
} else {
// delta == 15
return _scaleTemperature(873382373802);
}
}
if (delta < 18) {
if (delta == 16) {
return _scaleTemperature(889283474924);
} else {
// delta == 17
return _scaleTemperature(904248660443);
}
} else {
// delta == 18
return _scaleTemperature(918382006208);
}
}
if (delta < 22) {
if (delta < 21) {
if (delta == 19) {
return _scaleTemperature(931771138485);
} else {
// delta == 20
return _scaleTemperature(944490527707);
}
} else {
// delta = 21
return _scaleTemperature(956603996980);
}
}
if (delta <= 23) {
if (delta == 22) {
return _scaleTemperature(968166659804);
} else {
// delta == 23
return _scaleTemperature(979226436102);
}
} else {
// delta == 24
return _scaleTemperature(989825252096);
}

But the problem here is, this is not the right approach to handle this for an L2, one L1 there are 12 seconds block time and you go directly from block 1 to 2, block 2 to 3. You can't go from block 3 to 3.5 but in current implementaion this is possible and we can get better result using the formula on chain og51(2x+1) which is the formula that is applied behind these hard codings by using the higher precision for the delta.

For example consider the following scenerio

block.number - sunriseBlock = 24
27 * 2 = 54
54 / 12 = 4.5

So the delta will be rounded down to 4, and it will use the value 558830625409 while the formula yeilds 5804892177 which is a 3% difference that is a very significant difference for defi applications like beanstalk and skew multiple calculation functions in field facet.

So just to summarize, problem arises from not using larger precision for the delta and than hardcoding formula results which don't let calculate any other values except which are hardcoded. This is done to save gas but on L2 that is not gonna be concern for beanstalk and this is also the primary reason to move to L2 to cost less gas to users.

Impact

High because the results are skewed by several percents and chances of it happening are very high.

Tools Used

Brain

Recommendations

Use higher precision for delta and use the formula on chain PRB math library which is already integrated into contracts.

Updates

Lead Judging Commences

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

Support

FAQs

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