Skip to content

Commit a6c27d9

Browse files
authored
Oracleless ctoken mint and redeem (#69)
* no need to refresh on mint/redeem * test fixes * added more robust tests to make sure interest accrues, added oracleless deposit_obligation_collateral, updated instruction.rs for writable account * comment change
1 parent 6ca5206 commit a6c27d9

File tree

7 files changed

+112
-49
lines changed

7 files changed

+112
-49
lines changed

token-lending/program/src/instruction.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,7 @@ pub enum LendingInstruction {
121121
/// 0. `[writable]` Source collateral token account.
122122
/// $authority can transfer $collateral_amount.
123123
/// 1. `[writable]` Destination liquidity token account.
124-
/// 2. `[writable]` Reserve account. - refreshed
124+
/// 2. `[writable]` Reserve account.
125125
/// 3. `[writable]` Reserve collateral SPL Token mint.
126126
/// 4. `[writable]` Reserve liquidity supply SPL Token account.
127127
/// 5. `[]` Lending market account.
@@ -161,15 +161,15 @@ pub enum LendingInstruction {
161161
RefreshObligation,
162162

163163
// 8
164-
/// Deposit collateral to an obligation. Requires a refreshed reserve.
164+
/// Deposit collateral to an obligation.
165165
///
166166
/// Accounts expected by this instruction:
167167
///
168168
/// 0. `[writable]` Source collateral token account.
169169
/// Minted by deposit reserve collateral mint.
170170
/// $authority can transfer $collateral_amount.
171171
/// 1. `[writable]` Destination deposit reserve collateral supply SPL Token account.
172-
/// 2. `[]` Deposit reserve account - refreshed.
172+
/// 2. `[writable]` Deposit reserve account.
173173
/// 3. `[writable]` Obligation account.
174174
/// 4. `[]` Lending market account.
175175
/// 5. `[signer]` Obligation owner.
@@ -948,7 +948,7 @@ pub fn deposit_obligation_collateral(
948948
accounts: vec![
949949
AccountMeta::new(source_collateral_pubkey, false),
950950
AccountMeta::new(destination_collateral_pubkey, false),
951-
AccountMeta::new_readonly(deposit_reserve_pubkey, false),
951+
AccountMeta::new(deposit_reserve_pubkey, false),
952952
AccountMeta::new(obligation_pubkey, false),
953953
AccountMeta::new_readonly(lending_market_pubkey, false),
954954
AccountMeta::new_readonly(obligation_owner_pubkey, true),

token-lending/program/src/processor.rs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -458,7 +458,7 @@ fn process_deposit_reserve_liquidity(
458458
let clock = &Clock::from_account_info(next_account_info(account_info_iter)?)?;
459459
let token_program_id = next_account_info(account_info_iter)?;
460460

461-
// We don't care about the return value here, so just ignore it.
461+
_refresh_reserve_interest(program_id, reserve_info, clock)?;
462462
_deposit_reserve_liquidity(
463463
program_id,
464464
liquidity_amount,
@@ -473,6 +473,7 @@ fn process_deposit_reserve_liquidity(
473473
clock,
474474
token_program_id,
475475
)?;
476+
476477
Ok(())
477478
}
478479

@@ -599,6 +600,8 @@ fn process_redeem_reserve_collateral(
599600
let user_transfer_authority_info = next_account_info(account_info_iter)?;
600601
let clock = &Clock::from_account_info(next_account_info(account_info_iter)?)?;
601602
let token_program_id = next_account_info(account_info_iter)?;
603+
604+
_refresh_reserve_interest(program_id, reserve_info, clock)?;
602605
_redeem_reserve_collateral(
603606
program_id,
604607
collateral_amount,
@@ -612,7 +615,12 @@ fn process_redeem_reserve_collateral(
612615
user_transfer_authority_info,
613616
clock,
614617
token_program_id,
615-
)
618+
)?;
619+
let mut reserve = Reserve::unpack(&reserve_info.data.borrow())?;
620+
reserve.last_update.mark_stale();
621+
Reserve::pack(reserve, &mut reserve_info.data.borrow_mut())?;
622+
623+
Ok(())
616624
}
617625

618626
#[allow(clippy::too_many_arguments)]
@@ -896,6 +904,7 @@ fn process_deposit_obligation_collateral(
896904
let user_transfer_authority_info = next_account_info(account_info_iter)?;
897905
let clock = &Clock::from_account_info(next_account_info(account_info_iter)?)?;
898906
let token_program_id = next_account_info(account_info_iter)?;
907+
_refresh_reserve_interest(program_id, deposit_reserve_info, clock)?;
899908
_deposit_obligation_collateral(
900909
program_id,
901910
collateral_amount,
@@ -908,7 +917,11 @@ fn process_deposit_obligation_collateral(
908917
user_transfer_authority_info,
909918
clock,
910919
token_program_id,
911-
)
920+
)?;
921+
let mut reserve = Reserve::unpack(&deposit_reserve_info.data.borrow())?;
922+
reserve.last_update.mark_stale();
923+
Reserve::pack(reserve, &mut deposit_reserve_info.data.borrow_mut())?;
924+
Ok(())
912925
}
913926

914927
#[allow(clippy::too_many_arguments)]

token-lending/program/tests/deposit_obligation_collateral.rs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ async fn test_success() {
2828

2929
const SOL_DEPOSIT_AMOUNT_LAMPORTS: u64 = 10 * LAMPORTS_TO_SOL * INITIAL_COLLATERAL_RATIO;
3030
const SOL_RESERVE_COLLATERAL_LAMPORTS: u64 = 2 * SOL_DEPOSIT_AMOUNT_LAMPORTS;
31+
const SOL_BORROWED_AMOUNT_LAMPORTS: u64 = SOL_DEPOSIT_AMOUNT_LAMPORTS;
3132

3233
let user_accounts_owner = Keypair::new();
3334
let user_transfer_authority = Keypair::new();
@@ -45,6 +46,7 @@ async fn test_success() {
4546
liquidity_amount: SOL_RESERVE_COLLATERAL_LAMPORTS,
4647
liquidity_mint_decimals: 9,
4748
liquidity_mint_pubkey: spl_token::native_mint::id(),
49+
borrow_amount: SOL_BORROWED_AMOUNT_LAMPORTS,
4850
config: test_reserve_config(),
4951
mark_fresh: true,
5052
..AddReserveArgs::default()
@@ -58,14 +60,24 @@ async fn test_success() {
5860
AddObligationArgs::default(),
5961
);
6062

61-
let (mut banks_client, payer, recent_blockhash) = test.start().await;
63+
let mut test_context = test.start_with_context().await;
64+
test_context.warp_to_slot(300).unwrap(); // clock.slot = 300
65+
66+
let ProgramTestContext {
67+
mut banks_client,
68+
payer,
69+
last_blockhash: recent_blockhash,
70+
..
71+
} = test_context;
6272

6373
test_obligation.validate_state(&mut banks_client).await;
6474

6575
let initial_collateral_supply_balance =
6676
get_token_balance(&mut banks_client, sol_test_reserve.collateral_supply_pubkey).await;
6777
let initial_user_collateral_balance =
6878
get_token_balance(&mut banks_client, sol_test_reserve.user_collateral_pubkey).await;
79+
let pre_sol_reserve = sol_test_reserve.get_state(&mut banks_client).await;
80+
let old_borrow_rate = pre_sol_reserve.liquidity.cumulative_borrow_rate_wads;
6981

7082
let mut transaction = Transaction::new_with_payer(
7183
&[
@@ -99,6 +111,9 @@ async fn test_success() {
99111
);
100112
assert!(banks_client.process_transaction(transaction).await.is_ok());
101113

114+
let sol_reserve = sol_test_reserve.get_state(&mut banks_client).await;
115+
assert_eq!(sol_reserve.last_update.stale, true);
116+
102117
// check that collateral tokens were transferred
103118
let collateral_supply_balance =
104119
get_token_balance(&mut banks_client, sol_test_reserve.collateral_supply_pubkey).await;
@@ -112,4 +127,6 @@ async fn test_success() {
112127
user_collateral_balance,
113128
initial_user_collateral_balance - SOL_DEPOSIT_AMOUNT_LAMPORTS
114129
);
130+
131+
assert!(sol_reserve.liquidity.cumulative_borrow_rate_wads > old_borrow_rate);
115132
}

token-lending/program/tests/deposit_reserve_liquidity.rs

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ async fn test_success() {
1616
);
1717

1818
// limit to track compute unit increase
19-
test.set_bpf_compute_max_units(30_000);
19+
test.set_bpf_compute_max_units(45_000);
2020

2121
let user_accounts_owner = Keypair::new();
2222
let lending_market = add_lending_market(&mut test);
@@ -33,13 +33,26 @@ async fn test_success() {
3333
liquidity_amount: 10_000 * FRACTIONAL_TO_USDC,
3434
liquidity_mint_decimals: usdc_mint.decimals,
3535
liquidity_mint_pubkey: usdc_mint.pubkey,
36+
borrow_amount: 5_000 * FRACTIONAL_TO_USDC,
3637
config: test_reserve_config(),
3738
mark_fresh: true,
3839
..AddReserveArgs::default()
3940
},
4041
);
4142

42-
let (mut banks_client, payer, _recent_blockhash) = test.start().await;
43+
let mut test_context = test.start_with_context().await;
44+
test_context.warp_to_slot(300).unwrap(); // clock.slot = 300
45+
46+
let ProgramTestContext {
47+
mut banks_client,
48+
payer,
49+
..
50+
} = test_context;
51+
52+
let initial_ctoken_amount =
53+
get_token_balance(&mut banks_client, usdc_test_reserve.user_collateral_pubkey).await;
54+
let pre_usdc_reserve = usdc_test_reserve.get_state(&mut banks_client).await;
55+
let old_borrow_rate = pre_usdc_reserve.liquidity.cumulative_borrow_rate_wads;
4356

4457
lending_market
4558
.deposit(
@@ -50,4 +63,17 @@ async fn test_success() {
5063
100 * FRACTIONAL_TO_USDC,
5164
)
5265
.await;
66+
67+
let usdc_reserve = usdc_test_reserve.get_state(&mut banks_client).await;
68+
assert_eq!(usdc_reserve.last_update.stale, true);
69+
70+
let user_remaining_liquidity_amount =
71+
get_token_balance(&mut banks_client, usdc_test_reserve.user_liquidity_pubkey).await;
72+
assert_eq!(user_remaining_liquidity_amount, 0);
73+
74+
let final_ctoken_amount =
75+
get_token_balance(&mut banks_client, usdc_test_reserve.user_collateral_pubkey).await;
76+
assert!(final_ctoken_amount - initial_ctoken_amount < 100 * FRACTIONAL_TO_USDC);
77+
78+
assert!(usdc_reserve.liquidity.cumulative_borrow_rate_wads > old_borrow_rate);
5379
}

token-lending/program/tests/deposit_reserve_liquidity_and_obligation_collateral.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,11 +50,6 @@ async fn test_success() {
5050

5151
test_obligation.validate_state(&mut banks_client).await;
5252

53-
// let initial_collateral_supply_balance =
54-
// get_token_balance(&mut banks_client, usdc_test_reserve.collateral_supply_pubkey).await;
55-
// let initial_user_collateral_balance =
56-
// get_token_balance(&mut banks_client, usdc_test_reserve.user_collateral_pubkey).await;
57-
5853
lending_market
5954
.deposit_obligation_and_collateral(
6055
&mut banks_client,

token-lending/program/tests/obligation_end_to_end.rs

Lines changed: 25 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -123,13 +123,6 @@ async fn test_success() {
123123
user_accounts_owner_pubkey,
124124
),
125125
// 2
126-
refresh_reserve(
127-
spl_token_lending::id(),
128-
sol_test_reserve.pubkey,
129-
sol_oracle.pyth_price_pubkey,
130-
sol_oracle.switchboard_feed_pubkey,
131-
),
132-
// 3
133126
approve(
134127
&spl_token::id(),
135128
&sol_test_reserve.user_collateral_pubkey,
@@ -139,7 +132,7 @@ async fn test_success() {
139132
SOL_DEPOSIT_AMOUNT_LAMPORTS,
140133
)
141134
.unwrap(),
142-
// 4
135+
// 3
143136
deposit_obligation_collateral(
144137
spl_token_lending::id(),
145138
SOL_DEPOSIT_AMOUNT_LAMPORTS,
@@ -151,19 +144,26 @@ async fn test_success() {
151144
user_accounts_owner_pubkey,
152145
user_transfer_authority_pubkey,
153146
),
154-
// 5
155-
refresh_obligation(
156-
spl_token_lending::id(),
157-
obligation_pubkey,
158-
vec![sol_test_reserve.pubkey],
159-
),
160-
// 6
147+
// 4
161148
refresh_reserve(
162149
spl_token_lending::id(),
163150
usdc_test_reserve.pubkey,
164151
usdc_oracle.pyth_price_pubkey,
165152
usdc_oracle.switchboard_feed_pubkey,
166153
),
154+
// 5
155+
refresh_reserve(
156+
spl_token_lending::id(),
157+
sol_test_reserve.pubkey,
158+
sol_oracle.pyth_price_pubkey,
159+
sol_oracle.switchboard_feed_pubkey,
160+
),
161+
// 6
162+
refresh_obligation(
163+
spl_token_lending::id(),
164+
obligation_pubkey,
165+
vec![sol_test_reserve.pubkey],
166+
),
167167
// 7
168168
borrow_obligation_liquidity(
169169
spl_token_lending::id(),
@@ -178,19 +178,6 @@ async fn test_success() {
178178
Some(usdc_test_reserve.liquidity_host_pubkey),
179179
),
180180
// 8
181-
refresh_reserve(
182-
spl_token_lending::id(),
183-
usdc_test_reserve.pubkey,
184-
usdc_oracle.pyth_price_pubkey,
185-
usdc_oracle.switchboard_feed_pubkey,
186-
),
187-
// 9
188-
refresh_obligation(
189-
spl_token_lending::id(),
190-
obligation_pubkey,
191-
vec![sol_test_reserve.pubkey, usdc_test_reserve.pubkey],
192-
),
193-
// 10
194181
approve(
195182
&spl_token::id(),
196183
&usdc_test_reserve.user_liquidity_pubkey,
@@ -200,7 +187,7 @@ async fn test_success() {
200187
USDC_REPAY_AMOUNT_FRACTIONAL,
201188
)
202189
.unwrap(),
203-
// 11
190+
// 9
204191
repay_obligation_liquidity(
205192
spl_token_lending::id(),
206193
USDC_REPAY_AMOUNT_FRACTIONAL,
@@ -211,13 +198,20 @@ async fn test_success() {
211198
lending_market.pubkey,
212199
user_transfer_authority_pubkey,
213200
),
214-
// 12
201+
// 10
202+
refresh_reserve(
203+
spl_token_lending::id(),
204+
usdc_test_reserve.pubkey,
205+
usdc_oracle.pyth_price_pubkey,
206+
usdc_oracle.switchboard_feed_pubkey,
207+
),
208+
// 11
215209
refresh_obligation(
216210
spl_token_lending::id(),
217211
obligation_pubkey,
218212
vec![sol_test_reserve.pubkey],
219213
),
220-
// 13
214+
// 12
221215
withdraw_obligation_collateral(
222216
spl_token_lending::id(),
223217
SOL_DEPOSIT_AMOUNT_LAMPORTS,

token-lending/program/tests/redeem_reserve_collateral.rs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,14 @@ async fn test_success() {
2424
);
2525

2626
// limit to track compute unit increase
27-
test.set_bpf_compute_max_units(29_000);
27+
test.set_bpf_compute_max_units(45_000);
2828

2929
let user_accounts_owner = Keypair::new();
3030
let lending_market = add_lending_market(&mut test);
3131

3232
const USDC_RESERVE_LIQUIDITY_FRACTIONAL: u64 = 10 * FRACTIONAL_TO_USDC;
3333
const COLLATERAL_AMOUNT: u64 = USDC_RESERVE_LIQUIDITY_FRACTIONAL * INITIAL_COLLATERAL_RATIO;
34+
const BORROWED_AMOUNT: u64 = FRACTIONAL_TO_USDC;
3435

3536
let usdc_mint = add_usdc_mint(&mut test);
3637
let usdc_oracle = add_usdc_oracle(&mut test);
@@ -41,16 +42,28 @@ async fn test_success() {
4142
&user_accounts_owner,
4243
AddReserveArgs {
4344
collateral_amount: COLLATERAL_AMOUNT,
44-
liquidity_amount: USDC_RESERVE_LIQUIDITY_FRACTIONAL,
45+
liquidity_amount: 2 * USDC_RESERVE_LIQUIDITY_FRACTIONAL,
4546
liquidity_mint_decimals: usdc_mint.decimals,
4647
liquidity_mint_pubkey: usdc_mint.pubkey,
48+
borrow_amount: BORROWED_AMOUNT,
4749
config: test_reserve_config(),
4850
mark_fresh: true,
4951
..AddReserveArgs::default()
5052
},
5153
);
5254

53-
let (mut banks_client, payer, recent_blockhash) = test.start().await;
55+
let mut test_context = test.start_with_context().await;
56+
test_context.warp_to_slot(300).unwrap(); // clock.slot = 300
57+
58+
let ProgramTestContext {
59+
mut banks_client,
60+
payer,
61+
last_blockhash: recent_blockhash,
62+
..
63+
} = test_context;
64+
65+
let pre_usdc_reserve = usdc_test_reserve.get_state(&mut banks_client).await;
66+
let old_borrow_rate = pre_usdc_reserve.liquidity.cumulative_borrow_rate_wads;
5467

5568
let user_transfer_authority = Keypair::new();
5669
let mut transaction = Transaction::new_with_payer(
@@ -84,4 +97,9 @@ async fn test_success() {
8497
recent_blockhash,
8598
);
8699
assert!(banks_client.process_transaction(transaction).await.is_ok());
100+
101+
let usdc_reserve = usdc_test_reserve.get_state(&mut banks_client).await;
102+
assert_eq!(usdc_reserve.last_update.stale, true);
103+
104+
assert!(usdc_reserve.liquidity.cumulative_borrow_rate_wads > old_borrow_rate);
87105
}

0 commit comments

Comments
 (0)