# Stale checkpoint interest and fee math

Interest or fee computed on a stale delta or wrong rate basis, undercharging or inflating balances

_Area: DeFi accounting and math bugs. Seen in 2 disclosed reports; latest 2025-02-17. Updated 2026-11-02._

## How it works
Interest and fee accounting assumes a stored checkpoint and a rate basis stay consistent with how the charge is applied. Two assumptions break. First, a fee computed as a delta between a stored checkpoint rate and the current rate silently drops every rate change that happened while the checkpoint was stale, so the charge collapses. Second, a rate accumulator seeded at 1e18 and used as a divisor applies the fee as `amount / (1+rate)` instead of `amount - amount*rate`, so the effective fee is smaller than intended and diverges as the rate grows. In both cases the bookkeeping no longer matches the economic intent, and balances drift from reality.

## Where it shows up
- Fee math of the form `(currentRate - lastCheckpointRate) * balance` with an early return when nothing changed [E2](https://bugbountylibrary.com/r/cantina%3Ahmx_january2025%3A3.2.5.md)
- Rate accumulators seeded at `1e18` that are later used as a divisor in borrow/mint paths [E1](https://bugbountylibrary.com/r/sherlock%3A2023-04-jojo%3AM-1.md)
- Two functions computing the same economic quantity (e.g. slope) where one omits a scaling constant or time/expiry handling [E3](https://bugbountylibrary.com/r/sherlock%3A2022-10-astaria%3AM-8.md)
- Checkpoints updated only on user interaction, so inactive users carry stale state [E2](https://bugbountylibrary.com/r/cantina%3Ahmx_january2025%3A3.2.5.md)

## How to review
For each fee or interest charge, identify the exact invariant: the total charged over a period must equal the integral of the rate over that period, regardless of when the user last interacted. Check that:
- The checkpoint is advanced across every rate change, or the fee compounds per change rather than on a single delta [E2](https://bugbountylibrary.com/r/cantina%3Ahmx_january2025%3A3.2.5.md).
- A rate used as a divisor is applied as a fraction (`amount - amount*rate`), not `amount / (1+rate)`; test with a one-year example at the intended rate [E1](https://bugbountylibrary.com/r/sherlock%3A2023-04-jojo%3AM-1.md).
- Functions computing the same quantity are diffed line-by-line for missing denominators and time/expiry terms [E3](https://bugbountylibrary.com/r/sherlock%3A2022-10-astaria%3AM-8.md).

## How finders spotted it
- Read the interest-rate accumulator, noticed `t0Rate` seeded at `1e18` and `_borrow` dividing by `tRate`, then computed a one-year example showing the fee fraction inverted [E1](https://bugbountylibrary.com/r/sherlock%3A2023-04-jojo%3AM-1.md).
- Read `_settlePendingBorrowingFee`'s early return and delta math, then built a two-user scenario with sequential rate hikes to expose the gap between active and inactive users [E2](https://bugbountylibrary.com/r/cantina%3Ahmx_january2025%3A3.2.5.md).
- Compared `changeInSlope` against `calculateSlope` by code reading and saw the missing `INTEREST_DENOMINATOR` and missing `_getOwed`/`_getInterest` handling of `lien.last` and expiry [E3](https://bugbountylibrary.com/r/sherlock%3A2022-10-astaria%3AM-8.md).

## Variants seen
- Fee undercharged because the rate delta skips intermediate hikes on a stale checkpoint [E2](https://bugbountylibrary.com/r/cantina%3Ahmx_january2025%3A3.2.5.md).
- Fee undercharged because the rate is applied as a divisor instead of a fraction [E1](https://bugbountylibrary.com/r/sherlock%3A2023-04-jojo%3AM-1.md).
- Slope inflated and underflowing because a scaling denominator and time logic were omitted [E3](https://bugbountylibrary.com/r/sherlock%3A2022-10-astaria%3AM-8.md).

## Impact and severity
Protocol revenue is shorted: ~9.1% collected instead of 10% [E1](https://bugbountylibrary.com/r/sherlock%3A2023-04-jojo%3AM-1.md), and inactive users pay less than active ones [E2](https://bugbountylibrary.com/r/cantina%3Ahmx_january2025%3A3.2.5.md). In E3 the inflated slope underflows and breaks vault accounting, risking insolvency. Impact scales with how long checkpoints stay stale and how large the rate grows; combining with insolvency or underflow raises severity sharply [E3](https://bugbountylibrary.com/r/sherlock%3A2022-10-astaria%3AM-8.md).

## Evidence
- E1: https://bugbountylibrary.com/r/sherlock%3A2023-04-jojo%3AM-1.md
- E2: https://bugbountylibrary.com/r/cantina%3Ahmx_january2025%3A3.2.5.md
- E3: https://bugbountylibrary.com/r/sherlock%3A2022-10-astaria%3AM-8.md
