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

ReseedField.sol incorrectly configures Field values because of mistake in storage layout

Summary

Previously there was single Field, so variable s.sys.field in storage contained data about Pods. Now field data is stored in mapping(uint256 => Field) fields.

Problem is that variable s.sys.field is forgotten to delete. And this variable by mistake configured in ReseedField instead of actual mapping s.sys.fields.

Vulnerability Details

Here you can see that s.sys.field is configured:
https://github.com/Cyfrin/2024-05-beanstalk-the-finale/blob/df2dd129a878d16d4adc75049179ac0029d9a96b/protocol/contracts/beanstalk/init/reseed/L2/ReseedField.sol#L64-L66

function init(
MigratedPlotData[] calldata accountPlots,
uint256 totalPods,
uint256 harvestable,
uint256 harvested,
uint256 fieldId,
uint8 initialTemperature
) external {
...
s.sys.field.pods = totalPods;
s.sys.field.harvestable = harvestable;
s.sys.field.harvested = harvested;
...
}

However protocol never uses s.sys.field. It uses s.sys.fields[fieldId] instead.

Impact

Field module is completely broken because Field's main variables are not initialized after migration. At least users can't harvest their Pods because their plotIndex is much bigger than current harvestable index (because s.sys.fields[fieldId].harvestable counts again from 0):
https://github.com/Cyfrin/2024-05-beanstalk-the-finale/blob/df2dd129a878d16d4adc75049179ac0029d9a96b/protocol/contracts/beanstalk/field/FieldFacet.sol#L169-L186

function _harvest(
uint256 fieldId,
uint256[] calldata plots
) internal returns (uint256 beansHarvested) {
for (uint256 i; i < plots.length; ++i) {
// The Plot is partially harvestable if its index is less than
// the current harvestable index.
@> require(plots[i] < s.sys.fields[fieldId].harvestable, "Field: Plot not Harvestable");
uint256 harvested = _harvestPlot(LibTractor._user(), fieldId, plots[i]);
beansHarvested += harvested;
}
s.sys.fields[fieldId].harvested += beansHarvested;
emit Harvest(LibTractor._user(), fieldId, plots, beansHarvested);
}

Additionally Invariable.sol uses uninitialized value to calculate minimum required balance:
https://github.com/Cyfrin/2024-05-beanstalk-the-finale/blob/df2dd129a878d16d4adc75049179ac0029d9a96b/protocol/contracts/beanstalk/Invariable.sol#L189

Tools Used

Manual Review

Recommendations

Configure s.sys.fields in ReseedField.sol and remove s.sys.field from storage.

Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

ReseedField.sol incorrectly configures Field values because of mistake in storage layout

Appeal created

T1MOH Submitter
about 1 year ago
0xgenaudits Judge
about 1 year ago
T1MOH Submitter
about 1 year ago
0xgenaudits Judge
about 1 year ago
inallhonesty Lead Judge
about 1 year ago
inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

ReseedField.sol incorrectly configures Field values because of mistake in storage layout

Support

FAQs

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