Skip to content

Commit ea05dd3

Browse files
authored
[Liquidity Mining] Obligation packing & unpacking (5) (#204)
* optimized reserve (un)packing * obligation dynamically (un)packs * fixed BPF tests * using account discriminator
1 parent 389a7d8 commit ea05dd3

31 files changed

+909
-311
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ hfuzz_workspace
1010
**/*.so
1111
**/.DS_Store
1212
test-ledger
13+
cargo-test-*.profraw

token-lending/cli/src/main.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -781,7 +781,6 @@ fn main() {
781781
.required(true)
782782
.help("Reserve address"),
783783
)
784-
785784
)
786785
.subcommand(
787786
SubCommand::with_name("update-reserve")

token-lending/program/src/processor.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -983,7 +983,7 @@ fn process_init_obligation(program_id: &Pubkey, accounts: &[AccountInfo]) -> Pro
983983
let token_program_id = next_account_info(account_info_iter)?;
984984

985985
assert_rent_exempt(rent, obligation_info)?;
986-
let mut obligation = assert_uninitialized::<Obligation>(obligation_info)?;
986+
let mut obligation = Obligation::unpack_uninitialized(&obligation_info.data.borrow())?;
987987
if obligation_info.owner != program_id {
988988
msg!("Obligation provided is not owned by the lending program");
989989
return Err(LendingError::InvalidAccountOwner.into());

token-lending/program/src/processor/liquidity_mining.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77
//! implementation of the same feature.
88
//!
99
//! There are three admin-only ixs:
10-
//! - [add_pool_reward]
11-
//! - [cancel_pool_reward]
12-
//! - [close_pool_reward]
10+
//! - [add_pool_reward] (TODO: add bpf tests)
11+
//! - [cancel_pool_reward] (TODO: add bpf tests)
12+
//! - [close_pool_reward] (TODO: add bpf tests)
1313
//!
1414
//! [suilend-lm]: https://github.com/solendprotocol/suilend/blob/dc53150416f352053ac3acbb320ee143409c4a5d/contracts/suilend/sources/liquidity_mining.move#L2
1515
@@ -33,6 +33,7 @@ use solana_program::{
3333
system_instruction,
3434
sysvar::Sysvar,
3535
};
36+
use solend_sdk::state::discriminator::AccountDiscriminator;
3637
use solend_sdk::{
3738
error::LendingError,
3839
state::{LendingMarket, PositionKind, Reserve},
@@ -282,9 +283,16 @@ pub(crate) fn upgrade_reserve(program_id: &Pubkey, accounts: &[AccountInfo]) ->
282283
// 3.
283284
//
284285

285-
// sanity checks pack and unpack reserves is ok
286-
let reserve = Reserve::unpack(&accounts.reserve_info.data.borrow())?;
287-
Reserve::pack(reserve, &mut accounts.reserve_info.data.borrow_mut())?;
286+
// we upgrade discriminator as we've checked that the account is indeed
287+
// a reserve account in [UpgradeReserveAccounts::from_unchecked_iter]
288+
let mut data = accounts.reserve_info.data.borrow_mut();
289+
data[0] = AccountDiscriminator::Reserve as u8;
290+
// Now the reserve can unpack fine and doesn't have to worry about
291+
// migrations.
292+
// Instead it returns an error on an invalid discriminator.
293+
// This way a reserve cannot be mistaken for an obligation.
294+
let reserve = Reserve::unpack(&data)?;
295+
Reserve::pack(reserve, &mut data)?;
288296

289297
Ok(())
290298
}

token-lending/program/tests/attributed_borrows.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use solana_program::native_token::LAMPORTS_PER_SOL;
2222

2323
use solend_sdk::math::Decimal;
2424

25-
use solend_program::state::{Obligation, ReserveConfig};
25+
use solend_program::state::ReserveConfig;
2626

2727
use solend_sdk::state::ReserveFees;
2828
mod helpers;
@@ -398,7 +398,7 @@ async fn test_calculations() {
398398
.await
399399
.unwrap();
400400

401-
let obligation_post = test.load_account::<Obligation>(obligations[0].pubkey).await;
401+
let obligation_post = test.load_obligation(obligations[0].pubkey).await;
402402

403403
// obligation 0 after borrowing 10 usd
404404
// usdc.borrow_attribution = 80 / 100 * 30 = 24
@@ -688,7 +688,7 @@ async fn test_withdraw() {
688688
Decimal::from_percent(250)
689689
);
690690

691-
let obligation_post = test.load_account::<Obligation>(obligations[0].pubkey).await;
691+
let obligation_post = test.load_obligation(obligations[0].pubkey).await;
692692
assert_eq!(
693693
obligation_post.account.deposits[0].attributed_borrow_value,
694694
Decimal::from(7500u64)
@@ -733,7 +733,7 @@ async fn test_withdraw() {
733733
Decimal::zero()
734734
);
735735

736-
let obligation_post = test.load_account::<Obligation>(obligations[0].pubkey).await;
736+
let obligation_post = test.load_obligation(obligations[0].pubkey).await;
737737
assert_eq!(
738738
obligation_post.account.deposits[0].attributed_borrow_value,
739739
Decimal::from(10u64)

token-lending/program/tests/borrow_obligation_liquidity.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ async fn setup(
7777
.unwrap();
7878

7979
// populate deposit value correctly.
80-
let obligation = test.load_account::<Obligation>(obligation.pubkey).await;
80+
let obligation = test.load_obligation(obligation.pubkey).await;
8181
lending_market
8282
.refresh_obligation(&mut test, &obligation)
8383
.await
@@ -86,7 +86,7 @@ async fn setup(
8686
let lending_market = test.load_account(lending_market.pubkey).await;
8787
let usdc_reserve = test.load_account(usdc_reserve.pubkey).await;
8888
let wsol_reserve = test.load_account(wsol_reserve.pubkey).await;
89-
let obligation = test.load_account::<Obligation>(obligation.pubkey).await;
89+
let obligation = test.load_obligation(obligation.pubkey).await;
9090

9191
let host_fee_receiver = User::new_with_balances(&mut test, &[(&wsol_mint::id(), 0)]).await;
9292
(
@@ -244,7 +244,7 @@ async fn test_success() {
244244
wsol_reserve_post, expected_wsol_reserve_post
245245
);
246246

247-
let obligation_post = test.load_account::<Obligation>(obligation.pubkey).await;
247+
let obligation_post = test.load_obligation(obligation.pubkey).await;
248248
assert_eq!(
249249
obligation_post.account,
250250
Obligation {

token-lending/program/tests/borrow_weight.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ async fn test_refresh_obligation() {
3737
.await
3838
.unwrap();
3939

40-
let obligation_post = test.load_account::<Obligation>(obligation.pubkey).await;
40+
let obligation_post = test.load_obligation(obligation.pubkey).await;
4141

4242
// obligation has borrowed 10 sol and sol = $10 but since borrow weight == 2, the
4343
// borrowed_value is 200 instead of 100.
@@ -134,7 +134,7 @@ async fn test_borrow() {
134134
.await
135135
.unwrap();
136136

137-
let obligation_post = test.load_account::<Obligation>(obligation.pubkey).await;
137+
let obligation_post = test.load_obligation(obligation.pubkey).await;
138138
// - usdc ltv is 0.5,
139139
// - sol borrow weight is 2
140140
// max you can borrow is 100 * 0.5 / 2 = 2.5 SOL
@@ -176,7 +176,7 @@ async fn test_borrow() {
176176

177177
test.advance_clock_by_slots(1).await;
178178

179-
let obligation = test.load_account::<Obligation>(obligation.pubkey).await;
179+
let obligation = test.load_obligation(obligation.pubkey).await;
180180

181181
// max withdraw
182182
{
@@ -302,7 +302,7 @@ async fn test_liquidation() {
302302
.await
303303
.unwrap();
304304

305-
let obligation_post = test.load_account::<Obligation>(obligation.pubkey).await;
305+
let obligation_post = test.load_obligation(obligation.pubkey).await;
306306
// - usdc ltv is 0.5,
307307
// - sol borrow weight is 1
308308
// max you can borrow is 100 * 0.5 = 5 SOL

token-lending/program/tests/deposit_obligation_collateral.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ async fn test_success() {
8080
let usdc_reserve_post = test.load_account(usdc_reserve.pubkey).await;
8181
assert_eq!(usdc_reserve, usdc_reserve_post);
8282

83-
let obligation_post = test.load_account::<Obligation>(obligation.pubkey).await;
83+
let obligation_post = test.load_obligation(obligation.pubkey).await;
8484
assert_eq!(
8585
obligation_post.account,
8686
Obligation {

token-lending/program/tests/deposit_reserve_liquidity_and_obligation_collateral.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ async fn test_success() {
119119
}
120120
);
121121

122-
let obligation_post = test.load_account::<Obligation>(obligation.pubkey).await;
122+
let obligation_post = test.load_obligation(obligation.pubkey).await;
123123
assert_eq!(
124124
obligation_post.account,
125125
Obligation {

token-lending/program/tests/forgive_debt.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ async fn test_forgive_debt_success_easy() {
165165
.await
166166
.unwrap();
167167

168-
let obligation_post = test.load_account::<Obligation>(obligations[0].pubkey).await;
168+
let obligation_post = test.load_obligation(obligations[0].pubkey).await;
169169
assert_eq!(
170170
obligation_post.account,
171171
Obligation {
@@ -182,6 +182,7 @@ async fn test_forgive_debt_success_easy() {
182182
allowed_borrow_value: Decimal::zero(),
183183
unhealthy_borrow_value: Decimal::zero(),
184184
super_unhealthy_borrow_value: Decimal::zero(),
185+
user_reward_managers: obligation_post.account.user_reward_managers.clone(),
185186
..obligations[0].account
186187
}
187188
);

0 commit comments

Comments
 (0)