lindy-labs / opus_contracts

Opus Source Code
https://opus.money
Other
0 stars 0 forks source link

feat: handle exceptional redistributions using deficit for troves #532

Closed tserg closed 8 months ago

tserg commented 9 months ago

When a trove's debt is exceptionally redistributed, we let the yang accrue to the initial yang amount, and add the exceptionally redistributed debt to a deficit.

  1. Assuming Shrine has two troves with 1,000 debt each, the starting total_troves_debt is 2,000, and total yin is 2,000.
  2. One trove is being redistributed entirely where 800 debt is redistributed ordinarily, and another 200 debt is redistributed exceptionally. The recipient trove receives 800 debt, so its trove.debt is now at 1,800. The redistributed trove is completely redistributed, so its trove.debt is now at 0. The total_troves_debt has to remain at 2,000 because if the Shrine is shut now, the Caretaker needs to transfer enough yangs to back the 2,000 yin that originated from these two troves. The 200 debt that is exceptionally redistributed then gets added to a deficit, and in the event of shutdown, they are backed by the value of the initial yang amounts.
    • The relationship can be given as: total_troves_debt - deficit = [sum(trove.debt) for all troves]. Plucking in the figures, we get 2,000 - 200 = 1,800.

Continuing from this example, we assume that interest of 50 is then accrued on the remaining trove. Since there is a deficit of 200 debt, this interest of 50 is used to first reduce the deficit rather than being added to the budget as a surplus. This has the effect of transferring the backing for this 50 troves' debt deficit from the initial yang amount to the trove's debt. Note that we do not add this 50 interest to the surplus because the 50 yin corresponding to the 50 deficit reduced is already in circulation.


Why can we not use the budget to handle exceptional redistributions? i.e. add the deficit to the budget, and then as surplus comes in, the deficit is reduced.

If we use the budget, the Caretaker would end up using more yangs than needed to back the amount of yin originating from troves at the time of shutdown.

Assuming the same example above, where total_troves_debt is at 2,000, redistribution happens, and we add -200 to the budget instead. Another 200 interest is accrued on the remaining trove, which bumps total_troves_debt to 2,200, sum(trove.debt) to 2,000, and budget is now 0, with total_yin at 2,000. Now, shutdown occurs. The Caretaker would transfer yangs equivalent to 2,200 debt worth to back total_troves_debt when there is only 2,000 circulating yin. Each reclaim for 1 yin would end up receiving 1.1 yin worth of yangs instead.

