Skip to content

Add time-based interest accrual and debt indexes - #235

Merged
Cedarich merged 1 commit into
Zyntarivoid:mainfrom
zhero-o:feat/174-interest-accrual-indexes
Jul 23, 2026
Merged

Add time-based interest accrual and debt indexes#235
Cedarich merged 1 commit into
Zyntarivoid:mainfrom
zhero-o:feat/174-interest-accrual-indexes

Conversation

@zhero-o

@zhero-o zhero-o commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Introduces index-based accounting (Aave/Compound-style) so borrow and supply balances grow over time instead of remaining static. A new InterestState (supply_index/borrow_index/last_accrual_timestamp) is tracked per asset, with per-position index snapshots realized into Position.deposited/borrowed on every touch. The rate model is a simple, deterministic linear function of utilization (derived from the existing TotalDeposited/TotalBorrowed totals), with supply_rate = borrow_rate * utilization so interest accrued to borrowers always equals interest credited to suppliers (no protocol fee skim). All accrual math lives in interest.rs as pure, storage-free functions with dedicated unit tests; deposit/borrow/repay/withdraw/record_protocol_fee accrue before their own effects so caps and balances stay accurate, and get_position/ get_asset_reserve reflect live simulated values without persisting. Bumps CONTRACT_VERSION/STORAGE_SCHEMA_VERSION to 2 (VLENDV2) per the project's own versioning convention, since storage layout changed.

Along the way, fixed two pre-existing bugs blocking this work:

  • tests/integration.rs was configured with harness = false and an empty main(), silently disabling all 10 integration tests (they never compiled or ran, and used an incorrect contract-registration pattern that wouldn't have compiled anyway).
  • configure_asset() wrote deposit/borrow caps and totals as untyped integer literals, which Rust defaults to i32, while every reader expects i128 - any configured asset's caps/totals panicked with a storage type mismatch as soon as they were read back.

Closes #174

Introduces index-based accounting (Aave/Compound-style) so borrow and
supply balances grow over time instead of remaining static. A new
InterestState (supply_index/borrow_index/last_accrual_timestamp) is
tracked per asset, with per-position index snapshots realized into
Position.deposited/borrowed on every touch. The rate model is a simple,
deterministic linear function of utilization (derived from the existing
TotalDeposited/TotalBorrowed totals), with supply_rate = borrow_rate *
utilization so interest accrued to borrowers always equals interest
credited to suppliers (no protocol fee skim). All accrual math lives in
interest.rs as pure, storage-free functions with dedicated unit tests;
deposit/borrow/repay/withdraw/record_protocol_fee accrue before their
own effects so caps and balances stay accurate, and get_position/
get_asset_reserve reflect live simulated values without persisting.
Bumps CONTRACT_VERSION/STORAGE_SCHEMA_VERSION to 2 (VLENDV2) per the
project's own versioning convention, since storage layout changed.

Along the way, fixed two pre-existing bugs blocking this work:
- tests/integration.rs was configured with `harness = false` and an
  empty main(), silently disabling all 10 integration tests (they
  never compiled or ran, and used an incorrect contract-registration
  pattern that wouldn't have compiled anyway).
- configure_asset() wrote deposit/borrow caps and totals as untyped
  integer literals, which Rust defaults to i32, while every reader
  expects i128 - any configured asset's caps/totals panicked with a
  storage type mismatch as soon as they were read back.

Closes Zyntarivoid#174
@Cedarich
Cedarich merged commit d172d1e into Zyntarivoid:main Jul 23, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4. Add time-based interest accrual and debt indexes

2 participants