code-423n4 / 2024-03-dittoeth-findings

0 stars 0 forks source link

A successfully disputed redemption proposal has still increased the redemption fee base rate; exploit to depeg dUSD #274

Open c4-bot-9 opened 7 months ago

c4-bot-9 commented 7 months ago

Lines of code

https://github.com/code-423n4/2024-03-dittoeth/blob/91faf46078bb6fe8ce9f55bcb717e5d2d302d22e/contracts/facets/RedemptionFacet.sol#L204

Vulnerability details

Impact

Redemptions may not be incentivized to increase the value of dUSD. Furthermore, this may be deliberately induced to prevent a falling dUSD from repegging, ultimately causing dUSD to fully depeg and crash. The motivations for this attack could be anything from pure spite (perhaps from a competitor)

Root cause and summary

The most fundamental root cause of this issue and exploit is that the base rate in the redemption fee is increased when a redemption is proposed but not restored (decreased) if the redemption is successfully disputed. When dUSD is trading below the dollar, redemptions are needed to restore the peg. The redemption fee regulates the incentive to redeem dUSD. So if the redemption fee is increased, without contributing to the peg restoration by decreasing the supply of dUSD, the peg restoration mechanism is impeded and sufficient redemptions will not happen. A sufficiently high redemption fee will make any redemption a loss for the redeemer, which means that the peg will not be restored. This issue becomes viable as a direct exploit because of multiple factors reducing its cost to the attacker. These are

  1. The attacker can avoid paying the penalty by disputing his own proposal (using a different account).
  2. The redemption fee contains an added base fee of 0.5% which reduces the required amount to propose, on which the fee is paid.
  3. a. The total redemption fee decreases, down to almost a half, if the proposed amount is split over several redemption proposals. b. By splitting the total proposed amount the attacker only needs to escrow dUSD for one such part (at a time), which minimizes his own loss on his devalued dUSD.
  4. The redemption fee is proportional to the collateral that would be redeemed, which is capped to the short record's collateral balance, whereas the base rate is increased based on the amount proposed, which is not reduced accordingly. This can only be leveraged if there exists an undercollateralized short record. But if there is, this can be leveraged to make this exploit essentially for free for about 48 hours.

With the possible exception of 1. all of the above are issues in their own right, especially 4. which is therefore also reported separately. The impact of 2. and 3. is subject to the model used for how (quantitatively) redemptions restore the peg, and therefore discussed below rather than reported separately.

Proof of Concept

The goal of this exploit is to cause a persistent and complete loss of incentive to redeem dUSD, such that a dUSD trading below the dollar fails to recover its peg. There is some level below which dUSD is critically depegged. This is at least at the level where it becomes undercollateralized. For example, if the total collateral ratio is 1.25, this would happen if dUSD trades at $0.80. However, there is also a psychological and interfacing aspect. Since dUSD is supposed to maintain a 1:1 peg, if dUSD persistently trades at $0.90 or even $0.95, users might become suspicious, lose interest, or deem dUSD unsuitable or broken, which would cause it to further depeg. Therefore, any significant depeg will become critical if it is also persistent over time. It is assumed that there are always market forces (randomly) pushing the value of dUSD down, which is why the peg restoration mechanism through redemptions is necessary. If redemptions are prevented it is therefore assumed that these forces will take over and keep pushing dUSD downwards. A complete collapse of dUSD is not necessarily the goal. This could also be profited from as a kind of market manipulation where the attacker crashes the price to buy cheap dUSD, and then lets the redemption incentive back in and redeem his cheaply gotten dUSD (for real this time). The exploit will thus be considered successful if redemptions are prevented throughout the time it takes dUSD to drop from $1.00 to e.g. $0.95 and then keep preventing redemptions for some time.

The redemption fee is redemptionRate * redemptionAmount (redemptionAmount in USD value or dUSD equivalently). The profit on a redemption is (1 - price) * redemptionAmount - redemptionRate * redemptionAmount. Thus, whenever redemptionRate >= (1 - price) there is no profit to be made on redemptions. This is the redemption rate we want to maintain.

When a redemption is proposed the redemption fee is calculated. This updates the baseRate. When a redemption proposal is disputed nothing is done to the baseRate. This is the root cause of this issue.

When a redemption proposal is disputed the redemption proposer gets back the entire amount proposed minus the penalty. This means that if the disputer and the proposer is the same person (using different addresses, since they cannot be the same) then the penalty is not lost. The attack would be performed as a proposal atomically followed by a dispute. This shows 1. in the list above.

The redemption proposer still has to pay the redemption fee however. We will now investigate how much this would cost the attacker.

Ignoring the decay for now, when an amount a is proposed the base rate increases by a / (2 * totalSupply), where totalSupply is the total supply of dUSD, i.e. the total ercDebt.

