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

Unchecked endStem must be larger than startStem in `LibSilo.sol:stalkReward` could lead to a huge amount reward when the int96 value is negative

Summary

The calculation of the Stalk reward is based on the start stems, end stems, and the amount of BDV deposited. The comment states that 'endStem must be larger than startStem.', however there is no check to ensure endStem is larger than startStem. When endStem is less than startStem, resulting in a negative value for endStem.sub(startStem). When the calculation converts a negative int96 value to uint96, it leads to an unexpected large positive value due to how unsigned integers handle negative values. This can cause the calculation to produce incorrect results.

https://github.com/Cyfrin/2024-05-beanstalk-the-finale/blob/main/protocol/contracts/libraries/Silo/LibSilo.sol#L658-L669

POC

Test:

function sub(int96 a, int96 b) internal pure returns (int96) {
return a - b;
}
function testStalkReward() public {
int96 startStem = 2;
int96 endStem = 1;
uint128 bdv = 1;
// Calculate correct value: 1 - 2
int96 correct = sub(endStem, startStem);
console.logInt(correct);
// Cast the negative int96 value to uint96
uint96 endStemSmallerThanStartStem = uint96(sub(endStem, startStem));
console.log("endStemSmallerThanStartStem:", endStemSmallerThanStartStem);
// Use LibSilo.stalkReward for testing
uint256 reward = LibSilo.stalkReward(startStem, endStem, bdv);
console.log("reward:", reward);
}

Result:

Logs:
-1
endStemSmallerThanStartStem: 79228162514264337593543950335
reward: 79228162514264337593543

Impact

When the calculation converts a negative int96 value to uint96, it leads to an unexpected large positive reward. This can cause the calculation to produce incorrect results.

Tools Used

Manual review & Foundry

Recommendations

function stalkReward(
int96 startStem,
int96 endStem,
uint128 bdv
) internal pure returns (uint256) {
+ require(endStem > startStem, 'endStem is less than or equal to startStem');
uint128 reward = uint128(uint96(endStem.sub(startStem))).mul(bdv).div(PRECISION);
return reward;
}
Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement
Assigned finding tags:

'endStem must be larger than startStem' never enforced in LibSilo::stalkReward

Support

FAQs

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