DeFiHardhat
21,000 USDC
View results
Submission Details
Severity: low
Invalid

Missing `s.fertilizedIndex == s.unfertilizedIndex` check in `Sun::rewardToFertilizer` Function

Summary

The rewardToFertilizer function in the Sun.sol contract is to distribute rewards to fertilizers by calculating and updating various state variables.In the function s.fertilizedIndex == s.unfertilizedIndex check is missing in the final part of the function.

Vulnerability Details

The function updates the s.bpf and s.fertilizedIndex variables at the end, but it lacks a consistency check that ensures the total fertilized beans are as expected. Specifically, the following lines are missing:

require(s.fertilizedIndex == s.unfertilizedIndex, "Paid != owed");

Without this check, the contract might end up with an inconsistent state where s.fertilizedIndex does not match s.unfertilizedIndex.

Tools Used

Manual Review

Recommendations

function rewardToFertilizer(uint256 amount)
internal
returns (uint256 newFertilized)
{
// 1/3 of new Beans being minted
uint256 maxNewFertilized = amount.div(FERTILIZER_DENOMINATOR);
// Get the new Beans per Fertilizer and the total new Beans per Fertilizer
uint256 newBpf = maxNewFertilized.div(s.activeFertilizer);
uint256 oldTotalBpf = s.bpf;
uint256 newTotalBpf = oldTotalBpf.add(newBpf);
// Get the end Beans per Fertilizer of the first Fertilizer to run out.
uint256 firstEndBpf = s.fFirst;
// If the next fertilizer is going to run out, then step BPF according
while(newTotalBpf >= firstEndBpf) {
// Calculate BPF and new Fertilized when the next Fertilizer ID ends
newBpf = firstEndBpf.sub(oldTotalBpf);
newFertilized = newFertilized.add(newBpf.mul(s.activeFertilizer));
// If there is no more fertilizer, end
if (!LibFertilizer.pop()) {
s.bpf = uint128(firstEndBpf); // SafeCast unnecessary here.
s.fertilizedIndex = s.fertilizedIndex.add(newFertilized);
require(s.fertilizedIndex == s.unfertilizedIndex, "Paid != owed");
return newFertilized;
}
// Calculate new Beans per Fertilizer values
newBpf = maxNewFertilized.sub(newFertilized).div(s.activeFertilizer);
oldTotalBpf = firstEndBpf;
newTotalBpf = oldTotalBpf.add(newBpf);
firstEndBpf = s.fFirst;
}
// Distribute the rest of the Fertilized Beans
s.bpf = uint128(newTotalBpf); // SafeCast unnecessary here.
newFertilized = newFertilized.add(newBpf.mul(s.activeFertilizer));
s.fertilizedIndex = s.fertilizedIndex.add(newFertilized);
+ require(s.fertilizedIndex == s.unfertilizedIndex, "Paid != owed");
}
Updates

Lead Judging Commences

giovannidisiena Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement
hunter_w3b Submitter
about 1 year ago
giovannidisiena Lead Judge
about 1 year ago
giovannidisiena Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

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