Account Interest Accumulation performs operation on the Reserve Data and Account Reserve Data based on the Reserve Indexes,Reserve Fees and the external fee reductions.
The trick in accumulating an account interest lays in the deposit_index_e18 and debt_index_e18.
These values are measures of the accumulated deposit and debt interest, thus if during deposit/borrow we store the current indexes in applied_deposit_index_e18 and applied_debt_index_e18 at later time with access to already increased deposit_index_e18 and debt_index_e18 one is able to deduce the interest that should be accumulated.
For example:
Alice makes deposit when deposit_index_e18 = 1.1 * 10^18
Alice deposit is accumulated when deposit_index_e18 = 1.21 * 10^18. The deposit_index_e18 increased by 1.1 since Alice have made her deposit thus her earned interest should be 0.1 of what she has deposited.
The above example doesn't take into account protocol fees that are applied during interest accumulation. The fees are applied both on the deposits and debts. The fees reduce the deposit interest the account earns and increases the debt interest the account pays.
**'Internal' Inputs:**
- `reserve_data`: mutable reference to 'ReserveData' struct
- `account_reserve_data`: mutable reference to `AccountReserveData` struct
- `reserve_indexes`: reference to `ReserveIndexes` struct
- `reserve_fees`: reference to `ReserveFees` struct
**'External' Inputs:**
- `deposit_fee_reduction_e6`: reference to u32 representing deposit fee reduction
- `debt_fee_reduction_e6`: reference to u32 representing debt fee reduction
**Pseudocode:**
1. If `account_reserve_data.applied_deposit_index_e18` is
greater than or equal to `reserve_indexes.deposit_index_e18`
and
`self.applied_debt_index_e18` is
greater than or equal to `reserve_indexes.debt_index_e18`
return Ok((0, 0)).
2. Initialize `(delta_account_deposit, delta_account_debt)` as `(0, 0)`.
3. If `account_reserve_data.deposit` is not 0 and
`account_reserve_data.applied_deposit_index_e18` is not 0 and
`account_reserve_data.applied_deposit_index_e18` is
less than `reserve_indexes.deposit_index_e18`
then:
a. `deposit_interest_with_fee` =
`account_reserve_data.deposit` * (
`reserve_indexes.deposit_index_e18` /
`account_reserve_data.applied_deposit_index_e18` - 1 ).
round in such way that the result is not greater than the "precise result".
b. `fee_no_reduction' =
`deposit_interest_with_fee' * reserve_fees.deposit_fee_e6 / 10^6.
round in such way that the result is not lesser than the "precise result".
c. `fee` =
`fee_no_reduction` * (1 - `deposit_fee_reduction_e6` / 10^6).
round in such way that the result is not lesser than the "precise result".
d. `delta_account_deposit` = `deposit_interest_with_fee` - `fee`.
e. increase `account_reserve_data.deposit' by 'delta_account_deposit'
4. Update `account_reserve_data.applied_deposit_index_e18` to
`reserve_indexes.deposit_index_e18`.
3. If `account_reserve_data.debt` is not 0 and
`account_reserve_data.applied_debt_index_e18` is not 0 and
`account_reserve_data.applied_debt_index_e18` is
less than `reserve_indexes.debt_index_e18`
then:
a. `debt_interest_without_fee` =
`account_reserve_data.debt` * (
`reserve_indexes.debt_index_e18` /
`account_reserve_data.applied_debt_index_e18` - 1 ).
round in such way that the result is not lesser than the "precise result".
b. `fee_no_reduction' =
`debt_interest_without_fee' * reserve_fees.deposit_fee_e6 / 10^6.
round in such way that the result is not lesser than the "precise result".
c. `fee` =
`fee_no_reduction` * (1 - `debt_fee_reduction_e6` / 10^6).
round in such way that the result is not lesser than the "precise result".
d. `delta_account_debt` = `debt_interest_without_fee` + `fee`.
e. increase `account_reserve_data.debt' by 'delta_account_debt'
6. Update `self.applied_debt_index_e18` to `reserve_indexes.debt_index_e18`.
7. Increae`reserve_data.total_deposit' and `reserve_data'.total_debt`
by `delta_account_deposit` and `delta_account_debt`.