[UPDATE - note that this PR would supercede #530 and #531]

tserg commented 9 months ago

What if the redistribution error would be also added to the budget? Does it make sense? The error is expected to be pretty small right? Not having to deal with it in subsequent redistributions would simplify the code further.

The redistribution error needs to backed by value, and in this case they would be backed by the initial yang amount. Since the error is expected to be pretty small, they should be easily covered as fees accrue, so I think this would work. In any case, there would already be loss of precision when reattributing the unit debt back to troves and these amounts would similarly be backed by the initial yang amount, so I do not think this is an issue.

what if the deficit will be payed off, is it ok to have the yangs still in initial_yang_amts?

The value would be locked up in Shrine, so it improves the Shrine's LTV. The issue is that they would still be stuck after shutdown. Maybe Caretaker should have another function for admin to withdraw initial yang amounts?

focus more on the budget, e.g. can we run into some FUBAR because of a chain of exceptional redistributions?

I realized that adding exceptionally redistributed debt to the budget is more tricky than I initially thought.

Consider this example where we assume Shrine has a single trove:

  1. A trove forges 1,000 debt, minting 1,000 yin into circulation. Total troves debt is 1,000.
  2. 200 debt is redistributed, and added to the budget as deficit. Total troves debt remains at 1,000.
  3. Interest of 200 accumulates. Now, as the code is, we add 200 to the budget so budget is back to zero, but we also add 200 to the total troves debt, so total troves debt is now 1,200, but total yin remains at 1,000.
  4. If the Caretaker shuts now, the amount of yin that will be backed is based on the total troves debt which is 1,200, but there is only 1,000 yin in circulation.

This gets even trickier once we have other modules adjusting the budget directly in the future, which means that we would not know how much of circulating yin should be backed by the Shrine's collateral.

The solution I have in mind is to introduce a new storage variable total_troves_deficit that is solely used for exceptional redistributions, and any additions to trove debt would go towards zero-ing this deficit first before adding to total_troves_debt.

tserg commented 9 months ago

One thing I am still trying to think through - if there is a positive budget adjustment for fees and interest from other modules like Transmuter and Bonds, should it also reduce the total troves' deficit?

I think it should, since the yin representing the redistributed debt would already be in circulation.

[UPDATE - I realized this should not be the case, because the deficit is linked to the total troves debt, and positive budget adjustment from other modules do not count towards total_troves_debt, so they should not affect the deficit. Another way of putting it is that only positive budget adjustments that would have increased the total troves debt can go towards reducing the total troves deficit.]

[UPDATE 2 - I made a mistake in the previous update. The correct statement should be that only increments to the total trove debt can go towards reducing the deficit, so this includes (1) forging of new debt; (2) interest; and (3) forge fees.]

milancermak commented 9 months ago

only positive budget adjustments that would have increased the total troves debt

That's only charge right?

milancermak commented 9 months ago

Consider this example where we assume Shrine has a single trove:

  1. A trove forges 1,000 debt, minting 1,000 yin into circulation. Total troves debt is 1,000.
  2. 200 debt is redistributed, and added to the budget as deficit. Total troves debt remains at 1,000.
  3. Interest of 200 accumulates. Now, as the code is, we add 200 to the budget so budget is back to zero, but we also add 200 to the total troves debt, so total troves debt is now 1,200, but total yin remains at 1,000.
  4. If the Caretaker shuts now, the amount of yin that will be backed is based on the total troves debt which is 1,200, but > there is only 1,000 yin in circulation.

So in this example, the total_troves_deficit would be used in step 2 (set to -200) and then in step 4 (as 1200 + -200) to even out the backed yin? 🤔

tserg commented 9 months ago

That's only charge right?

I made a mistake with that statement. The correct statement should be that only increments to the total trove debt can go towards reducing the deficit, so this includes (1) forging of new debt; (2) interest; and (3) forge fees.

The central idea is that circulating yin originating from troves should match the total trove debt. When exceptionally redistributed debt are added to the deficit, they are in a limbo state because they are no longer attributed to a trove, but we cannot decrement total debt at the same time because the yin that were originated from this exceptionally redistributed debt is already in circulation, and need to be backed should the Shrine be killed. Hence, we need to balance the total troves deficit back to zero, before we can continue minting yin that originated from troves.

the total_troves_deficit would be used in step 2 (set to -200)

Yes.

in step 4 (as 1200 + -200) to even out the backed yin?

The solution here is actually that we should not increase the total troves' debt at all, and total troves deficit would be incremented by 200 i.e. -200 + 200 = 0.

tserg commented 9 months ago

[DELETED - moved the original post to the top-level post]

tserg commented 9 months ago

An outstanding question is how should the initial yang amounts be dealt with since they would be bricked at shutdown.

@milancermak suggested that the initial yang amounts can be rebased so that users benefit from the rebasing. This would require caretaker.shut to call seer.update_prices so that the rebased prices are used at shutdown. I agree it is a good idea, and that it should be taken up as a separate PR, since it would apply regardless of how we handle exceptional redistributions.

milancermak commented 9 months ago

Q: would it make sense for Equalizer.normalize() to potentially zero-out the trove's deficit along with the budget? In other words, first take care of the deficit, if there's leftover, use it for the budget - what accrue_surplus_from_troves does.

tserg commented 9 months ago

Q: would it make sense for Equalizer.normalize() to potentially zero-out the trove's deficit along with the budget? In other words, first take care of the deficit, if there's leftover, use it for the budget - what accrue_surplus_from_troves does.

Good question, and a tough one!

Zero-ing out the deficit would require us to decrease total_troves_debt by the troves' deficit that has been paid off, which would require a new external function of Shrine that modifies the Shrine's debt. Hence, I prefer not to do this. Another reason is that the deficit is backed by the initial yangs, so IMO there is no urgency to clear out the deficit - we can slowly let the backing for the deficit shift from initial yangs back to troves as interest accrue.

tserg commented 8 months ago

Update: I will add some tests to check emission of TotalTrovesDebtUpdated when protocol owned troves debt is non-zero.

tserg commented 8 months ago

Closes #530, closes #531.