@@ -39,6 +39,7 @@ module suilend::obligation {
39
39
const ETooManyBorrows : u64 = 6 ;
40
40
const EObligationIsNotForgivable : u64 = 7 ;
41
41
const ECannotDepositAndBorrowSameAsset : u64 = 8 ;
42
+ const EOraclesAreStale : u64 = 9 ;
42
43
43
44
// === Constants ===
44
45
const CLOSE_FACTOR_PCT : u8 = 20 ;
@@ -100,6 +101,9 @@ module suilend::obligation {
100
101
user_reward_manager_index: u64 ,
101
102
}
102
103
104
+ // hot potato. used by obligation::refresh to indicate that prices are stale.
105
+ public struct ExistStaleOracles {}
106
+
103
107
// === Events ===
104
108
public struct ObligationDataEvent has copy , drop {
105
109
lending_market_id: address ,
@@ -167,7 +171,9 @@ module suilend::obligation {
167
171
obligation: &mut Obligation <P >,
168
172
reserves: &mut vector <Reserve <P >>,
169
173
clock: &Clock ,
170
- ) {
174
+ ): Option <ExistStaleOracles > {
175
+ let mut exist_stale_oracles = false ;
176
+
171
177
let mut i = 0 ;
172
178
let mut deposited_value_usd = decimal::from (0 );
173
179
let mut allowed_borrow_value_usd = decimal::from (0 );
@@ -179,7 +185,10 @@ module suilend::obligation {
179
185
let deposit_reserve = vector ::borrow_mut (reserves, deposit.reserve_array_index);
180
186
181
187
reserve::compound_interest (deposit_reserve, clock);
182
- reserve::assert_price_is_fresh (deposit_reserve, clock);
188
+
189
+ if (!reserve::is_price_fresh (deposit_reserve, clock)) {
190
+ exist_stale_oracles = true ;
191
+ };
183
192
184
193
let market_value = reserve::ctoken_market_value (
185
194
deposit_reserve,
@@ -227,7 +236,9 @@ module suilend::obligation {
227
236
228
237
let borrow_reserve = vector ::borrow_mut (reserves, borrow.reserve_array_index);
229
238
reserve::compound_interest (borrow_reserve, clock);
230
- reserve::assert_price_is_fresh (borrow_reserve, clock);
239
+ if (!reserve::is_price_fresh (borrow_reserve, clock)) {
240
+ exist_stale_oracles = true ;
241
+ };
231
242
232
243
compound_debt (borrow, borrow_reserve);
233
244
@@ -269,6 +280,12 @@ module suilend::obligation {
269
280
weighted_borrowed_value_upper_bound_usd;
270
281
271
282
obligation.borrowing_isolated_asset = borrowing_isolated_asset;
283
+
284
+ if (exist_stale_oracles) {
285
+ return option::some (ExistStaleOracles {})
286
+ };
287
+
288
+ option::none ()
272
289
}
273
290
274
291
/// Process a deposit action
@@ -492,7 +509,14 @@ module suilend::obligation {
492
509
reserve: &mut Reserve <P >,
493
510
clock: &Clock ,
494
511
ctoken_amount: u64 ,
512
+ stale_oracles: Option <ExistStaleOracles >,
495
513
) {
514
+ if (stale_oracles.is_some () && vector ::is_empty (&obligation.borrows)) {
515
+ let ExistStaleOracles {} = option::destroy_some (stale_oracles);
516
+ } else {
517
+ assert_no_stale_oracles (stale_oracles);
518
+ };
519
+
496
520
withdraw_unchecked (obligation, reserve, clock, ctoken_amount);
497
521
498
522
assert !(is_healthy (obligation), EObligationIsNotHealthy );
@@ -834,6 +858,11 @@ module suilend::obligation {
834
858
)
835
859
}
836
860
861
+ public (package ) fun assert_no_stale_oracles (exist_stale_oracles: Option <ExistStaleOracles >) {
862
+ assert !(option::is_none (&exist_stale_oracles), EOraclesAreStale );
863
+ option::destroy_none (exist_stale_oracles);
864
+ }
865
+
837
866
public (package ) fun zero_out_rewards_if_looped <P >(
838
867
obligation: &mut Obligation <P >,
839
868
reserves: &mut vector <Reserve <P >>,
0 commit comments