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

Incorrect Penalty Percentage Calculation in `getPercentPenalty` Function for `C.UNRIPE_BEAN`

Summary

The getPercentPenalty function in the UnripeFacet.sol contract incorrectly calculates the penalty percentage for C.UNRIPE_BEAN by using LibUnripe.getPenalizedUnderlying intended to return the amount of redeemable tokens, not a percentage. This results in the function returning incorrect values that do not represent the intended penalty percentage.

Vulnerability Details

Let's look at this function:

https://github.com/Cyfrin/2024-05-Beanstalk-3/blob/662d26f12ee219ee92dc485c06e01a4cb5ee8dfb/protocol/contracts/beanstalk/barn/UnripeFacet.sol#L233-L247

function getPercentPenalty(address unripeToken) external view returns (uint256 penalty) {
if (unripeToken == C.UNRIPE_BEAN) {
return LibUnripe.getPenalizedUnderlying(
unripeToken,
LibUnripe.DECIMALS,
IERC20(unripeToken).totalSupply()
);
}
if (unripeToken == C.UNRIPE_LP) {
return LibUnripe.getTotalRecapitalizedPercent()
.mul(LibUnripe.getTotalRecapitalizedPercent())
.div(LibUnripe.DECIMALS);
}
}

Here is LibUnripe.getPenalizedUnderlying function used for C.UNRIPE_BEAN:

https://github.com/Cyfrin/2024-05-Beanstalk-3/blob/662d26f12ee219ee92dc485c06e01a4cb5ee8dfb/protocol/contracts/libraries/LibUnripe.sol#L149-L172

function getPenalizedUnderlying(
address unripeToken,
uint256 amount,
uint256 supply
) internal view returns (uint256 redeem) {
// Calculation logic that returns an amount, not a percentage
}

Scenario

Suppose the total supply of C.UNRIPE_BEAN is 1,000,000 tokens and the current recapitalization allows for 500,000 tokens to be redeemed. If we use LibUnripe.DECIMALS, which equals 1,000,000 as an input parameter representing 'amount' in this context to calculate penalties based on amounts instead of percentages. The returned value might suggest a 50% rate when it actually represents 500,000 redeemable beans - misleading users about actual penalties involved when converting their Unripened Beans into Ripe Beans.

Impact

This issue leads to incorrect penalty calculations, potentially causing users to be misinformed about the penalties associated with converting their unripe tokens into ripe tokens. This can affect the protocol at large

Tools Used

Manual review

Recommendations

Ensure that the penalty calculation for C.UNRIPE_BEAN correctly computes a percentage value, and add a default return statement to handle cases where unripeToken does not match any expected values.

function getPercentPenalty(address unripeToken) external view returns (uint256 penalty) {
if (unripeToken == C.UNRIPE_BEAN) {
uint256 recapPercent = LibUnripe.percentBeansRecapped();
return recapPercent.mul(recapPercent).div(LibUnripe.DECIMALS);
}
if (unripeToken == C.UNRIPE_LP) {
uint256 recapPercent = LibUnripe.percentLPRecapped();
return recapPercent.mul(recapPercent).div(LibUnripe.DECIMALS);
}
return 0; // Default return if unripeToken does not match any known tokens
}

This correction ensures that the function returns a penalty percentage for both C.UNRIPE_BEAN and C.UNRIPE_LP based on the square of the recapitalized percentage, and it handles other tokens by returning 0, which is a safe default.

Updates

Lead Judging Commences

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.