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

shipment barnReceive s.sys.fert.leftoverBeans missing state update

Line of code

https://github.com/Cyfrin/2024-05-beanstalk-the-finale/blob/df2dd129a878d16d4adc75049179ac0029d9a96b/protocol/contracts/libraries/LibReceiving.sol#L136

Summary

shipment barnReceive s.sys.fert.leftoverBeans missing state update

Vulnerability Details

// If the next fertilizer is going to run out, then step BPF according
while (newBpf >= firstBpf) {
// Increment the cumulative change in Fertilized.
deltaFertilized += (firstBpf - oldBpf) * s.sys.fert.activeFertilizer; // fertilizer between init and next cliff
if (LibFertilizer.pop()) {
oldBpf = firstBpf;
firstBpf = s.sys.fert.fertFirst;
// Calculate BPF beyond the first Fertilizer edge.
remainingBpf = (amountToFertilize - deltaFertilized) / s.sys.fert.activeFertilizer;
newBpf = oldBpf + remainingBpf;
}
// Else, if there is no more fertilizer. Matches plan cap.
else {
s.sys.fert.bpf = uint128(firstBpf); // SafeCast unnecessary here.
s.sys.fert.fertilizedIndex += deltaFertilized;
@ require(amountToFertilize == deltaFertilized, "Inexact amount of Beans at Barn");
require(s.sys.fert.fertilizedIndex == s.sys.fert.unfertilizedIndex, "Paid != owed");
return;
}
}
// Distribute the rest of the Fertilized Beans
s.sys.fert.bpf = uint128(newBpf); // SafeCast unnecessary here.
deltaFertilized += (remainingBpf * s.sys.fert.activeFertilizer);
s.sys.fert.fertilizedIndex += deltaFertilized;
// There will be up to activeFertilizer Beans leftover Beans that are not fertilized.
// These leftovers will be applied on future Fertilizer receipts.
@ s.sys.fert.leftoverBeans = amountToFertilize - deltaFertilized;

In the code block above if we hit the else block, we will return and the remaining logic will not execute. More specifically we can observe the code block below.

s.sys.fert.bpf = uint128(firstBpf); // SafeCast unnecessary here.
s.sys.fert.fertilizedIndex += deltaFertilized;
require(amountToFertilize == deltaFertilized, "Inexact amount of Beans at Barn");
require(s.sys.fert.fertilizedIndex == s.sys.fert.unfertilizedIndex, "Paid != owed");
return;

the code returns early, while amountToFertilize == deltaFertilized,, the code needs to reset leftoverBeans and set it to 0 but failed to reset leftoverBeans to 0

Impact

There will be up to activeFertilizer Beans leftover Beans that are not fertilized, These leftovers will be applied on future Fertilizer receipts, but in this case, there is no leftovers and should not be applied on future Fertilizer receipts, otherwise future Fertilizer receipts is incorrectly inflated when computing the function

https://github.com/Cyfrin/2024-05-beanstalk-the-finale/blob/df2dd129a878d16d4adc75049179ac0029d9a96b/protocol/contracts/beanstalk/Invariable.sol#L186

getTokenEntitlementsAndBalances, thus make all function that consume

https://github.com/Cyfrin/2024-05-beanstalk-the-finale/blob/df2dd129a878d16d4adc75049179ac0029d9a96b/protocol/contracts/beanstalk/Invariable.sol#L35

the modifier fundSafe inaccurate.

Tools Used

Manual review

Recommendations

ensure we reset the leftoverBeans by setting the value to 0 in the codeblock before returning.

s.sys.fert.leftoverBeans = 0;
Updates

Lead Judging Commences

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

shipment barnReceive s.sys.fert.leftoverBeans missing state update

Appeal created

asefewwexa Submitter
11 months ago
T1MOH Judge
11 months ago
inallhonesty Lead Judge
10 months ago
inallhonesty Lead Judge 10 months ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement
Assigned finding tags:

shipment barnReceive s.sys.fert.leftoverBeans missing state update

Support

FAQs

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