osmosis-labs / isotonic

Smart Contracts for the Lendex Protocol
MIT License
1 stars 0 forks source link

Add reserve for each Market #47

Closed ethanfrey closed 2 years ago

ethanfrey commented 2 years ago

A reserve fund is defined in Compound and is a small portion of the interest collected by the borrowers that doesn't go to the lenders but rather is held in the protocol. This can be used to provide liquidity and cover debts in extreme market conditions. It is not extracted to devs/governance.

The logic is defined in end of page 4 - page 5 of the Compound Whitepaper under Accrue Interest and is referenced in their docs: https://compound.finance/docs/ctokens#total-reserves

Basically, we need a new percentage (0 <= reserve_factor <= 1) for each Market. This is set in the constructor and will later be adjustable by governance. You can see some reference values here of 7.5% - 25% depending on the market. The reserve balance is just a Uint128 stored in the contract, which is set to 0 on initialisation and is the amount of base_assets in the contract that actually belong to the protocol (not the lenders).

What changes is what happens when calculating interest. This is currently roughly defined (in the rustdoc) as:

    /// It calculates ratio for increasing both btokens and ltokens.a
    /// btokens formula:
    /// b_ratio = calculate_interest() * epochs_passed * epoch_length / 31.556.736 (or 31.536.000 as mentioned in #40 )
    /// ltokens formula:
    /// l_ratio = b_supply() * b_ratio / l_supply()

The new calculation will calculate the bratio increase the same way (0.023% increase of all btoken value). However, rather than just handing that out to the LTokens, it will be split by reserve_factor between LTokens and Reserve. A safe way to handle this, in order to account for tokens received out of band and rounding issues, is to simply enforce this invariant every time we accrue Interest:

l_supply() = b_supply() + base_asset_balance() - reserve
  1. Increase b_supply() by some amount (as before)
  2. Update reserve value (rounding down) such that reserve += reserve_factor * btokens_created
  3. Remainder ends up in l_supply by enforcing the invariant and calculating the needed multiplier to keep this