Skip to content

[bug] Default cumulative_borrow_rate_wads value to 1 in creating ObligationLiquidity #2

@yanCode

Description

@yanCode

Note

as the original project in https://github.com/solana-labs/solana-program-library is recently marked as archived, I have no way to add the PR directly to it. So i open the ticket to track it here. the original solana program is https://github.com/solana-labs/solana-program-library/tree/master/token-lendinghttps://github.com/solana-labs/solana-program-library/tree/master/token-lending

TL;DR

when creating ObligationLiquidity, it uses default value 1 for cumulative_borrow_rate_wads, but in fact, as borrowers borrowing from the system, the cumulative_borrow_rate_wads of a reserve can go up, higher than 1.

Detailed Explanation

In the original logic, when a borrower is borrowing a token from a reserve, it need to check if the borrow liquidity is here, using an upsert-like operation.

obligation
.find_or_add_liquidity_to_borrows(*borrow_reserve_info.key)?
.borrow(borrow_amount)?;

So, if this borrower's obligation is first time to borrow from this reseve, it needs to create a new instance of ObligationLiquidity into current Obligation to track this borrow (and following borrows for the same borrower borrowing the same token).

let liquidity = ObligationLiquidity::new(borrow_reserve);
self.borrows.push(liquidity);

The issue is ObligationLiquidity::new, as in line 26, using Decimal::one() as the cumulative_borrow_rate_wads.

impl ObligationLiquidity {
pub fn new(borrow_reserve: Pubkey) -> Self {
Self {
borrow_reserve,
cumulative_borrow_rate_wads: Decimal::one(),
..Default::default()
}
}

This can be a major issue, sets cumulative_borrow_rate_wads to 1, that's because in the whole system, only refresh obligation instruction can update the value of cumulative_borrow_rate_wads in accrue_interest

liquidity.accrue_interest(borrow_reserve.liquidity.cumulative_borrow_rate_wads)?;

if the ObligationLiquidity first time gets refrehsed, as in below. let's say, if Alice first time want to borrow from a reserve. but, Bob previously borrowed from the same reserve. At the time Alice is borrowing, the cumulative_borrow_rate_wads from the reseve can be higher than 1. but, it still stores 1 as the cumulative_borrow_rate_wads. that results in compounded_interest_rate incorrectly higher that it actually is.

let compounded_interest_rate: Rate = cumulative_borrow_rate_wads
.try_div(self.cumulative_borrow_rate_wads)?
.try_into()?;
self.borrowed_amount_wads = self
.borrowed_amount_wads
.try_mul(compounded_interest_rate)?;

How to fix this

To fix this issue, cumulative_borrow_rate_wads of the moment of creating a new ObligationLiquidity should be saved from the reserve. not using default value 1.

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions