@@ -377,6 +377,21 @@ module suilend::reserve {
377
377
reserve.unclaimed_spread_fees
378
378
)
379
379
}
380
+
381
+ fun simulated_total_supply <P >(reserve: &Reserve <P >, clock: &Clock ): Decimal {
382
+ let (
383
+ borrowed_amount,
384
+ unclaimed_spread_fees,
385
+ ) = reserve.simulated_compound_interest (clock);
386
+
387
+ sub (
388
+ add (
389
+ decimal::from (reserve.available_amount),
390
+ borrowed_amount
391
+ ),
392
+ unclaimed_spread_fees
393
+ )
394
+ }
380
395
381
396
public fun calculate_utilization_rate <P >(reserve: &Reserve <P >): Decimal {
382
397
let total_supply_excluding_fees = add (
@@ -409,6 +424,23 @@ module suilend::reserve {
409
424
)
410
425
}
411
426
}
427
+
428
+ public fun simulated_ctoken_ratio <P >(reserve: &Reserve <P >, clock: &Clock ): Decimal {
429
+ let total_supply = simulated_total_supply (reserve, clock);
430
+
431
+ // this branch is only used once -- when the reserve is first initialized and has
432
+ // zero deposits. after that, borrows and redemptions won't let the ctoken supply fall
433
+ // below MIN_AVAILABLE_AMOUNT
434
+ if (reserve.ctoken_supply == 0 ) {
435
+ decimal::from (1 )
436
+ }
437
+ else {
438
+ div (
439
+ total_supply,
440
+ decimal::from (reserve.ctoken_supply)
441
+ )
442
+ }
443
+ }
412
444
413
445
public fun config <P >(reserve: &Reserve <P >): &ReserveConfig {
414
446
cell::get (&reserve.config)
@@ -623,6 +655,43 @@ module suilend::reserve {
623
655
supply_interest_earned_usd_estimate: market_value (reserve, sub (net_new_debt, spread_fee)),
624
656
});
625
657
}
658
+
659
+ /// Compound interest, debt. Interest is compounded every second.
660
+ fun simulated_compound_interest <P >(reserve: &Reserve <P >, clock: &Clock ): (Decimal , Decimal ) {
661
+ let cur_time_s = clock::timestamp_ms (clock) / 1000 ;
662
+ let time_elapsed_s = cur_time_s - reserve.interest_last_update_timestamp_s;
663
+ if (time_elapsed_s == 0 ) {
664
+ return (
665
+ reserve.borrowed_amount,
666
+ reserve.unclaimed_spread_fees
667
+ )
668
+ };
669
+
670
+ // I(t + n) = I(t) * (1 + apr()/SECONDS_IN_YEAR) ^ n
671
+ let utilization_rate = calculate_utilization_rate (reserve);
672
+ let compounded_borrow_rate = pow (
673
+ add (
674
+ decimal::from (1 ),
675
+ div (
676
+ calculate_apr (config (reserve), utilization_rate),
677
+ decimal::from (365 * 24 * 60 * 60 )
678
+ )
679
+ ),
680
+ time_elapsed_s
681
+ );
682
+
683
+ let net_new_debt = mul (
684
+ reserve.borrowed_amount,
685
+ sub (compounded_borrow_rate, decimal::from (1 ))
686
+ );
687
+
688
+ let spread_fee = mul (net_new_debt, spread_fee (config (reserve)));
689
+
690
+ return (
691
+ reserve.borrowed_amount.add (net_new_debt),
692
+ reserve.unclaimed_spread_fees.add (spread_fee)
693
+ )
694
+ }
626
695
627
696
public (package ) fun claim_fees <P , T >(
628
697
reserve: &mut Reserve <P >,
0 commit comments