Currently, the redemption process leads to substantial precision loss, causing users to receive significantly less than anticipated for the tokens they provide. This arises from the sequence of operations used to calculate the redemption amount, particularly in the LibUnripe
library. The calculation involves dividing underlyingAmount.mul(s.recapitalized)
by totalUsdNeeded
before multiplying by amount/supply
, a method chosen to prevent a potential overflow of the calculation. However, this approach inadvertently shifts the burden of precision loss onto users, leading to discrepancies in the actual versus expected redemption amounts.
Whenever calculating the amount to be finally redeemed there is a heavy precision loss due to the order of operations which leads to users receiving way less than they are to get for the amount of tokens they provide.
Going through the code snippets this is finally done to get the amount to be redeemed https://github.com/Cyfrin/2024-05-Beanstalk-3/blob/662d26f12ee219ee92dc485c06e01a4cb5ee8dfb/protocol/contracts/libraries/LibUnripe.sol#L166-L167
Now keep in mind that logically we can conclude the value of totalUsdNeeded
is going to be very large considering it's decimals and all, showcasing how heavy the precision that's going to be lost would be.
Now going through the BIP-X: Misc Improvements whose changes this update contest was based on, we can see that this method of calculating the redeem
(i.e dividing underlyingAmount.mul(s.recapitalized
by totalUsdNeeded
before multiplying it by amount/supply
was hinted to be done so as to ensure that the attempt at calculating the redeem
value does not overflow and leads to a revert, Which also confirms our previous statement that indeed the
totalUsdNeeded
is to be considered as somewhat large. However doing it this way showcases protocol is solving the potential overflow issue by unfairly delegating the cost to users, since their assets would be deducted where they can easily just break the calculation and have a numerator denominator pattern.
Keep in mind that this function is directly queried whenever there is a need to chop
unripe tokens to ripe tokens in LibChop.chop()
Precision loss would constantly affect the amount of the tokens that gets redeemed for a user chopping their assets.
Manual review
Either bring all the multiplications ahead of the division, or break the calculation into two parts, implement it as something as:
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.