Since a base rate of 0.5% is always added (point 2.), we only need to keep the base rate at 1 - price - 0.005.

Assuming an initial base rate of 0, to bring the base rate up to 1 - price - 0.005 we would then propose a = (1 - price - 0.005) * 2 * totalSupply. The redemption fee would then be (1 - price) * (1 - price - 0.005) * 2 * totalSupply. For price = 0.95 this is 0.0045 * totalSupply.

If we split the amount a into n smaller parts each of size a/n then the base rate will increase (a/n) / (2 * totalSupply) each time (so we still need to propose the same total amount), but the redemption fee on the kth time will only be a/n * (k * (a/n) / (2 * totalSupply) + 0.005). (Note that if each proposals is immediately disputed then totalSupply remains constant, otherwise totalSupply decreases slightly each time such that the redeemed fraction increases such that we can propose less overall for even lower fees.) Summed over all k this is a^2 * n*(n+1) / (n^2 * 4 * totalSupply) + 0.005 * a. The limit for high n is a * (a / (4 * totalSupply) + 0.005 * a). Substituting a from above we get that the total fees are ((1 - price)^2 - 2.5e-5) * totalSupply, which is almost half of the single proposal cost. For price = 0.95 this is 0.002475 * totalSupply.

Let's now consider the cost of working against the decay of the base rate. After t hours the base rate has decayed by a factor 2^(-t/12). In order to bring the redemption rate back up to 1 - price we need to propose another (1 - price - (1 - price)*2^(-t/12)) * 2 * totalSupply, on which we pay in fees (1 - price)^2 * (1 - 2^(-t/12)) * 2 * totalSupply. In the best case we only need to do this very rarely, and the average cost per hours then tends to zero. In the worst case, if we have to propose continuously, the limit is (1 - price)^2 * 2 * totalSupply * ln(2)/12 per hour. For price = 0.95 this is 0.00029 * totalSupply in the worst case.

Finally let's discuss point 4. If the short record holds less collateral than can cover the proposed amount, then it is capped to whatever it does hold. The proposed amount, however, is not reduced. These are passed to the calculation of the redemption fee, and it is the collateral redeemed that is multiplied by the redemption rate, while the base rate is increased based on the amount proposed (ercDebtRedeemed). This means that we pay a smaller fee than we should. Once there is an undercollateralized short record we can first partially redeem it so that almost no (or zero?) collateral remains. This decreases the collateral to almost 0, while some debt still remains. Performing our attack with two such short records, we can make and dispute proposals where the fees are almost zero but still increase the base rate each time. We can now blow up the redemption rate to the maximum 100% essentially for free. This will decay down to 6.25% in 48 hours, which is sufficient to prevent redemptions down to a price of 0.9325. These severely undercollateralized short records may of course be immediately proposed and claimed by anyone, but it is not necessarily likely that anyone will do that, since there is no profit to be made. We might therefore be able to repeat this every 48 hours (or more often) and maintain an arbitrarily high redemption rate almost for free.

Bonus note on 2. and 3.

The redemption fee mechanism is clearly intended to be optimal for redemption amounts which reduce the supply in accordance with the Quantity Theory of Money. However, the added 0.5% fee disrupts this and makes redemption optimal for a amount insufficient to restore the peg. The intention behind the 0.5% is probably to not allow free redemptions and to bring in some profit to the protocol, but it does not make sense to always add it. It should then be only a lower limit. Furthermore, this optimality is only valid under the assumption that redemptions are proposed in wholes, and not split up. As seen above, more can profitably be redeemed if the redemption is split in many small parts. This causes redemptions to overshoot, causing the price to increase above $1.00 (as per QTM). This is not as straightforward to fix, but one solution might be to only allow sufficiently large proposed amounts. It should also of course be possible to redesign the peg stabilization mechanism, by some direct reference to the deviation from the peg, since this deviation is explicitly know through the oracle price.

Recommended Mitigation Steps

Make sure the base rate is unaffected by a proposal which is successfully disputed. It might be tricky to account for the decay if attempting to later subtract when disputing. A possible solution might be to simply calculate and apply the new rate only when a proposal is successfully claimed.

Assessed type

Other

c4-pre-sort commented 7 months ago

raymondfam marked the issue as sufficient quality report

c4-pre-sort commented 7 months ago

raymondfam marked the issue as primary issue

raymondfam commented 7 months ago

Inadequate system measures to stem devaluing dUSD.

c4-sponsor commented 7 months ago

ditto-eth (sponsor) confirmed

c4-judge commented 7 months ago

hansfriese marked the issue as satisfactory

c4-judge commented 7 months ago

hansfriese marked the issue as selected for report