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

`getPercentPenalty` returns penalized underlying instead of a percentage

Description

The getPercentPenalty function is designed to return the percentage of tokens that can be retrieved if a user decides to chop their unripe tokens. Following the latest update, the new chop rate is calculated as (recapitalized percent)^2. However, there's an issue when unripeToken == C.UNRIPE_BEAN. In this case, the function returns the penalized underlying value, not the expected percentage. This could lead to unexpected behavior if any entity or individual uses this function to obtain a percentage.

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);
}
}
function getPenalizedUnderlying(
address unripeToken,
uint256 amount,
uint256 supply
) internal view returns (uint256 redeem) {
...
uint256 underlyingAmount = s.u[unripeToken].balanceOfUnderlying;
@> redeem = underlyingAmount.mul(s.recapitalized).div(totalUsdNeeded).mul(amount).div(supply);
// cap `redeem to `balanceOfUnderlying in the case that `s.recapitalized` exceeds `totalUsdNeeded`.
// this can occur due to unripe LP chops.
@> if (redeem > underlyingAmount) redeem = underlyingAmount;
}

Risk: Medium

Likelyhood: Medium/High

  • Every time this function is called with UNRIPE_BEAN token.

  • There is no usage in the protocol but could be high if the Beanstalk dApps or any other protocols/users rely on it.

Impact: Medium/High

  • Return an integer number with 6 decimals (>=1e6) instead of a percentage (1e6>=). It will lead the caller to retrieve an incorrect nubme and could result in unexpected behavior.

Given the available context, this appears to be at least a medium severity bug.

Recommended Mitigation

Since the recapitalization percent is calculated using the UnripeLP supply (even for UNRIPE_BEAN), remove all conditions and retain only the code in the second if statement:

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);
+ return
+ LibUnripe
+ .getTotalRecapitalizedPercent()
+ .mul(LibUnripe.getTotalRecapitalizedPercent())
+ .div(LibUnripe.DECIMALS);
- }
}
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.