diff --git a/pool/src/auctions/backstop_interest_auction.rs b/pool/src/auctions/backstop_interest_auction.rs index 73c0fce..d77519c 100644 --- a/pool/src/auctions/backstop_interest_auction.rs +++ b/pool/src/auctions/backstop_interest_auction.rs @@ -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); } } @@ -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(), diff --git a/pool/src/auctions/bad_debt_auction.rs b/pool/src/auctions/bad_debt_auction.rs index 98873df..7c517ed 100644 --- a/pool/src/auctions/bad_debt_auction.rs +++ b/pool/src/auctions/bad_debt_auction.rs @@ -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); diff --git a/pool/src/auctions/user_liquidation_auction.rs b/pool/src/auctions/user_liquidation_auction.rs index 3f91395..51e6cf2 100644 --- a/pool/src/auctions/user_liquidation_auction.rs +++ b/pool/src/auctions/user_liquidation_auction.rs @@ -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); @@ -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); diff --git a/pool/src/contract.rs b/pool/src/contract.rs index 7625981..b27f0f6 100644 --- a/pool/src/contract.rs +++ b/pool/src/contract.rs @@ -71,12 +71,20 @@ 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); + /// Fetch the positions for an address /// /// ### Arguments @@ -84,7 +92,7 @@ pub trait Pool { 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' /// @@ -104,46 +112,48 @@ pub trait Pool { requests: Vec, ) -> 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, ) -> 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, ) -> 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 @@ -229,12 +239,12 @@ pub trait Pool { /// * `to` - The Address to send the claimed tokens to fn claim(e: Env, from: Address, reserve_token_ids: Vec, 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; /// Get the emissions data for a user /// @@ -242,7 +252,8 @@ pub trait Pool { /// * `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; /***** Auction / Liquidation Functions *****/ @@ -379,6 +390,17 @@ impl Pool for PoolContract { Reserve::load(&e, &pool_config, &asset) } + fn get_market(e: Env) -> (PoolConfig, Vec) { + let pool_config = storage::get_pool_config(&e); + let res_list = storage::get_res_list(&e); + let mut reserves = Vec::::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) } @@ -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, - ) -> 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, @@ -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, + ) -> 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); } @@ -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 { + 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 { + storage::get_user_emissions(&e, &user, &reserve_token_index) } /***** Auction / Liquidation Functions *****/ diff --git a/pool/src/pool/actions.rs b/pool/src/pool/actions.rs index 49ef500..a04ce50 100644 --- a/pool/src/pool/actions.rs +++ b/pool/src/pool/actions.rs @@ -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 { @@ -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); @@ -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 { @@ -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); @@ -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) + ); }); } @@ -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) ); }); @@ -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); }); } @@ -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) ); }); @@ -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) ); }); @@ -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); }); } @@ -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); }); } @@ -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 + ); }); } @@ -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); }); } diff --git a/pool/src/pool/config.rs b/pool/src/pool/config.rs index 614f37b..e969b37 100644 --- a/pool/src/pool/config.rs +++ b/pool/src/pool/config.rs @@ -110,7 +110,7 @@ fn initialize_reserve(e: &Env, asset: &Address, config: &ReserveConfig) -> u32 { let mut pool = Pool::load(e); // @dev: Store the reserve to ledger manually let mut reserve = pool.load_reserve(e, asset, false); - index = reserve.index; + index = reserve.config.index; let reserve_config = storage::get_res_config(e, asset); // decimals cannot change if reserve_config.decimals != config.decimals { @@ -123,7 +123,7 @@ fn initialize_reserve(e: &Env, asset: &Address, config: &ReserveConfig) -> u32 { || reserve_config.r_three != config.r_three || reserve_config.util != config.util { - reserve.ir_mod = SCALAR_9; + reserve.data.ir_mod = SCALAR_9; } reserve.store(e); } else { diff --git a/pool/src/pool/gulp.rs b/pool/src/pool/gulp.rs index b5ee801..c61c6d9 100644 --- a/pool/src/pool/gulp.rs +++ b/pool/src/pool/gulp.rs @@ -17,19 +17,19 @@ pub fn execute_gulp(e: &Env, asset: &Address) -> (i128, i128) { let mut reserve = Reserve::load(e, &pool_config, asset); let pool_token_balance = TokenClient::new(e, asset).balance(&e.current_contract_address()); let reserve_token_balance = - reserve.total_supply() + reserve.backstop_credit - reserve.total_liabilities(); + reserve.total_supply() + reserve.data.backstop_credit - reserve.total_liabilities(); let token_balance_delta = pool_token_balance - reserve_token_balance; - let pre_gulp_b_rate = reserve.b_rate; + let pre_gulp_b_rate = reserve.data.b_rate; reserve.gulp(pool_config.bstop_rate, token_balance_delta); // If the reserve's b_rate hasn't changed the token delta is not significant - if pre_gulp_b_rate == reserve.b_rate { + if pre_gulp_b_rate == reserve.data.b_rate { return (0, pre_gulp_b_rate); } reserve.store(e); - return (token_balance_delta, reserve.b_rate); + return (token_balance_delta, reserve.data.b_rate); } #[cfg(test)] diff --git a/pool/src/pool/pool.rs b/pool/src/pool/pool.rs index c356882..4236571 100644 --- a/pool/src/pool/pool.rs +++ b/pool/src/pool/pool.rs @@ -195,12 +195,12 @@ mod tests { ); let new_reserve = pool.load_reserve(&e, &underlying, true); - assert_eq!(new_reserve.d_rate, reserve.d_rate); + assert_eq!(new_reserve.data.d_rate, reserve.data.d_rate); // store all cached reserves and verify the data is updated pool.store_cached_reserves(&e); let new_reserve_data = storage::get_res_data(&e, &underlying); - assert_eq!(new_reserve_data.d_rate, reserve.d_rate); + assert_eq!(new_reserve_data.d_rate, reserve.data.d_rate); }); } @@ -250,13 +250,13 @@ mod tests { let reserve_0 = pool.load_reserve(&e, &underlying_0, false); let mut reserve_1 = pool.load_reserve(&e, &underlying_1, true); let mut reserve_2 = pool.load_reserve(&e, &underlying_2, true); - reserve_2.d_rate = 456; + reserve_2.data.d_rate = 456; pool.cache_reserve(reserve_0.clone()); pool.cache_reserve(reserve_1.clone()); pool.cache_reserve(reserve_2.clone()); // verify a duplicate cache takes the most recently cached - reserve_1.d_rate = 123; + reserve_1.data.d_rate = 123; pool.cache_reserve(reserve_1.clone()); // verify reloading without store flag still stores reserve @@ -278,7 +278,7 @@ mod tests { ); let new_reserve = pool.load_reserve(&e, &underlying_0, false); - assert_eq!(new_reserve.d_rate, reserve_0.d_rate); + assert_eq!(new_reserve.data.d_rate, reserve_0.data.d_rate); // store all cached reserves and verify the temp one was not stored pool.store_cached_reserves(&e); @@ -338,8 +338,8 @@ mod tests { let reserve_0 = pool.load_reserve(&e, &underlying_0, false); let mut reserve_1 = pool.load_reserve(&e, &underlying_1, true); let mut reserve_2 = pool.load_reserve(&e, &underlying_2, true); - reserve_1.b_rate = 123; - reserve_2.d_rate = 456; + reserve_1.data.b_rate = 123; + reserve_2.data.d_rate = 456; pool.cache_reserve(reserve_0.clone()); pool.cache_reserve(reserve_1.clone()); // pool.cache_reserve(reserve_2.clone()); @@ -655,7 +655,7 @@ mod tests { let mut reserve_0 = testutils::default_reserve(&e); let mut reserve_1 = testutils::default_reserve(&e); - reserve_1.index = 1; + reserve_1.config.index = 1; let (oracle, _) = testutils::create_mock_oracle(&e); let mut user = User { @@ -691,7 +691,7 @@ mod tests { let mut reserve_0 = testutils::default_reserve(&e); let mut reserve_1 = testutils::default_reserve(&e); - reserve_1.index = 1; + reserve_1.config.index = 1; let (oracle, _) = testutils::create_mock_oracle(&e); let mut user = User { @@ -729,7 +729,7 @@ mod tests { let mut reserve_0 = testutils::default_reserve(&e); let mut reserve_1 = testutils::default_reserve(&e); - reserve_1.index = 1; + reserve_1.config.index = 1; let mut user = User { address: samwise.clone(), diff --git a/pool/src/pool/reserve.rs b/pool/src/pool/reserve.rs index 2650852..771d214 100644 --- a/pool/src/pool/reserve.rs +++ b/pool/src/pool/reserve.rs @@ -6,7 +6,7 @@ use crate::{ constants::{SCALAR_7, SCALAR_9}, errors::PoolError, pool::actions::RequestType, - storage::{self, PoolConfig, ReserveData}, + storage::{self, PoolConfig, ReserveConfig, ReserveData}, }; use super::interest::calc_accrual; @@ -15,20 +15,9 @@ use super::interest::calc_accrual; #[contracttype] pub struct Reserve { pub asset: Address, // the underlying asset address - pub index: u32, // the reserve index in the pool - pub l_factor: u32, // the liability factor for the reserve - pub c_factor: u32, // the collateral factor for the reserve - pub max_util: u32, // the maximum utilization rate for the reserve - pub last_time: u64, // the last block the data was updated - pub scalar: i128, // scalar used for positions, b/d token supply, and credit - pub d_rate: i128, // the conversion rate from dToken to underlying (9 decimals) - pub b_rate: i128, // the conversion rate from bToken to underlying (9 decimals) - pub ir_mod: i128, // the interest rate curve modifier (9 decimals) - pub b_supply: i128, // the total supply of b tokens - pub d_supply: i128, // the total supply of d tokens - pub backstop_credit: i128, // the total amount of underlying tokens owed to the backstop - pub collateral_cap: i128, // the total amount of underlying tokens that can be used as collateral - pub enabled: bool, // is the reserve enabled + pub config: ReserveConfig, // the reserve configuration + pub data: ReserveData, // the reserve data + pub scalar: i128, } impl Reserve { @@ -48,72 +37,52 @@ impl Reserve { let reserve_data = storage::get_res_data(e, asset); let mut reserve = Reserve { asset: asset.clone(), - index: reserve_config.index, - l_factor: reserve_config.l_factor, - c_factor: reserve_config.c_factor, - max_util: reserve_config.max_util, - last_time: reserve_data.last_time, scalar: 10i128.pow(reserve_config.decimals), - d_rate: reserve_data.d_rate, - b_rate: reserve_data.b_rate, - ir_mod: reserve_data.ir_mod, - b_supply: reserve_data.b_supply, - d_supply: reserve_data.d_supply, - backstop_credit: reserve_data.backstop_credit, - collateral_cap: reserve_config.collateral_cap, - enabled: reserve_config.enabled, + config: reserve_config, + data: reserve_data, }; // short circuit if the reserve has already been updated this ledger - if e.ledger().timestamp() == reserve.last_time { + if e.ledger().timestamp() == reserve.data.last_time { return reserve; } - if reserve.b_supply == 0 { - reserve.last_time = e.ledger().timestamp(); + if reserve.data.b_supply == 0 { + reserve.data.last_time = e.ledger().timestamp(); return reserve; } let cur_util = reserve.utilization(); if cur_util == 0 { // if there are no assets borrowed, we don't need to update the reserve - reserve.last_time = e.ledger().timestamp(); + reserve.data.last_time = e.ledger().timestamp(); return reserve; } let (loan_accrual, new_ir_mod) = calc_accrual( e, - &reserve_config, + &reserve.config, cur_util, - reserve.ir_mod, - reserve.last_time, + reserve.data.ir_mod, + reserve.data.last_time, ); - reserve.ir_mod = new_ir_mod; + reserve.data.ir_mod = new_ir_mod; let pre_update_liabilities = reserve.total_liabilities(); - reserve.d_rate = loan_accrual - .fixed_mul_ceil(reserve.d_rate, SCALAR_9) + reserve.data.d_rate = loan_accrual + .fixed_mul_ceil(reserve.data.d_rate, SCALAR_9) .unwrap_optimized(); let accrued_interest = reserve.total_liabilities() - pre_update_liabilities; reserve.gulp(pool_config.bstop_rate, accrued_interest); - reserve.last_time = e.ledger().timestamp(); + reserve.data.last_time = e.ledger().timestamp(); reserve } /// Store the updated reserve to the ledger. pub fn store(&self, e: &Env) { - let reserve_data = ReserveData { - d_rate: self.d_rate, - b_rate: self.b_rate, - ir_mod: self.ir_mod, - b_supply: self.b_supply, - d_supply: self.d_supply, - backstop_credit: self.backstop_credit, - last_time: self.last_time, - }; - storage::set_res_data(e, &self.asset, &reserve_data); + storage::set_res_data(e, &self.asset, &self.data); } /// Accrue tokens to the reserve supply. This issues any `backstop_credit` required and updates the reserve's bRate to account for the additional tokens. @@ -132,10 +101,10 @@ impl Reserve { new_backstop_credit = accrued .fixed_mul_floor(i128(bstop_rate), SCALAR_7) .unwrap_optimized(); - self.backstop_credit += new_backstop_credit; + self.data.backstop_credit += new_backstop_credit; } - self.b_rate = (pre_update_supply + accrued - new_backstop_credit) - .fixed_div_floor(self.b_supply, SCALAR_9) + self.data.b_rate = (pre_update_supply + accrued - new_backstop_credit) + .fixed_div_floor(self.data.b_supply, SCALAR_9) .unwrap_optimized(); } } @@ -149,7 +118,7 @@ impl Reserve { /// Require that the utilization rate is below the maximum allowed, or panic. pub fn require_utilization_below_max(&self, e: &Env) { - if self.utilization() > i128(self.max_util) { + if self.utilization() > i128(self.config.max_util) { panic_with_error!(e, PoolError::InvalidUtilRate) } } @@ -160,7 +129,7 @@ impl Reserve { /// * `action_type` - The type of action being performed pub fn require_action_allowed(&self, e: &Env, action_type: u32) { // disable borrowing or auction cancellation for any non-active pool and disable supplying for any frozen pool - if !self.enabled { + if !self.config.enabled { if action_type == RequestType::Supply as u32 || action_type == RequestType::SupplyCollateral as u32 || action_type == RequestType::Borrow as u32 @@ -172,12 +141,12 @@ impl Reserve { /// Fetch the total liabilities for the reserve in underlying tokens pub fn total_liabilities(&self) -> i128 { - self.to_asset_from_d_token(self.d_supply) + self.to_asset_from_d_token(self.data.d_supply) } /// Fetch the total supply for the reserve in underlying tokens pub fn total_supply(&self) -> i128 { - self.to_asset_from_b_token(self.b_supply) + self.to_asset_from_b_token(self.data.b_supply) } /********** Conversion Functions **********/ @@ -188,7 +157,7 @@ impl Reserve { /// * `d_tokens` - The amount of tokens to convert pub fn to_asset_from_d_token(&self, d_tokens: i128) -> i128 { d_tokens - .fixed_mul_ceil(self.d_rate, SCALAR_9) + .fixed_mul_ceil(self.data.d_rate, SCALAR_9) .unwrap_optimized() } @@ -198,7 +167,7 @@ impl Reserve { /// * `b_tokens` - The amount of tokens to convert pub fn to_asset_from_b_token(&self, b_tokens: i128) -> i128 { b_tokens - .fixed_mul_floor(self.b_rate, SCALAR_9) + .fixed_mul_floor(self.data.b_rate, SCALAR_9) .unwrap_optimized() } @@ -210,7 +179,7 @@ impl Reserve { pub fn to_effective_asset_from_d_token(&self, d_tokens: i128) -> i128 { let assets = self.to_asset_from_d_token(d_tokens); assets - .fixed_div_ceil(i128(self.l_factor), SCALAR_7) + .fixed_div_ceil(i128(self.config.l_factor), SCALAR_7) .unwrap_optimized() } @@ -222,7 +191,7 @@ impl Reserve { pub fn to_effective_asset_from_b_token(&self, b_tokens: i128) -> i128 { let assets = self.to_asset_from_b_token(b_tokens); assets - .fixed_mul_floor(i128(self.c_factor), SCALAR_7) + .fixed_mul_floor(i128(self.config.c_factor), SCALAR_7) .unwrap_optimized() } @@ -232,7 +201,7 @@ impl Reserve { /// * `amount` - The amount of tokens to convert pub fn to_d_token_up(&self, amount: i128) -> i128 { amount - .fixed_div_ceil(self.d_rate, SCALAR_9) + .fixed_div_ceil(self.data.d_rate, SCALAR_9) .unwrap_optimized() } @@ -242,7 +211,7 @@ impl Reserve { /// * `amount` - The amount of tokens to convert pub fn to_d_token_down(&self, amount: i128) -> i128 { amount - .fixed_div_floor(self.d_rate, SCALAR_9) + .fixed_div_floor(self.data.d_rate, SCALAR_9) .unwrap_optimized() } @@ -252,7 +221,7 @@ impl Reserve { /// * `amount` - The amount of tokens to convert pub fn to_b_token_up(&self, amount: i128) -> i128 { amount - .fixed_div_ceil(self.b_rate, SCALAR_9) + .fixed_div_ceil(self.data.b_rate, SCALAR_9) .unwrap_optimized() } @@ -262,7 +231,7 @@ impl Reserve { /// * `amount` - The amount of tokens to convert pub fn to_b_token_down(&self, amount: i128) -> i128 { amount - .fixed_div_floor(self.b_rate, SCALAR_9) + .fixed_div_floor(self.data.b_rate, SCALAR_9) .unwrap_optimized() } } @@ -311,13 +280,13 @@ mod tests { let reserve = Reserve::load(&e, &pool_config, &underlying); // (accrual: 1_002_957_369, util: .7864353) - assert_eq!(reserve.d_rate, 1_349_657_800); - assert_eq!(reserve.b_rate, 1_125_547_124); - assert_eq!(reserve.ir_mod, 1_044_981_563); - assert_eq!(reserve.d_supply, 65_0000000); - assert_eq!(reserve.b_supply, 99_0000000); - assert_eq!(reserve.backstop_credit, 0_0517358); - assert_eq!(reserve.last_time, 617280); + assert_eq!(reserve.data.d_rate, 1_349_657_800); + assert_eq!(reserve.data.b_rate, 1_125_547_124); + assert_eq!(reserve.data.ir_mod, 1_044_981_563); + assert_eq!(reserve.data.d_supply, 65_0000000); + assert_eq!(reserve.data.b_supply, 99_0000000); + assert_eq!(reserve.data.backstop_credit, 0_0517358); + assert_eq!(reserve.data.last_time, 617280); }); } @@ -360,13 +329,13 @@ mod tests { let reserve = Reserve::load(&e, &pool_config, &underlying); // (accrual: 1_002_957_369, util: .7864352)q - assert_eq!(reserve.d_rate, 0); - assert_eq!(reserve.b_rate, 0); - assert_eq!(reserve.ir_mod, 1_000_000_000); - assert_eq!(reserve.d_supply, 0); - assert_eq!(reserve.b_supply, 0); - assert_eq!(reserve.backstop_credit, 0); - assert_eq!(reserve.last_time, 617280); + assert_eq!(reserve.data.d_rate, 0); + assert_eq!(reserve.data.b_rate, 0); + assert_eq!(reserve.data.ir_mod, 1_000_000_000); + assert_eq!(reserve.data.d_supply, 0); + assert_eq!(reserve.data.b_supply, 0); + assert_eq!(reserve.data.backstop_credit, 0); + assert_eq!(reserve.data.last_time, 617280); }); } @@ -406,13 +375,13 @@ mod tests { storage::set_pool_config(&e, &pool_config); let reserve = Reserve::load(&e, &pool_config, &underlying); - assert_eq!(reserve.d_rate, 0); - assert_eq!(reserve.b_rate, reserve_data.b_rate); - assert_eq!(reserve.ir_mod, reserve_data.ir_mod); - assert_eq!(reserve.d_supply, 0); - assert_eq!(reserve.b_supply, reserve_data.b_supply); - assert_eq!(reserve.backstop_credit, 0); - assert_eq!(reserve.last_time, 617280); + assert_eq!(reserve.data.d_rate, 0); + assert_eq!(reserve.data.b_rate, reserve_data.b_rate); + assert_eq!(reserve.data.ir_mod, reserve_data.ir_mod); + assert_eq!(reserve.data.d_supply, 0); + assert_eq!(reserve.data.b_supply, reserve_data.b_supply); + assert_eq!(reserve.data.backstop_credit, 0); + assert_eq!(reserve.data.last_time, 617280); }); } @@ -455,13 +424,13 @@ mod tests { let reserve = Reserve::load(&e, &pool_config, &underlying); // (accrual: 1_002_957_369, util: .7864353) - assert_eq!(reserve.d_rate, 1_349_657_800); - assert_eq!(reserve.b_rate, 1_126_069_708); - assert_eq!(reserve.ir_mod, 1_044_981_563); - assert_eq!(reserve.d_supply, 65_0000000); - assert_eq!(reserve.b_supply, 99_0000000); - assert_eq!(reserve.backstop_credit, 0); - assert_eq!(reserve.last_time, 617280); + assert_eq!(reserve.data.d_rate, 1_349_657_800); + assert_eq!(reserve.data.b_rate, 1_126_069_708); + assert_eq!(reserve.data.ir_mod, 1_044_981_563); + assert_eq!(reserve.data.d_supply, 65_0000000); + assert_eq!(reserve.data.b_supply, 99_0000000); + assert_eq!(reserve.data.backstop_credit, 0); + assert_eq!(reserve.data.last_time, 617280); }); } @@ -522,10 +491,10 @@ mod tests { let e = Env::default(); let mut reserve = testutils::default_reserve(&e); - reserve.d_rate = 1_345_678_123; - reserve.b_rate = 1_123_456_789; - reserve.b_supply = 99_0000000; - reserve.d_supply = 65_0000000; + reserve.data.d_rate = 1_345_678_123; + reserve.data.b_rate = 1_123_456_789; + reserve.data.b_supply = 99_0000000; + reserve.data.d_supply = 65_0000000; let result = reserve.utilization(); @@ -537,8 +506,8 @@ mod tests { let e = Env::default(); let mut reserve = testutils::default_reserve(&e); - reserve.b_supply = 99_0000000; - reserve.d_supply = 65_0000000; + reserve.data.b_supply = 99_0000000; + reserve.data.d_supply = 65_0000000; reserve.require_utilization_below_max(&e); // no panic @@ -551,8 +520,8 @@ mod tests { let e = Env::default(); let mut reserve = testutils::default_reserve(&e); - reserve.b_supply = 100_0000000; - reserve.d_supply = 95_0000100; + reserve.data.b_supply = 100_0000000; + reserve.data.d_supply = 95_0000100; reserve.require_utilization_below_max(&e); } @@ -564,9 +533,9 @@ mod tests { let e = Env::default(); let mut reserve = testutils::default_reserve(&e); - reserve.d_rate = 1_321_834_961; - reserve.b_supply = 99_0000000; - reserve.d_supply = 65_0000000; + reserve.data.d_rate = 1_321_834_961; + reserve.data.b_supply = 99_0000000; + reserve.data.d_supply = 65_0000000; let result = reserve.to_asset_from_d_token(1_1234567); @@ -578,9 +547,9 @@ mod tests { let e = Env::default(); let mut reserve = testutils::default_reserve(&e); - reserve.b_rate = 1_321_834_961; - reserve.b_supply = 99_0000000; - reserve.d_supply = 65_0000000; + reserve.data.b_rate = 1_321_834_961; + reserve.data.b_supply = 99_0000000; + reserve.data.d_supply = 65_0000000; let result = reserve.to_asset_from_b_token(1_1234567); @@ -592,10 +561,10 @@ mod tests { let e = Env::default(); let mut reserve = testutils::default_reserve(&e); - reserve.d_rate = 1_321_834_961; - reserve.b_supply = 99_0000000; - reserve.d_supply = 65_0000000; - reserve.l_factor = 1_1000000; + reserve.data.d_rate = 1_321_834_961; + reserve.data.b_supply = 99_0000000; + reserve.data.d_supply = 65_0000000; + reserve.config.l_factor = 1_1000000; let result = reserve.to_effective_asset_from_d_token(1_1234567); @@ -607,10 +576,10 @@ mod tests { let e = Env::default(); let mut reserve = testutils::default_reserve(&e); - reserve.b_rate = 1_321_834_961; - reserve.b_supply = 99_0000000; - reserve.d_supply = 65_0000000; - reserve.c_factor = 0_8500000; + reserve.data.b_rate = 1_321_834_961; + reserve.data.b_supply = 99_0000000; + reserve.data.d_supply = 65_0000000; + reserve.config.c_factor = 0_8500000; let result = reserve.to_effective_asset_from_b_token(1_1234567); @@ -622,9 +591,9 @@ mod tests { let e = Env::default(); let mut reserve = testutils::default_reserve(&e); - reserve.d_rate = 1_823_912_692; - reserve.b_supply = 99_0000000; - reserve.d_supply = 65_0000000; + reserve.data.d_rate = 1_823_912_692; + reserve.data.b_supply = 99_0000000; + reserve.data.d_supply = 65_0000000; let result = reserve.total_liabilities(); @@ -636,9 +605,9 @@ mod tests { let e = Env::default(); let mut reserve = testutils::default_reserve(&e); - reserve.b_rate = 1_823_912_692; - reserve.b_supply = 99_0000000; - reserve.d_supply = 65_0000000; + reserve.data.b_rate = 1_823_912_692; + reserve.data.b_supply = 99_0000000; + reserve.data.d_supply = 65_0000000; let result = reserve.total_supply(); @@ -650,9 +619,9 @@ mod tests { let e = Env::default(); let mut reserve = testutils::default_reserve(&e); - reserve.d_rate = 1_321_834_961; - reserve.b_supply = 99_0000000; - reserve.d_supply = 65_0000000; + reserve.data.d_rate = 1_321_834_961; + reserve.data.b_supply = 99_0000000; + reserve.data.d_supply = 65_0000000; let result = reserve.to_d_token_up(1_4850243); @@ -664,9 +633,9 @@ mod tests { let e = Env::default(); let mut reserve = testutils::default_reserve(&e); - reserve.d_rate = 1_321_834_961; - reserve.b_supply = 99_0000000; - reserve.d_supply = 65_0000000; + reserve.data.d_rate = 1_321_834_961; + reserve.data.b_supply = 99_0000000; + reserve.data.d_supply = 65_0000000; let result = reserve.to_d_token_down(1_4850243); @@ -678,9 +647,9 @@ mod tests { let e = Env::default(); let mut reserve = testutils::default_reserve(&e); - reserve.b_rate = 1_321_834_961; - reserve.b_supply = 99_0000000; - reserve.d_supply = 65_0000000; + reserve.data.b_rate = 1_321_834_961; + reserve.data.b_supply = 99_0000000; + reserve.data.d_supply = 65_0000000; let result = reserve.to_b_token_up(1_4850243); @@ -692,9 +661,9 @@ mod tests { let e = Env::default(); let mut reserve = testutils::default_reserve(&e); - reserve.b_rate = 1_321_834_961; - reserve.b_supply = 99_0000000; - reserve.d_supply = 65_0000000; + reserve.data.b_rate = 1_321_834_961; + reserve.data.b_supply = 99_0000000; + reserve.data.d_supply = 65_0000000; let result = reserve.to_b_token_down(1_4850243); @@ -707,7 +676,7 @@ mod tests { let e = Env::default(); let mut reserve = testutils::default_reserve(&e); - reserve.enabled = false; + reserve.config.enabled = false; reserve.require_action_allowed(&e, RequestType::SupplyCollateral as u32); } @@ -718,7 +687,7 @@ mod tests { let e = Env::default(); let mut reserve = testutils::default_reserve(&e); - reserve.enabled = false; + reserve.config.enabled = false; reserve.require_action_allowed(&e, RequestType::Borrow as u32); } @@ -728,7 +697,7 @@ mod tests { let e = Env::default(); let mut reserve = testutils::default_reserve(&e); - reserve.enabled = false; + reserve.config.enabled = false; reserve.require_action_allowed(&e, RequestType::Withdraw as u32); reserve.require_action_allowed(&e, RequestType::WithdrawCollateral as u32); @@ -752,12 +721,12 @@ mod tests { }); let mut reserve = testutils::default_reserve(&e); - reserve.backstop_credit = 0_1234567; + reserve.data.backstop_credit = 0_1234567; reserve.gulp(0_2000000, 100_0000000); - assert_eq!(reserve.backstop_credit, 20_0000000 + 0_1234567); - assert_eq!(reserve.b_rate, 1_800000000); - assert_eq!(reserve.last_time, 0); + assert_eq!(reserve.data.backstop_credit, 20_0000000 + 0_1234567); + assert_eq!(reserve.data.b_rate, 1_800000000); + assert_eq!(reserve.data.last_time, 0); } #[test] @@ -777,11 +746,11 @@ mod tests { }); let mut reserve = testutils::default_reserve(&e); - reserve.backstop_credit = 0_1234567; + reserve.data.backstop_credit = 0_1234567; reserve.gulp(0_2000000, -10_0000000); - assert_eq!(reserve.backstop_credit, 0_1234567); - assert_eq!(reserve.b_rate, 1000000000); - assert_eq!(reserve.last_time, 0); + assert_eq!(reserve.data.backstop_credit, 0_1234567); + assert_eq!(reserve.data.b_rate, 1000000000); + assert_eq!(reserve.data.last_time, 0); } } diff --git a/pool/src/pool/user.rs b/pool/src/pool/user.rs index 74ccf88..541b363 100644 --- a/pool/src/pool/user.rs +++ b/pool/src/pool/user.rs @@ -70,12 +70,12 @@ impl User { if amount == 0 { panic_with_error!(e, PoolError::InvalidDTokenMintAmount) } - let balance = self.get_liabilities(reserve.index); + let balance = self.get_liabilities(reserve.config.index); self.update_d_emissions(e, reserve, balance); self.positions .liabilities - .set(reserve.index, balance + amount); - reserve.d_supply += amount; + .set(reserve.config.index, balance + amount); + reserve.data.d_supply += amount; } /// Remove liabilities from the position expressed in debtTokens. Accrues emissions @@ -84,16 +84,18 @@ impl User { if amount == 0 { panic_with_error!(e, PoolError::InvalidDTokenBurnAmount) } - let balance = self.get_liabilities(reserve.index); + let balance = self.get_liabilities(reserve.config.index); self.update_d_emissions(e, reserve, balance); let new_balance = balance - amount; require_nonnegative(e, &new_balance); if new_balance == 0 { - self.positions.liabilities.remove(reserve.index); + self.positions.liabilities.remove(reserve.config.index); } else { - self.positions.liabilities.set(reserve.index, new_balance); + self.positions + .liabilities + .set(reserve.config.index, new_balance); } - reserve.d_supply -= amount; + reserve.data.d_supply -= amount; } /// Default on liabilities from the position expressed in debtTokens. Accrues emissions @@ -106,10 +108,10 @@ impl User { // determine amount of funds in underlying that have defaulted // and deduct them from the b_rate let default_amount = reserve.to_asset_from_d_token(amount); - let b_rate_loss = default_amount.fixed_div_floor(&e, &reserve.b_supply, &SCALAR_9); - reserve.b_rate -= b_rate_loss; - if reserve.b_rate < 0 { - reserve.b_rate = 0; + let b_rate_loss = default_amount.fixed_div_floor(&e, &reserve.data.b_supply, &SCALAR_9); + reserve.data.b_rate -= b_rate_loss; + if reserve.data.b_rate < 0 { + reserve.data.b_rate = 0; } } @@ -124,12 +126,12 @@ impl User { if amount == 0 { panic_with_error!(e, PoolError::InvalidBTokenMintAmount) } - let balance = self.get_collateral(reserve.index); - self.update_b_emissions(e, reserve, self.get_total_supply(reserve.index)); + let balance = self.get_collateral(reserve.config.index); + self.update_b_emissions(e, reserve, self.get_total_supply(reserve.config.index)); self.positions .collateral - .set(reserve.index, balance + amount); - reserve.b_supply += amount; + .set(reserve.config.index, balance + amount); + reserve.data.b_supply += amount; } /// Remove collateral from the position expressed in blendTokens. Accrues emissions @@ -138,16 +140,18 @@ impl User { if amount == 0 { panic_with_error!(e, PoolError::InvalidBTokenBurnAmount) } - let balance = self.get_collateral(reserve.index); - self.update_b_emissions(e, reserve, self.get_total_supply(reserve.index)); + let balance = self.get_collateral(reserve.config.index); + self.update_b_emissions(e, reserve, self.get_total_supply(reserve.config.index)); let new_balance = balance - amount; require_nonnegative(e, &new_balance); if new_balance == 0 { - self.positions.collateral.remove(reserve.index); + self.positions.collateral.remove(reserve.config.index); } else { - self.positions.collateral.set(reserve.index, new_balance); + self.positions + .collateral + .set(reserve.config.index, new_balance); } - reserve.b_supply -= amount; + reserve.data.b_supply -= amount; } /// Get the uncollateralized blendToken position for the reserve at the given index @@ -161,10 +165,12 @@ impl User { if amount == 0 { panic_with_error!(e, PoolError::InvalidBTokenMintAmount) } - let balance = self.get_supply(reserve.index); - self.update_b_emissions(e, reserve, self.get_total_supply(reserve.index)); - self.positions.supply.set(reserve.index, balance + amount); - reserve.b_supply += amount; + let balance = self.get_supply(reserve.config.index); + self.update_b_emissions(e, reserve, self.get_total_supply(reserve.config.index)); + self.positions + .supply + .set(reserve.config.index, balance + amount); + reserve.data.b_supply += amount; } /// Remove supply from the position expressed in blendTokens. Accrues emissions @@ -173,16 +179,16 @@ impl User { if amount == 0 { panic_with_error!(e, PoolError::InvalidBTokenBurnAmount) } - let balance = self.get_supply(reserve.index); - self.update_b_emissions(e, reserve, self.get_total_supply(reserve.index)); + let balance = self.get_supply(reserve.config.index); + self.update_b_emissions(e, reserve, self.get_total_supply(reserve.config.index)); let new_balance = balance - amount; require_nonnegative(e, &new_balance); if new_balance == 0 { - self.positions.supply.remove(reserve.index); + self.positions.supply.remove(reserve.config.index); } else { - self.positions.supply.set(reserve.index, new_balance); + self.positions.supply.set(reserve.config.index, new_balance); } - reserve.b_supply -= amount; + reserve.data.b_supply -= amount; } /// Get the total supply and collateral of blendTokens for the user at the given index @@ -233,8 +239,8 @@ impl User { fn update_d_emissions(&self, e: &Env, reserve: &Reserve, amount: i128) { emissions::update_emissions( e, - reserve.index * 2, - reserve.d_supply, + reserve.config.index * 2, + reserve.data.d_supply, reserve.scalar, &self.address, amount, @@ -244,8 +250,8 @@ impl User { fn update_b_emissions(&self, e: &Env, reserve: &Reserve, amount: i128) { emissions::update_emissions( e, - reserve.index * 2 + 1, - reserve.b_supply, + reserve.config.index * 2 + 1, + reserve.data.b_supply, reserve.scalar, &self.address, amount, @@ -297,11 +303,11 @@ mod tests { let pool = testutils::create_pool(&e); let mut reserve_0 = testutils::default_reserve(&e); - let starting_d_supply_0 = reserve_0.d_supply; + let starting_d_supply_0 = reserve_0.data.d_supply; let mut reserve_1 = testutils::default_reserve(&e); - reserve_1.index = 1; - let starting_d_supply_1 = reserve_1.d_supply; + reserve_1.config.index = 1; + let starting_d_supply_1 = reserve_1.data.d_supply; let mut user = User { address: samwise.clone(), @@ -313,27 +319,27 @@ mod tests { user.add_liabilities(&e, &mut reserve_0, 123); assert_eq!(user.get_liabilities(0), 123); - assert_eq!(reserve_0.d_supply, starting_d_supply_0 + 123); + assert_eq!(reserve_0.data.d_supply, starting_d_supply_0 + 123); assert_eq!(user.has_liabilities(), true); user.add_liabilities(&e, &mut reserve_1, 456); assert_eq!(user.get_liabilities(0), 123); assert_eq!(user.get_liabilities(1), 456); - assert_eq!(reserve_1.d_supply, starting_d_supply_1 + 456); + assert_eq!(reserve_1.data.d_supply, starting_d_supply_1 + 456); user.remove_liabilities(&e, &mut reserve_1, 100); assert_eq!(user.get_liabilities(1), 356); - assert_eq!(reserve_1.d_supply, starting_d_supply_1 + 356); + assert_eq!(reserve_1.data.d_supply, starting_d_supply_1 + 356); user.remove_liabilities(&e, &mut reserve_1, 356); assert_eq!(user.get_liabilities(1), 0); assert_eq!(user.positions.liabilities.len(), 1); - assert_eq!(reserve_1.d_supply, starting_d_supply_1); + assert_eq!(reserve_1.data.d_supply, starting_d_supply_1); user.remove_liabilities(&e, &mut reserve_0, 123); assert_eq!(user.get_liabilities(0), 0); assert_eq!(user.positions.liabilities.len(), 0); - assert_eq!(reserve_0.d_supply, starting_d_supply_0); + assert_eq!(reserve_0.data.d_supply, starting_d_supply_0); assert_eq!(user.has_liabilities(), false); }); } @@ -378,7 +384,7 @@ mod tests { }); let mut reserve_0 = testutils::default_reserve(&e); - let starting_d_supply_0 = reserve_0.d_supply; + let starting_d_supply_0 = reserve_0.data.d_supply; let emis_res_data = ReserveEmissionData { expiration: 20000000, @@ -394,20 +400,20 @@ mod tests { let mut user = User { address: samwise.clone(), positions: Positions { - liabilities: map![&e, (reserve_0.index, 1000)], + liabilities: map![&e, (reserve_0.config.index, 1000)], collateral: map![&e], supply: map![&e], }, }; e.as_contract(&pool, || { - let res_0_d_token_index = reserve_0.index * 2 + 0; + let res_0_d_token_index = reserve_0.config.index * 2 + 0; storage::set_res_emis_data(&e, &res_0_d_token_index, &emis_res_data); storage::set_user_emissions(&e, &samwise, &res_0_d_token_index, &emis_user_data); user.add_liabilities(&e, &mut reserve_0, 123); assert_eq!(user.get_liabilities(0), 1123); - assert_eq!(reserve_0.d_supply, starting_d_supply_0 + 123); + assert_eq!(reserve_0.data.d_supply, starting_d_supply_0 + 123); let new_emis_res_data = storage::get_res_emis_data(&e, &res_0_d_token_index).unwrap(); let new_index = 10000000000 @@ -469,7 +475,7 @@ mod tests { }); let mut reserve_0 = testutils::default_reserve(&e); - let starting_d_supply_0 = reserve_0.d_supply; + let starting_d_supply_0 = reserve_0.data.d_supply; let emis_res_data = ReserveEmissionData { expiration: 20000000, @@ -484,19 +490,19 @@ mod tests { let mut user = User { address: samwise.clone(), positions: Positions { - liabilities: map![&e, (reserve_0.index, 1000)], + liabilities: map![&e, (reserve_0.config.index, 1000)], collateral: map![&e], supply: map![&e], }, }; e.as_contract(&pool, || { - let res_0_d_token_index = reserve_0.index * 2 + 0; + let res_0_d_token_index = reserve_0.config.index * 2 + 0; storage::set_res_emis_data(&e, &res_0_d_token_index, &emis_res_data); storage::set_user_emissions(&e, &samwise, &res_0_d_token_index, &emis_user_data); user.remove_liabilities(&e, &mut reserve_0, 123); assert_eq!(user.get_liabilities(0), 877); - assert_eq!(reserve_0.d_supply, starting_d_supply_0 - 123); + assert_eq!(reserve_0.data.d_supply, starting_d_supply_0 - 123); let new_emis_res_data = storage::get_res_emis_data(&e, &res_0_d_token_index).unwrap(); let new_index = 10000000000 @@ -544,10 +550,10 @@ mod tests { let pool = testutils::create_pool(&e); let mut reserve_0 = testutils::default_reserve(&e); - reserve_0.d_rate = 1_500_000_000; - reserve_0.d_supply = 500_0000000; - reserve_0.b_rate = 1_250_000_000; - reserve_0.b_supply = 750_0000000; + reserve_0.data.d_rate = 1_500_000_000; + reserve_0.data.d_supply = 500_0000000; + reserve_0.data.b_rate = 1_250_000_000; + reserve_0.data.b_supply = 750_0000000; let mut user = User { address: samwise.clone(), @@ -559,19 +565,19 @@ mod tests { user.add_liabilities(&e, &mut reserve_0, 20_0000000); assert_eq!(user.get_liabilities(0), 20_0000000); - let d_supply = reserve_0.d_supply; + let d_supply = reserve_0.data.d_supply; let total_supply = reserve_0.total_supply(); let underlying_default_amount = reserve_0.to_asset_from_d_token(20_0000000); user.default_liabilities(&e, &mut reserve_0, 20_0000000); assert_eq!(user.get_liabilities(0), 0); - assert_eq!(reserve_0.d_supply, d_supply - 20_0000000); + assert_eq!(reserve_0.data.d_supply, d_supply - 20_0000000); assert_eq!( reserve_0.total_supply(), total_supply - underlying_default_amount ); - assert_eq!(reserve_0.b_rate, 1_210_000_000); - assert_eq!(reserve_0.b_supply, 750_0000000); + assert_eq!(reserve_0.data.b_rate, 1_210_000_000); + assert_eq!(reserve_0.data.b_supply, 750_0000000); }); } @@ -583,10 +589,10 @@ mod tests { let pool = testutils::create_pool(&e); let mut reserve_0 = testutils::default_reserve(&e); - reserve_0.d_rate = 1_500_000_000; - reserve_0.d_supply = 500_0000000; - reserve_0.b_rate = 0_100_000_000; - reserve_0.b_supply = 750_0000000; + reserve_0.data.d_rate = 1_500_000_000; + reserve_0.data.d_supply = 500_0000000; + reserve_0.data.b_rate = 0_100_000_000; + reserve_0.data.b_supply = 750_0000000; let mut user = User { address: samwise.clone(), @@ -598,14 +604,14 @@ mod tests { user.add_liabilities(&e, &mut reserve_0, 100_0000000); assert_eq!(user.get_liabilities(0), 100_0000000); - let d_supply = reserve_0.d_supply; + let d_supply = reserve_0.data.d_supply; user.default_liabilities(&e, &mut reserve_0, 100_0000000); assert_eq!(user.get_liabilities(0), 0); - assert_eq!(reserve_0.d_supply, d_supply - 100_0000000); + assert_eq!(reserve_0.data.d_supply, d_supply - 100_0000000); assert_eq!(reserve_0.total_supply(), 0); - assert_eq!(reserve_0.b_rate, 0); - assert_eq!(reserve_0.b_supply, 750_0000000); + assert_eq!(reserve_0.data.b_rate, 0); + assert_eq!(reserve_0.data.b_supply, 750_0000000); }); } @@ -617,11 +623,11 @@ mod tests { let pool = testutils::create_pool(&e); let mut reserve_0 = testutils::default_reserve(&e); - let starting_b_supply_0 = reserve_0.b_supply; + let starting_b_supply_0 = reserve_0.data.b_supply; let mut reserve_1 = testutils::default_reserve(&e); - reserve_1.index = 1; - let starting_b_supply_1 = reserve_1.b_supply; + reserve_1.config.index = 1; + let starting_b_supply_1 = reserve_1.data.b_supply; let mut user = User { address: samwise.clone(), @@ -632,21 +638,21 @@ mod tests { user.add_collateral(&e, &mut reserve_0, 123); assert_eq!(user.get_collateral(0), 123); - assert_eq!(reserve_0.b_supply, starting_b_supply_0 + 123); + assert_eq!(reserve_0.data.b_supply, starting_b_supply_0 + 123); user.add_collateral(&e, &mut reserve_1, 456); assert_eq!(user.get_collateral(0), 123); assert_eq!(user.get_collateral(1), 456); - assert_eq!(reserve_1.b_supply, starting_b_supply_1 + 456); + assert_eq!(reserve_1.data.b_supply, starting_b_supply_1 + 456); user.remove_collateral(&e, &mut reserve_1, 100); assert_eq!(user.get_collateral(1), 356); - assert_eq!(reserve_1.b_supply, starting_b_supply_1 + 356); + assert_eq!(reserve_1.data.b_supply, starting_b_supply_1 + 356); user.remove_collateral(&e, &mut reserve_1, 356); assert_eq!(user.get_collateral(1), 0); assert_eq!(user.positions.collateral.len(), 1); - assert_eq!(reserve_1.b_supply, starting_b_supply_1); + assert_eq!(reserve_1.data.b_supply, starting_b_supply_1); }); } @@ -690,7 +696,7 @@ mod tests { }); let mut reserve_0 = testutils::default_reserve(&e); - let starting_b_token_supply = reserve_0.b_supply; + let starting_b_token_supply = reserve_0.data.b_supply; let emis_res_data = ReserveEmissionData { expiration: 20000000, @@ -707,18 +713,18 @@ mod tests { address: samwise.clone(), positions: Positions { liabilities: map![&e], - collateral: map![&e, (reserve_0.index, 700)], - supply: map![&e, (reserve_0.index, 300)], + collateral: map![&e, (reserve_0.config.index, 700)], + supply: map![&e, (reserve_0.config.index, 300)], }, }; e.as_contract(&pool, || { - let res_0_d_token_index = reserve_0.index * 2 + 1; + let res_0_d_token_index = reserve_0.config.index * 2 + 1; storage::set_res_emis_data(&e, &res_0_d_token_index, &emis_res_data); storage::set_user_emissions(&e, &samwise, &res_0_d_token_index, &emis_user_data); user.add_collateral(&e, &mut reserve_0, 123); assert_eq!(user.get_collateral(0), 823); - assert_eq!(reserve_0.b_supply, starting_b_token_supply + 123); + assert_eq!(reserve_0.data.b_supply, starting_b_token_supply + 123); let new_emis_res_data = storage::get_res_emis_data(&e, &res_0_d_token_index).unwrap(); let new_index = 10000000000 @@ -780,7 +786,7 @@ mod tests { }); let mut reserve_0 = testutils::default_reserve(&e); - let starting_b_token_supply = reserve_0.b_supply; + let starting_b_token_supply = reserve_0.data.b_supply; let emis_res_data = ReserveEmissionData { expiration: 20000000, @@ -797,18 +803,18 @@ mod tests { address: samwise.clone(), positions: Positions { liabilities: map![&e], - collateral: map![&e, (reserve_0.index, 700)], - supply: map![&e, (reserve_0.index, 300)], + collateral: map![&e, (reserve_0.config.index, 700)], + supply: map![&e, (reserve_0.config.index, 300)], }, }; e.as_contract(&pool, || { - let res_0_d_token_index = reserve_0.index * 2 + 1; + let res_0_d_token_index = reserve_0.config.index * 2 + 1; storage::set_res_emis_data(&e, &res_0_d_token_index, &emis_res_data); storage::set_user_emissions(&e, &samwise, &res_0_d_token_index, &emis_user_data); user.remove_collateral(&e, &mut reserve_0, 123); assert_eq!(user.get_collateral(0), 577); - assert_eq!(reserve_0.b_supply, starting_b_token_supply - 123); + assert_eq!(reserve_0.data.b_supply, starting_b_token_supply - 123); let new_emis_res_data = storage::get_res_emis_data(&e, &res_0_d_token_index).unwrap(); let new_index = 10000000000 @@ -857,11 +863,11 @@ mod tests { let pool = testutils::create_pool(&e); let mut reserve_0 = testutils::default_reserve(&e); - let starting_b_supply_0 = reserve_0.b_supply; + let starting_b_supply_0 = reserve_0.data.b_supply; let mut reserve_1 = testutils::default_reserve(&e); - reserve_1.index = 1; - let starting_b_supply_1 = reserve_1.b_supply; + reserve_1.config.index = 1; + let starting_b_supply_1 = reserve_1.data.b_supply; let mut user = User { address: samwise.clone(), @@ -872,21 +878,21 @@ mod tests { user.add_supply(&e, &mut reserve_0, 123); assert_eq!(user.get_supply(0), 123); - assert_eq!(reserve_0.b_supply, starting_b_supply_0 + 123); + assert_eq!(reserve_0.data.b_supply, starting_b_supply_0 + 123); user.add_supply(&e, &mut reserve_1, 456); assert_eq!(user.get_supply(0), 123); assert_eq!(user.get_supply(1), 456); - assert_eq!(reserve_1.b_supply, starting_b_supply_1 + 456); + assert_eq!(reserve_1.data.b_supply, starting_b_supply_1 + 456); user.remove_supply(&e, &mut reserve_1, 100); assert_eq!(user.get_supply(1), 356); - assert_eq!(reserve_1.b_supply, starting_b_supply_1 + 356); + assert_eq!(reserve_1.data.b_supply, starting_b_supply_1 + 356); user.remove_supply(&e, &mut reserve_1, 356); assert_eq!(user.get_supply(2), 0); assert_eq!(user.positions.supply.len(), 1); - assert_eq!(reserve_1.b_supply, starting_b_supply_1); + assert_eq!(reserve_1.data.b_supply, starting_b_supply_1); }); } @@ -930,7 +936,7 @@ mod tests { }); let mut reserve_0 = testutils::default_reserve(&e); - let starting_b_token_supply = reserve_0.b_supply; + let starting_b_token_supply = reserve_0.data.b_supply; let emis_res_data = ReserveEmissionData { expiration: 20000000, @@ -947,18 +953,18 @@ mod tests { address: samwise.clone(), positions: Positions { liabilities: map![&e], - collateral: map![&e, (reserve_0.index, 700)], - supply: map![&e, (reserve_0.index, 300)], + collateral: map![&e, (reserve_0.config.index, 700)], + supply: map![&e, (reserve_0.config.index, 300)], }, }; e.as_contract(&pool, || { - let res_0_d_token_index = reserve_0.index * 2 + 1; + let res_0_d_token_index = reserve_0.config.index * 2 + 1; storage::set_res_emis_data(&e, &res_0_d_token_index, &emis_res_data); storage::set_user_emissions(&e, &samwise, &res_0_d_token_index, &emis_user_data); user.add_supply(&e, &mut reserve_0, 123); assert_eq!(user.get_supply(0), 423); - assert_eq!(reserve_0.b_supply, starting_b_token_supply + 123); + assert_eq!(reserve_0.data.b_supply, starting_b_token_supply + 123); let new_emis_res_data = storage::get_res_emis_data(&e, &res_0_d_token_index).unwrap(); let new_index = 10000000000 @@ -1020,7 +1026,7 @@ mod tests { }); let mut reserve_0 = testutils::default_reserve(&e); - let starting_b_token_supply = reserve_0.b_supply; + let starting_b_token_supply = reserve_0.data.b_supply; let emis_res_data = ReserveEmissionData { expiration: 20000000, @@ -1037,18 +1043,18 @@ mod tests { address: samwise.clone(), positions: Positions { liabilities: map![&e], - collateral: map![&e, (reserve_0.index, 700)], - supply: map![&e, (reserve_0.index, 300)], + collateral: map![&e, (reserve_0.config.index, 700)], + supply: map![&e, (reserve_0.config.index, 300)], }, }; e.as_contract(&pool, || { - let res_0_d_token_index = reserve_0.index * 2 + 1; + let res_0_d_token_index = reserve_0.config.index * 2 + 1; storage::set_res_emis_data(&e, &res_0_d_token_index, &emis_res_data); storage::set_user_emissions(&e, &samwise, &res_0_d_token_index, &emis_user_data); user.remove_supply(&e, &mut reserve_0, 123); assert_eq!(user.get_supply(0), 177); - assert_eq!(reserve_0.b_supply, starting_b_token_supply - 123); + assert_eq!(reserve_0.data.b_supply, starting_b_token_supply - 123); let new_emis_res_data = storage::get_res_emis_data(&e, &res_0_d_token_index).unwrap(); let new_index = 10000000000 @@ -1099,7 +1105,7 @@ mod tests { let mut reserve_0 = testutils::default_reserve(&e); let mut reserve_1 = testutils::default_reserve(&e); - reserve_1.index = 1; + reserve_1.config.index = 1; let mut user = User { address: samwise.clone(), diff --git a/pool/src/testutils.rs b/pool/src/testutils.rs index 316b618..ba332bf 100644 --- a/pool/src/testutils.rs +++ b/pool/src/testutils.rs @@ -203,20 +203,31 @@ pub fn create_flashloan_receiver<'a>( pub(crate) fn default_reserve(e: &Env) -> Reserve { Reserve { asset: Address::generate(e), - index: 0, - l_factor: 0_7500000, - c_factor: 0_7500000, - max_util: 0_9500000, - last_time: 0, - scalar: 1_0000000, - d_rate: 1_000_000_000, - b_rate: 1_000_000_000, - ir_mod: 1_000_000_000, - b_supply: 100_0000000, - d_supply: 75_0000000, - backstop_credit: 0, - collateral_cap: 1000000000000000000, - enabled: true, + config: ReserveConfig { + decimals: 7, + c_factor: 0_7500000, + l_factor: 0_7500000, + util: 0_7500000, + max_util: 0_9500000, + r_base: 0_0100000, + r_one: 0_0500000, + r_two: 0_5000000, + r_three: 1_5000000, + reactivity: 0_0000020, // 2e-6 + index: 0, + collateral_cap: 1000000000000000000, + enabled: true, + }, + data: ReserveData { + b_rate: 1_000_000_000, + d_rate: 1_000_000_000, + ir_mod: 1_000_000_000, + b_supply: 100_0000000, + d_supply: 75_0000000, + last_time: 0, + backstop_credit: 0, + }, + scalar: SCALAR_7, } } diff --git a/test-suites/tests/test_flashloan.rs b/test-suites/tests/test_flashloan.rs index 557a14d..5edf792 100644 --- a/test-suites/tests/test_flashloan.rs +++ b/test-suites/tests/test_flashloan.rs @@ -114,7 +114,7 @@ fn test_flashloan() { let flash_loan_events = vec![&fixture.env, events.get_unchecked(0)]; let flash_loan_d_tokens_minted = flash_loan .amount - .fixed_div_ceil(xlm_res_data.d_rate, SCALAR_9) + .fixed_div_ceil(xlm_res_data.data.d_rate, SCALAR_9) .unwrap(); let flash_loan_event_data: soroban_sdk::Vec = vec![ &fixture.env, @@ -141,7 +141,7 @@ fn test_flashloan() { let supply_event = vec![&fixture.env, events.get_unchecked(1)]; let supply_b_tokens_minted = supply_amount - .fixed_div_floor(stable_res_data.b_rate, SCALAR_9) + .fixed_div_floor(stable_res_data.data.b_rate, SCALAR_9) .unwrap(); let supply_event_data: soroban_sdk::Vec = vec![ &fixture.env, @@ -167,7 +167,7 @@ fn test_flashloan() { let repay_event = vec![&fixture.env, events.get_unchecked(2)]; let repay_d_tokens_burned = repay_amount - .fixed_div_floor(xlm_res_data.d_rate, SCALAR_9) + .fixed_div_floor(xlm_res_data.data.d_rate, SCALAR_9) .unwrap(); let repay_event_data: soroban_sdk::Vec = vec![ &fixture.env,