Skip to content

Commit

Permalink
Merge pull request #37 from blend-capital/add-market-getter
Browse files Browse the repository at this point in the history
chore: add market endpoint and update internal reserve object to expose all data
  • Loading branch information
mootz12 authored Jan 22, 2025
2 parents e9615be + a36d054 commit bdda08c
Show file tree
Hide file tree
Showing 12 changed files with 362 additions and 344 deletions.
10 changes: 6 additions & 4 deletions pool/src/auctions/backstop_interest_auction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,14 @@ pub fn create_interest_auction_data(
// don't store updated reserve data back to ledger. This will occur on the the auction's fill.
// `load_reserve` will panic if the reserve does not exist
let reserve = pool.load_reserve(e, &lot_asset, false);
if reserve.backstop_credit > 0 {
if reserve.data.backstop_credit > 0 {
let asset_to_base = pool.load_price(e, &reserve.asset);
interest_value += i128(asset_to_base)
.fixed_mul_floor(reserve.backstop_credit, reserve.scalar)
.fixed_mul_floor(reserve.data.backstop_credit, reserve.scalar)
.unwrap_optimized();
auction_data.lot.set(reserve.asset, reserve.backstop_credit);
auction_data
.lot
.set(reserve.asset, reserve.data.backstop_credit);
}
}

Expand Down Expand Up @@ -110,7 +112,7 @@ pub fn fill_interest_auction(
// lot contains underlying tokens, but the backstop credit must be updated on the reserve
for (res_asset_address, lot_amount) in auction_data.lot.iter() {
let mut reserve = pool.load_reserve(e, &res_asset_address, true);
reserve.backstop_credit -= lot_amount;
reserve.data.backstop_credit -= lot_amount;
pool.cache_reserve(reserve);
TokenClient::new(e, &res_asset_address).transfer(
&e.current_contract_address(),
Expand Down
2 changes: 1 addition & 1 deletion pool/src/auctions/bad_debt_auction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ pub fn create_bad_debt_auction_data(
let reserve = pool.load_reserve(e, &bid_asset, false);
let liability_balance = backstop_positions
.liabilities
.get(reserve.index)
.get(reserve.config.index)
.unwrap_or(0);
if liability_balance > 0 {
let asset_to_base = pool.load_price(e, &reserve.asset);
Expand Down
12 changes: 8 additions & 4 deletions pool/src/auctions/user_liquidation_auction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,11 @@ pub fn create_user_liq_auction_data(
for bid_asset in bid {
// these will be cached if the bid is valid
let reserve = pool.load_reserve(e, &bid_asset, false);
match user_state.positions.liabilities.get(reserve.index) {
match user_state.positions.liabilities.get(reserve.config.index) {
Some(amount) => {
positions_auctioned.liabilities.set(reserve.index, amount);
positions_auctioned
.liabilities
.set(reserve.config.index, amount);
}
None => {
panic_with_error!(e, PoolError::InvalidBid);
Expand All @@ -72,9 +74,11 @@ pub fn create_user_liq_auction_data(
for lot_asset in lot {
// these will be cached if the lot is valid
let reserve = pool.load_reserve(e, &lot_asset, false);
match user_state.positions.collateral.get(reserve.index) {
match user_state.positions.collateral.get(reserve.config.index) {
Some(amount) => {
positions_auctioned.collateral.set(reserve.index, amount);
positions_auctioned
.collateral
.set(reserve.config.index, amount);
}
None => {
panic_with_error!(e, PoolError::InvalidLot);
Expand Down
110 changes: 64 additions & 46 deletions pool/src/contract.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,20 +71,28 @@ pub trait Pool {
/// Fetch the admin address of the pool
fn get_admin(e: Env) -> Address;

/// Fetch information about a reserve
/// Fetch information about a reserve, updated to the current ledger
///
/// ### Arguments
/// * `asset` - The address of the reserve asset
fn get_reserve(e: Env, asset: Address) -> Reserve;

/// Fetch data about the pool and its reserves.
///
/// Useful for external integrations that need to load all data about the pool
///
/// Returns a tuple with the pool configuration and a vector of reserves, where each reserve
/// is updated to the current ledger.
fn get_market(e: Env) -> (PoolConfig, Vec<Reserve>);

/// Fetch the positions for an address
///
/// ### Arguments
/// * `address` - The address to fetch positions for
fn get_positions(e: Env, address: Address) -> Positions;

/// Submit a set of requests to the pool where 'from' takes on the position, 'sender' sends any
/// required tokens to the pool and 'to' receives any tokens sent from the pool
/// required tokens to the pool and 'to' receives any tokens sent from the pool.
///
/// Returns the new positions for 'from'
///
Expand All @@ -104,46 +112,48 @@ pub trait Pool {
requests: Vec<Request>,
) -> Positions;

/// Submit a set of requests to the pool where 'from' takes on the position, 'sender' sends any
/// required tokens to the pool and 'to' receives any tokens sent from the pool
/// Submit a set of requests to the pool where 'from' takes on the position, 'spender' sends any
/// required tokens to the pool using transfer_from and 'to' receives any tokens sent from the pool.
///
/// Returns the new positions for 'from'
///
/// ### Arguments
/// * `from` - The address of the user whose positions are being modified and also the address of
/// the user who is sending and receiving the tokens to the pool.
/// * `flash_loan` - Arguments relative to the flash loan: receiver contract, asset and borroed amount.
/// * `from` - The address of the user whose positions are being modified
/// * `spender` - The address of the user who is sending tokens to the pool
/// * `to` - The address of the user who is receiving tokens from the pool
/// * `requests` - A vec of requests to be processed
///
/// ### Panics
/// If the request is not able to be completed for cases like insufficient funds or invalid health factor
fn flash_loan(
/// If the request is not able to be completed for cases like insufficient funds, insufficient allowance, or invalid health factor
fn submit_with_allowance(
e: Env,
from: Address,
flash_loan: FlashLoan,
spender: Address,
to: Address,
requests: Vec<Request>,
) -> Positions;

/// Submit a set of requests to the pool where 'from' takes on the position, 'spender' sends any
/// required tokens to the pool USING transfer_from and 'to' receives any tokens sent from the pool.
/// Submit flash loan and a set of requests to the pool where 'from' takes on the position. The flash loan will be invoked using
/// the 'flash_loan' arguments and 'from' as the caller. For the requests, 'from' sends any required tokens to the pool
/// using transfer_from and receives any tokens sent from the pool.
///
/// Returns the new positions for 'from'
///
/// ### Arguments
/// * `from` - The address of the user whose positions are being modified
/// * `spender` - The address of the user who is sending tokens to the pool
/// * `to` - The address of the user who is receiving tokens from the pool
/// * `from` - The address of the user whose positions are being modified and also the address of
/// the user who is sending and receiving the tokens to the pool.
/// * `flash_loan` - Arguments relative to the flash loan: receiver contract, asset and borroed amount.
/// * `requests` - A vec of requests to be processed
///
/// ### Panics
/// If the request is not able to be completed for cases like insufficient funds, insufficient allowance, or invalid health factor
fn submit_with_allowance(
/// If the request is not able to be completed for cases like insufficient funds ,insufficient allowance, or invalid health factor
fn flash_loan(
e: Env,
from: Address,
spender: Address,
to: Address,
flash_loan: FlashLoan,
requests: Vec<Request>,
) -> Positions;

/// Manage bad debt. Debt is considered "bad" if there is no longer has any collateral posted.
///
/// To manage a user's bad debt, all collateralized reserves for the user must be liquidated
Expand Down Expand Up @@ -229,20 +239,21 @@ pub trait Pool {
/// * `to` - The Address to send the claimed tokens to
fn claim(e: Env, from: Address, reserve_token_ids: Vec<u32>, to: Address) -> i128;

/// Get the emissions data for a reserve
/// Get the emissions data for a reserve token
///
/// ### Arguments
/// * `reserve_token_id` - The reserve token id. This is a unique identifier for the type of position in a pool. For
/// dTokens, a reserve token id (reserve_index * 2). For bTokens, a reserve token id (reserve_index * 2) + 1.
fn get_reserve_emissions(e: Env, reserve_token_id: u32) -> ReserveEmissionData;
fn get_reserve_emissions(e: Env, reserve_token_id: u32) -> Option<ReserveEmissionData>;

/// Get the emissions data for a user
///
/// ### Arguments
/// * `user` - The address of the user
/// * `reserve_token_id` - The reserve token id. This is a unique identifier for the type of position in a pool. For
/// dTokens, a reserve token id (reserve_index * 2). For bTokens, a reserve token id (reserve_index * 2) + 1.
fn get_user_emissions(e: Env, user: Address, reserve_token_id: u32) -> UserEmissionData;
fn get_user_emissions(e: Env, user: Address, reserve_token_id: u32)
-> Option<UserEmissionData>;

/***** Auction / Liquidation Functions *****/

Expand Down Expand Up @@ -379,6 +390,17 @@ impl Pool for PoolContract {
Reserve::load(&e, &pool_config, &asset)
}

fn get_market(e: Env) -> (PoolConfig, Vec<Reserve>) {
let pool_config = storage::get_pool_config(&e);
let res_list = storage::get_res_list(&e);
let mut reserves = Vec::<Reserve>::new(&e);
for res_address in res_list.iter() {
let res = Reserve::load(&e, &pool_config, &res_address);
reserves.push_back(res);
}
(pool_config, reserves)
}

fn get_positions(e: Env, address: Address) -> Positions {
storage::get_user_positions(&e, &address)
}
Expand All @@ -399,18 +421,6 @@ impl Pool for PoolContract {
pool::execute_submit(&e, &from, &spender, &to, requests, false)
}

fn flash_loan(
e: Env,
from: Address,
flash_loan: FlashLoan,
requests: Vec<Request>,
) -> Positions {
storage::extend_instance(&e);
from.require_auth();

pool::execute_submit_with_flash_loan(&e, &from, flash_loan, requests)
}

fn submit_with_allowance(
e: Env,
from: Address,
Expand All @@ -427,6 +437,18 @@ impl Pool for PoolContract {
pool::execute_submit(&e, &from, &spender, &to, requests, true)
}

fn flash_loan(
e: Env,
from: Address,
flash_loan: FlashLoan,
requests: Vec<Request>,
) -> Positions {
storage::extend_instance(&e);
from.require_auth();

pool::execute_submit_with_flash_loan(&e, &from, flash_loan, requests)
}

fn bad_debt(e: Env, user: Address) {
pool::transfer_bad_debt_to_backstop(&e, &user);
}
Expand Down Expand Up @@ -484,20 +506,16 @@ impl Pool for PoolContract {
amount_claimed
}

fn get_reserve_emissions(e: Env, reserve_token_index: u32) -> ReserveEmissionData {
storage::get_res_emis_data(&e, &reserve_token_index).unwrap_or(ReserveEmissionData {
expiration: 0,
eps: 0,
index: 0,
last_time: 0,
})
fn get_reserve_emissions(e: Env, reserve_token_index: u32) -> Option<ReserveEmissionData> {
storage::get_res_emis_data(&e, &reserve_token_index)
}

fn get_user_emissions(e: Env, user: Address, reserve_token_index: u32) -> UserEmissionData {
storage::get_user_emissions(&e, &user, &reserve_token_index).unwrap_or(UserEmissionData {
index: 0,
accrued: 0,
})
fn get_user_emissions(
e: Env,
user: Address,
reserve_token_index: u32,
) -> Option<UserEmissionData> {
storage::get_user_emissions(&e, &user, &reserve_token_index)
}

/***** Auction / Liquidation Functions *****/
Expand Down
34 changes: 21 additions & 13 deletions pool/src/pool/actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ pub fn build_actions_from_request(
}
RequestType::Withdraw => {
let mut reserve = pool.load_reserve(e, &request.address, true);
let cur_b_tokens = from_state.get_supply(reserve.index);
let cur_b_tokens = from_state.get_supply(reserve.config.index);
let mut to_burn = reserve.to_b_token_up(request.amount);
let mut tokens_out = request.amount;
if to_burn > cur_b_tokens {
Expand All @@ -171,7 +171,9 @@ pub fn build_actions_from_request(
let b_tokens_minted = reserve.to_b_token_down(request.amount);
from_state.add_collateral(e, &mut reserve, b_tokens_minted);
actions.add_for_spender_transfer(&reserve.asset, request.amount);
if reserve.to_asset_from_b_token(reserve.b_supply) > reserve.collateral_cap {
if reserve.to_asset_from_b_token(reserve.data.b_supply)
> reserve.config.collateral_cap
{
panic_with_error!(e, PoolError::ExceededCollateralCap);
}
pool.cache_reserve(reserve);
Expand All @@ -185,7 +187,7 @@ pub fn build_actions_from_request(
}
RequestType::WithdrawCollateral => {
let mut reserve = pool.load_reserve(e, &request.address, true);
let cur_b_tokens = from_state.get_collateral(reserve.index);
let cur_b_tokens = from_state.get_collateral(reserve.config.index);
let mut to_burn = reserve.to_b_token_up(request.amount);
let mut tokens_out = request.amount;
if to_burn > cur_b_tokens {
Expand Down Expand Up @@ -223,7 +225,7 @@ pub fn build_actions_from_request(
}
RequestType::Repay => {
let mut reserve = pool.load_reserve(e, &request.address, true);
let cur_d_tokens = from_state.get_liabilities(reserve.index);
let cur_d_tokens = from_state.get_liabilities(reserve.config.index);
let d_tokens_burnt = reserve.to_d_token_down(request.amount);
if d_tokens_burnt > cur_d_tokens {
let cur_underlying_borrowed = reserve.to_asset_from_d_token(cur_d_tokens);
Expand Down Expand Up @@ -413,7 +415,10 @@ mod tests {
assert_eq!(user.get_supply(0), 10_1234488);

let reserve = pool.load_reserve(&e, &underlying, false);
assert_eq!(reserve.b_supply, reserve_data.b_supply + user.get_supply(0));
assert_eq!(
reserve.data.b_supply,
reserve_data.b_supply + user.get_supply(0)
);
});
}

Expand Down Expand Up @@ -487,7 +492,7 @@ mod tests {

let reserve = pool.load_reserve(&e, &underlying, false);
assert_eq!(
reserve.b_supply,
reserve.data.b_supply,
reserve_data.b_supply - (20_0000000 - 9_8765502)
);
});
Expand Down Expand Up @@ -558,7 +563,7 @@ mod tests {
assert_eq!(positions.supply.len(), 0);

let reserve = pool.load_reserve(&e, &underlying.clone(), false);
assert_eq!(reserve.b_supply, reserve_data.b_supply - 20_0000000);
assert_eq!(reserve.data.b_supply, reserve_data.b_supply - 20_0000000);
});
}

Expand Down Expand Up @@ -628,7 +633,7 @@ mod tests {

let reserve = pool.load_reserve(&e, &underlying.clone(), false);
assert_eq!(
reserve.b_supply,
reserve.data.b_supply,
reserve_data.b_supply + user.get_collateral(0)
);
});
Expand Down Expand Up @@ -703,7 +708,7 @@ mod tests {

let reserve = pool.load_reserve(&e, &underlying, false);
assert_eq!(
reserve.b_supply,
reserve.data.b_supply,
reserve_data.b_supply - (20_0000000 - 9_8765502)
);
});
Expand Down Expand Up @@ -774,7 +779,7 @@ mod tests {
assert_eq!(positions.supply.len(), 0);

let reserve = pool.load_reserve(&e, &underlying, false);
assert_eq!(reserve.b_supply, reserve_data.b_supply - 20_0000000);
assert_eq!(reserve.data.b_supply, reserve_data.b_supply - 20_0000000);
});
}

Expand Down Expand Up @@ -839,7 +844,7 @@ mod tests {
assert_eq!(user.get_liabilities(0), 10_1234452);

let reserve = pool.load_reserve(&e, &underlying, false);
assert_eq!(reserve.d_supply, reserve_data.d_supply + 10_1234452);
assert_eq!(reserve.data.d_supply, reserve_data.d_supply + 10_1234452);
});
}

Expand Down Expand Up @@ -915,7 +920,10 @@ mod tests {
assert_eq!(user.get_liabilities(0), 20_0000000 - d_tokens_repaid);

let reserve = pool.load_reserve(&e, &underlying, false);
assert_eq!(reserve.d_supply, reserve_data.d_supply - d_tokens_repaid);
assert_eq!(
reserve.data.d_supply,
reserve_data.d_supply - d_tokens_repaid
);
});
}

Expand Down Expand Up @@ -988,7 +996,7 @@ mod tests {
assert_eq!(positions.supply.len(), 0);

let reserve = pool.load_reserve(&e, &underlying, false);
assert_eq!(reserve.d_supply, reserve_data.d_supply - 20_0000000);
assert_eq!(reserve.data.d_supply, reserve_data.d_supply - 20_0000000);
});
}

Expand Down
Loading

0 comments on commit bdda08c

Please sign in to comment.