Debt DAO Docs

'Interest Accrued' contract flow

Overviews the contract workflow for how and when InterestAccrued is updated
Prior advised reading and definitions: 'finance view' of how accrued interest is calculated in our contracts.
The term 'InterestAccrued' is the Interest owed by a Borrower but not yet repaid to the Line of Credit contract and made available for withdrawal by a Lender.
Steps 2 - 5 below deal with calculating calculating accrued interest in order to updateInterestAccruedfor a single credit position id as either a direct result of the external function request (step 1) or indirectly as a result of another action such as a change in the balance on a credit line id.
Step 1 is an external function that updates the accrued interest for all credit position ids in a Line of Credit facility
1) accrueInterest() in LineOfCredit.sol
This external function loops over all credit position ids and calls related internal functions during which InterestRateCredit.sol is called with the id data and then interestAccrued is updated.
function accrueInterest() external override returns(bool) {
uint256 len = ids.length;
bytes32 id;
for (uint256 i; i < len; ++i) {
id = ids[i];
Credit memory credit = credits[id];
credits[id] = _accrue(credit, id);
return true;
2) _accrue in LineOfCredit.sol
This internal function runs within step 1 or otherwise at any time the balance on a credit line changes or the interest rates are changed by mutual consent between a Borrower and a Lender.
function _accrue(Credit memory credit, bytes32 id) internal returns (Credit memory) {
if (!credit.isOpen) {
return credit;
return CreditLib.accrue(credit, id, address(interestRate));
3) accrue() in CreditLib.sol
Called by _accrue() in step 2 above any time the balance on a credit position changes or the interest rates are changed by mutual consent between a Borrower and a Lender.
It returns an updated token denominated interestAccrued for a single id.
It does so by adding the new amount of interest to accrue to the prior amount of interestAccrued recorded.
This new amount of interest to accrue is called accruedToken and is calculated in InterestRateCredit.sol (see steps 4 and 5 below).
function accrue(
ILineOfCredit.Credit memory credit,
bytes32 id,
address interest
) public returns (ILineOfCredit.Credit memory) {
unchecked {
// interest will almost always be less than deposit
// low risk of overflow unless extremely high interest rate
// get token demoninated interest accrued
uint256 accruedToken = IInterestRateCredit(interest).accrueInterest(id, credit.principal, credit.deposit);
// update credit line balance
credit.interestAccrued += accruedToken;
emit InterestAccrued(id, accruedToken);
return credit;
4) accrueInterest() in InterestRateCredit.sol
This is the main function for calculating the amount by which interestAccrued should be updated for a single credit position id, callable indirectly by _accrue() in LineOfCredit.sol (step 2 above) and then subsequently directly by accrue() in CreditLib.sol (step 3)
function accrueInterest(
bytes32 id,
uint256 drawnBalance,
uint256 facilityBalance
) external override onlyLineContract returns (uint256) {
return _accrueInterest(id, drawnBalance, facilityBalance);
5) _accrueInterest() and _calculateInterestOwed in InterestRateCredit.sol
Finally, this is where the amount by which interestAccrued should be updated is calculated per credit position id.
function _accrueInterest(bytes32 id, uint256 drawnBalance, uint256 facilityBalance) internal returns (uint256) {
Rate memory rate = rates[id];
uint256 timespan = block.timestamp - rate.lastAccrued;
// update last timestamp in storage
rates[id].lastAccrued = block.timestamp;
return (_calculateInterestOwed(rate.dRate, drawnBalance, timespan) +
_calculateInterestOwed(rate.fRate, (facilityBalance - drawnBalance), timespan));
function _calculateInterestOwed(
uint256 bpsRate,
uint256 balance,
uint256 timespan
) internal pure returns (uint256) {
return (bpsRate * balance * timespan) / INTEREST_DENOMINATOR;
last updated Dec 29 2022