Interest & Fee Accrual

Interest accrues lazily during operations that update the Tranche. Interest for the tranche's borrowers can be accrued separately from the tranche's lenders. Each tranche tracks

struct Tranche {
    uint128 trancheSupplyAssets; // Total amount of assets that have been supplied at this tranche
    uint128 trancheSupplyShares; // Total supply shares for only the current tranche. Each share corresponds to assets potentially in every tranche more senior than the current tranche.
    uint128 trancheBorrowAssets; // Total borrow assets for only the current tranche.
    uint128 trancheBorrowShares; // Total borrow shares for only the current tranche. Each share corresponds only to borrow activity in the current tranche.
    uint128 pendingInterest; // Interest that has not yet been distributed to suppliers
    uint128 fee; // Protocol fee taken from interest accrued at this tranche
    uint128 lastUpdate; // Last timestamp when interest was accrued for this tranche
}

The trancheBorrowAssets have all interest accrued up to the lastUpdate.

The trancheSupplyAssets DO NOT have all interest accrued up to the lastUpdate. To ensure the trancheSupplyAssets are up to date, the borrow interest and pending interest must be accrued from all more senior tranches as well.

Borrowing

In borrow interactions borrow(), repay(), and withdrawCollateral() only the tranche borrow interest is accrued. Instead of immediately paying out to trancheSupplyAssets, the interest is stored in pendingInterest until a supply action requires the value for accounting purposes.

function _accrueBorrowInterest(MarketParams memory marketParams, ..., uint256 trancheIndex) {
    ...
    uint256 elapsedTime = block.timestamp - uint256(tranche.lastUpdate);
    if (tranche.trancheBorrowAssets != 0 && elapsedTime > 0) {
        uint256 trancheBorrowUtilization = _getTrancheUtilization(jrSupply, freeSupply);
        uint256 borrowRate =
            IIrm(marketParams.irm).getTrancheBorrowRate(id, trancheIndex, trancheBorrowUtilization, irmData);
        uint256 trancheBorrowInterest =
            uint256(tranche.trancheBorrowAssets).mulWad(InterestMathLib.wTaylorCompounded(borrowRate, elapsedTime));
        tranche.trancheBorrowAssets += trancheBorrowInterest.toUint128();
        tranche.pendingInterest += trancheBorrowInterest.toUint128();
    }
    tranche.lastUpdate = block.timestamp.toUint128();
}

Lending

In lending interactions supply() and withdraw() all senior tranches must have borrow interest accrued and pending interest paid out for an accurate trancheSupplyAssets.

During a withdraw() lenders can opt out of interest accrual. This will undervalue their trancheSupplyShares and cost them loanToken units, but it avoids the gas cost of interest accrual for all more senior tranches.

Liquidation

During a liquidation without any bad debt, only the tranche borrow interest is accrued, similar to borrow(), repay(), and withdrawCollateral().

If a liquidation generates bad debt, then interest is accrued for the entire market.

Fee Accrual

A Tranche.fee portion of the trancheSupplyInterest is distributed to the protocol feeRecipient via inflation of the trancheSupplyShares.

If the fee is updated setFee() then interest is accrued.

Last updated