Lucene search

K
code423n4Code4renaCODE423N4:2023-11-BETAFINANCE-FINDINGS-ISSUES-13
HistoryNov 05, 2023 - 12:00 a.m.

Users pay higher fee than intended

2023-11-0500:00:00
Code4rena
github.com
2
reserve fee
interest calculation
vulnerability
code audit

7.2 High

AI Score

Confidence

High

Lines of code

Vulnerability details

Impact

Protocol mints incorrect depositAmount and depositShare to protocol. Such that reserveFee is higher than defined. Suppose following scenario:

  1. Tranche 2 has 20% APR, has 5_000 borrowed
  2. Tranche 1 has 10% APR, has 10_000 borrowed
  3. ReserveFee is 10%
  4. It means that reserveFee that must be payed after 1 year is 5_000 * 20% * 10% + 10_000 * 10% * 10% = 200. However current implementation will calculate 208, which will be shown PoC.

Lender pays this extra fee.

Proof of Concept

Here is gist with all tests <https://gist.github.com/T1MOH593/34729b5333fe43eb58cf8b4948ef137f&gt;

First part: show that issue exists. It is shown in custom_test1()

Second part: what is the issue.
Let’s set initial values, for example:
Tranche 2 has 20% APR, 5_000 borrowed, 20_000 deposited; Tranche 1 has 10% APR, 10_000 borrowed, 20_000 depositeed. And we use 1 year as time difference to ease calculations.
Tranche struct has 2 types of variables, let’s focus regarding deposit: totalDepositAmount and totalDepositShare. Initially without accrued interest they equal, 1 : 1, in above scenario will be 20_000 in both tranches. As the time passes, interest accrues. It means that totalDepositAmount increases. If reserveFee is 0%, that’s it - for example 1000 of interests accrued, totalDepositAmount is increased by 1000.

However in case 10% of interest must be payed to reserve. It means that extra shares will be minted increasing totalDepositShare AND totalDepositAmount should be also increased because otherwise user’s balance will decrease. Let’s take delta of totalDepositAmount as X and totalDepositShare as Y. And calculate these values for above scenario.

  • Total interest for Tranche2 is 5_000 * 20% = 1_000. For Tranche1 is 10_000 * 10% = 1_000

  • Interest for Tranche 2 stays in this tranche. Interest for Tranche 1 is divided between tranche1 and tranche2 based on deposit amounts, such that tranche1 receives 1000 * 20_000 / 40_000 = 500, tranche2 receives 500 too. Finally tranche2 has 1500 of interest, tranche1 has 500 of interest

  • Reserve fee must be payed. 1500 * 10% = 150 in tranche2, and 500 * 10% = 50 in tranche1

  • We need to mint such amount of share Y to Reserve and increase totalDepositAmount by X so that Reserve balance is 150 AND User’s balance is 20_000 + 1500 * 90% = 21350 in Tranche2. So let’s create system of equations.

    (20_000 / (20_000 + Y)) * (20_000 + X) = 21_350 is balance of User
    Y / (20_000 + Y) * (20_000 + X) = 150 is balance of Reserve

Solving this we get X = 1500, Y = 140.51. I.e. 140.51 of shares must be minted to Reserve, and totalDepositAmount must be increased by 1500 (amount of accrued interest) in Tranche2.
Now let’s calculate accordingly for Tranche1:

(20_000 / (20_000 + Y)) * (20_000 + X) = 20_450 is balance of User
Y / (20_000 + Y) * (20_000 + X) = 50 is balance of Reserve

X = 500, Y = 48.89.

However current implementation mints 100 shares to Reserve and increases totalDepositAmount by 1450 in Tranche 2; Also mints 100 shares to reserve and increases totalDepositAmount by 550 in Tranche1 as shown in test custom_test2

That is core issue: code always mints amount of shares equal to reserveInterest to Reserve (100 in this example) and calculates sub-optimal amount of depositAmount to increase.

Tools Used

Foundry

Recommended Mitigation Steps

Fix is not obvious at all, it’s the most difficult part of report to be honest.
Algorithm should be completely refactored, should be implemented following accounting:

  • totalDepositAmount should be increased by the amount of accrued interest allocated to this tranche. From above example it’s 1500 for Tranche2 and 500 for Tranche1

  • Number of shares minted to reserve in tranche should be calculated as solution of one of these equations

    1. (totalDepositSharesOfTranceBeforeAccruing / (totalDepositSharesOfTranceBeforeAccruing + Y)) * (totalDepositAmountBeforeAccruing + interestAmountAllocatedToThisTrance) = totalDepositSharesOfTranceBeforeAccruing + interestAmountAllocatedToThisTrance * 0.9
      If we paste values from above example with Tranche 2, we get (20_000 / (20_000 + Y)) * (20_000 + 1_500) = 21_350
    2. (Y / (totalDepositSharesOfTranceBeforeAccruing + Y)) * (totalDepositAmountBeforeAccruing + interestAmountAllocatedToThisTrance) = interestAmountAllocatedToThisTrance * 0.9
      If we paste values from above example with Tranche 2, we get (Y / (20_000 + Y)) * (20_000 + 1_500) = 150

And also write tests to check reserveFee amounts, now they absent

Assessed type

Math


The text was updated successfully, but these errors were encountered:

All reactions

7.2 High

AI Score

Confidence

High