From a3597ff6f201d311a97f65f4f6031a1592bdc1b8 Mon Sep 17 00:00:00 2001 From: markuspluna <59978114+markuspluna@users.noreply.github.com> Date: Tue, 19 Dec 2023 17:42:42 -0600 Subject: [PATCH] Pool: Simplified status flow --- pool-factory/src/test.rs | 2 +- pool/src/contract.rs | 69 ++----- pool/src/pool/config.rs | 268 ++++++++++---------------- pool/src/pool/mod.rs | 5 +- pool/src/pool/status.rs | 66 ++++++- pool/src/storage.rs | 16 +- test-suites/src/pool.rs | 2 +- test-suites/src/setup.rs | 23 +-- test-suites/src/test_fixture.rs | 23 +-- test-suites/tests/test_liquidation.rs | 41 ++-- test-suites/tests/test_pool.rs | 23 ++- 11 files changed, 239 insertions(+), 299 deletions(-) diff --git a/pool-factory/src/test.rs b/pool-factory/src/test.rs index 50bed872..ced86f29 100644 --- a/pool-factory/src/test.rs +++ b/pool-factory/src/test.rs @@ -92,7 +92,7 @@ fn test_pool_factory() { pool::PoolConfig { oracle: oracle, bstop_rate: backstop_rate, - status: 3 + status: 6 } ); assert_eq!( diff --git a/pool/src/contract.rs b/pool/src/contract.rs index cb301df8..ba30d477 100644 --- a/pool/src/contract.rs +++ b/pool/src/contract.rs @@ -57,37 +57,26 @@ pub trait Pool { /// If the caller is not the admin fn update_pool(e: Env, backstop_take_rate: u64); - /// (Admin only) Initializes the first pool reserves + /// (Admin only) Queues setting data for a reserve in the pool /// /// ### Arguments - /// * `reserves` - A vector of tuples of the form `(asset, config) /// * `asset` - The underlying asset to add as a reserve /// * `config` - The ReserveConfig for the reserve /// /// ### Panics /// If the caller is not the admin - fn init_initial_reserves(e: Env, reserves: Vec<(Address, ReserveConfig)>); + fn queue_set_reserve(e: Env, asset: Address, metadata: ReserveConfig); - /// (Admin only) Queues the initialization of a reserve in the pool - /// - /// ### Arguments - /// * `asset` - The underlying asset to add as a reserve - /// * `config` - The ReserveConfig for the reserve - /// - /// ### Panics - /// If the caller is not the admin - fn queue_init_reserve(e: Env, asset: Address, metadata: ReserveConfig); - - /// (Admin only) Cancels the queued initialization of a reserve in the pool + /// (Admin only) Cancels the queued set of a reserve in the pool /// /// ### Arguments /// * `asset` - The underlying asset to add as a reserve /// /// ### Panics /// If the caller is not the admin or the reserve is not queued for initialization - fn cancel_init_reserve(e: Env, asset: Address); + fn cancel_set_reserve(e: Env, asset: Address); - /// (Admin only) Executes the queued initialization of a reserve in the pool + /// (Admin only) Executes the queued set of a reserve in the pool /// /// ### Arguments /// * `asset` - The underlying asset to add as a reserve @@ -96,17 +85,7 @@ pub trait Pool { /// If the reserve is not queued for initialization /// or is already setup /// or has invalid metadata - fn init_reserve(e: Env, asset: Address) -> u32; - - /// (Admin only) Update a reserve in the pool - /// - /// ### Arguments - /// * `asset` - The underlying asset to add as a reserve - /// * `config` - The ReserveConfig for the reserve - /// - /// ### Panics - /// If the caller is not the admin or the reserve does not exist - fn update_reserve(e: Env, asset: Address, config: ReserveConfig); + fn set_reserve(e: Env, asset: Address) -> u32; /// Fetch the positions for an address /// @@ -292,52 +271,36 @@ impl Pool for PoolContract { .publish((Symbol::new(&e, "update_pool"), admin), backstop_take_rate); } - fn init_initial_reserves(e: Env, reserves: Vec<(Address, ReserveConfig)>) { + fn queue_set_reserve(e: Env, asset: Address, metadata: ReserveConfig) { storage::extend_instance(&e); let admin = storage::get_admin(&e); admin.require_auth(); - pool::execute_initialize_initial_reserves(&e, &reserves); - } - - fn queue_init_reserve(e: Env, asset: Address, metadata: ReserveConfig) { - storage::extend_instance(&e); - let admin = storage::get_admin(&e); - admin.require_auth(); - - pool::execute_queue_reserve_initialization(&e, &asset, &metadata); + pool::execute_queue_set_reserve(&e, &asset, &metadata); e.events().publish( - (Symbol::new(&e, "queue_init_reserve"), admin), + (Symbol::new(&e, "queue_set_reserve"), admin), (asset, metadata), ); } - fn cancel_init_reserve(e: Env, asset: Address) { + fn cancel_set_reserve(e: Env, asset: Address) { storage::extend_instance(&e); let admin = storage::get_admin(&e); admin.require_auth(); - pool::execute_cancel_queued_reserve_initialization(&e, &asset); + pool::execute_cancel_queued_set_reserve(&e, &asset); e.events() - .publish((Symbol::new(&e, "cancel_init_reserve"), admin), asset); - } - - fn init_reserve(e: Env, asset: Address) -> u32 { - let index = pool::execute_initialize_queued_reserve(&e, &asset); - index + .publish((Symbol::new(&e, "cancel_set_reserve"), admin), asset); } - fn update_reserve(e: Env, asset: Address, config: ReserveConfig) { - storage::extend_instance(&e); - let admin = storage::get_admin(&e); - admin.require_auth(); - - pool::execute_update_reserve(&e, &asset, &config); + fn set_reserve(e: Env, asset: Address) -> u32 { + let index = pool::execute_set_queued_reserve(&e, &asset); e.events() - .publish((Symbol::new(&e, "update_reserve"), admin), asset); + .publish((Symbol::new(&e, "set_reserve"),), (asset, index)); + index } fn get_positions(e: Env, address: Address) -> Positions { diff --git a/pool/src/pool/config.rs b/pool/src/pool/config.rs index c9a0e477..9eefd53e 100644 --- a/pool/src/pool/config.rs +++ b/pool/src/pool/config.rs @@ -3,7 +3,7 @@ use crate::{ errors::PoolError, storage::{self, PoolConfig, QueuedReserveInit, ReserveConfig, ReserveData}, }; -use soroban_sdk::{panic_with_error, Address, Env, Symbol, Vec}; +use soroban_sdk::{panic_with_error, Address, Env, Symbol}; use super::pool::Pool; @@ -38,7 +38,7 @@ pub fn execute_initialize( &PoolConfig { oracle: oracle.clone(), bstop_rate: *bstop_rate, - status: 3, + status: 6, }, ); storage::set_blnd_token(e, blnd_id); @@ -56,61 +56,71 @@ pub fn execute_update_pool(e: &Env, backstop_take_rate: u64) { storage::set_pool_config(e, &pool_config); } -/// Execute initial reserve initialization -pub fn execute_initialize_initial_reserves(e: &Env, reserves: &Vec<(Address, ReserveConfig)>) { - // confirm the pool has no reserves - if storage::get_res_list(e).len() > 0 { - panic_with_error!(e, PoolError::AlreadyInitialized); - } - // initialize reserves - for (asset, config) in reserves.iter() { - initialize_reserve(e, &asset, &config); - } -} - /// Execute a queueing a reserve initialization for the pool -pub fn execute_queue_reserve_initialization(e: &Env, asset: &Address, metadata: &ReserveConfig) { - storage::set_queued_reserve_init( +pub fn execute_queue_set_reserve(e: &Env, asset: &Address, metadata: &ReserveConfig) { + require_valid_reserve_metadata(e, metadata); + let mut unlock_time = e.ledger().timestamp(); + // require a timelock if pool status is not setup + if storage::get_pool_config(e).status != 6 { + unlock_time += SECONDS_PER_WEEK; + } + storage::set_queued_reserve_set( &e, &QueuedReserveInit { new_config: metadata.clone(), - unlock_time: e.ledger().timestamp() + SECONDS_PER_WEEK, + unlock_time, }, &asset, ); } /// Execute cancelling a queueing a reserve initialization for the pool -pub fn execute_cancel_queued_reserve_initialization(e: &Env, asset: &Address) { - storage::del_queued_reserve_init(&e, &asset); +pub fn execute_cancel_queued_set_reserve(e: &Env, asset: &Address) { + storage::del_queued_reserve_set(&e, &asset); } /// Execute a queued reserve initialization for the pool -pub fn execute_initialize_queued_reserve(e: &Env, asset: &Address) -> u32 { - let queued_init = storage::get_queued_reserve_init(e, asset); +pub fn execute_set_queued_reserve(e: &Env, asset: &Address) -> u32 { + let queued_init = storage::get_queued_reserve_set(e, asset); if queued_init.unlock_time > e.ledger().timestamp() { panic_with_error!(e, PoolError::InitNotUnlocked); } - // remove queued init - storage::del_queued_reserve_init(e, asset); + // remove queued reserve + storage::del_queued_reserve_set(e, asset); // initialize reserve - let index = initialize_reserve(e, asset, &queued_init.new_config); - - index + initialize_reserve(e, asset, &queued_init.new_config) } -/// Initialize a reserve for the pool +/// sets reserve data for the pool fn initialize_reserve(e: &Env, asset: &Address, config: &ReserveConfig) -> u32 { + let index: u32; + // if reserve already exists, ensure index and scalar do not change if storage::has_res(e, asset) { - panic_with_error!(e, PoolError::AlreadyInitialized); + // accrue and store reserve data to the ledger + let pool = Pool::load(e); + let reserve = pool.load_reserve(e, asset); + reserve.store(e); + index = reserve.index; + if reserve.scalar != 10i128.pow(config.decimals) { + panic_with_error!(e, PoolError::InvalidReserveMetadata); + } + } else { + index = storage::push_res_list(e, asset); + let init_data = ReserveData { + b_rate: 1_000_000_000, + d_rate: 1_000_000_000, + ir_mod: 1_000_000_000, + d_supply: 0, + b_supply: 0, + last_time: e.ledger().timestamp(), + backstop_credit: 0, + }; + storage::set_res_data(e, asset, &init_data); } - require_valid_reserve_metadata(e, config); - let index = storage::push_res_list(e, asset); - let reserve_config = ReserveConfig { index, decimals: config.decimals, @@ -124,39 +134,8 @@ fn initialize_reserve(e: &Env, asset: &Address, config: &ReserveConfig) -> u32 { reactivity: config.reactivity, }; storage::set_res_config(e, asset, &reserve_config); - let init_data = ReserveData { - b_rate: 1_000_000_000, - d_rate: 1_000_000_000, - ir_mod: 1_000_000_000, - d_supply: 0, - b_supply: 0, - last_time: e.ledger().timestamp(), - backstop_credit: 0, - }; - storage::set_res_data(e, asset, &init_data); - e.events() - .publish((Symbol::new(&e, "init_reserve"),), (asset, index)); - index -} - -/// Update a reserve in the pool -pub fn execute_update_reserve(e: &Env, asset: &Address, config: &ReserveConfig) { - require_valid_reserve_metadata(e, config); - let pool = Pool::load(e); - if pool.config.status == 2 { - panic_with_error!(e, PoolError::InvalidPoolStatus); - } - - // accrue and store reserve data to the ledger - let reserve = pool.load_reserve(e, asset); - reserve.store(e); - - // force index to remain constant and only allow metadata based changes - let mut new_config = config.clone(); - new_config.index = reserve.index; - - storage::set_res_config(e, asset, &new_config); + index } #[allow(clippy::zero_prefixed_literal)] @@ -180,7 +159,6 @@ mod tests { use super::*; use soroban_sdk::testutils::{Address as _, Ledger, LedgerInfo}; - use soroban_sdk::vec; #[test] fn test_execute_initialize() { @@ -194,21 +172,6 @@ mod tests { let backstop_address = Address::generate(&e); let blnd_id = Address::generate(&e); let usdc_id = Address::generate(&e); - let (asset_id_0, _) = testutils::create_token_contract(&e, &admin); - let (asset_id_1, _) = testutils::create_token_contract(&e, &admin); - - let metadata = ReserveConfig { - index: 0, - decimals: 7, - c_factor: 0_7500000, - l_factor: 0_7500000, - util: 0_5000000, - max_util: 0_9500000, - r_one: 0_0500000, - r_two: 0_5000000, - r_three: 1_5000000, - reactivity: 100, - }; e.as_contract(&pool, || { execute_initialize( @@ -226,7 +189,7 @@ mod tests { let pool_config = storage::get_pool_config(&e); assert_eq!(pool_config.oracle, oracle); assert_eq!(pool_config.bstop_rate, bstop_rate); - assert_eq!(pool_config.status, 3); + assert_eq!(pool_config.status, 6); assert_eq!(storage::get_backstop(&e), backstop_address); assert_eq!(storage::get_blnd_token(&e), blnd_id); assert_eq!(storage::get_usdc_token(&e), usdc_id); @@ -273,13 +236,12 @@ mod tests { }); } #[test] - fn test_initialize_initial_reserves() { + fn test_queue_initial_reserve() { let e = Env::default(); let pool = testutils::create_pool(&e); let bombadil = Address::generate(&e); let (asset_id_0, _) = testutils::create_token_contract(&e, &bombadil); - let (asset_id_1, _) = testutils::create_token_contract(&e, &bombadil); let metadata = ReserveConfig { index: 0, @@ -293,17 +255,17 @@ mod tests { r_three: 1_5000000, reactivity: 100, }; + let pool_config = PoolConfig { + oracle: Address::generate(&e), + bstop_rate: 0_100_000_000, + status: 6, + }; e.as_contract(&pool, || { - execute_initialize_initial_reserves( - &e, - &vec![ - &e, - (asset_id_0.clone(), metadata.clone()), - (asset_id_1.clone(), metadata.clone()), - ], - ); - let res_config_0 = storage::get_res_config(&e, &asset_id_0); - let res_config_1 = storage::get_res_config(&e, &asset_id_1); + storage::set_pool_config(&e, &pool_config); + execute_queue_set_reserve(&e, &asset_id_0, &metadata); + let queued_res = storage::get_queued_reserve_set(&e, &asset_id_0); + let res_config_0 = queued_res.new_config; + assert_eq!(queued_res.unlock_time, e.ledger().timestamp()); assert_eq!(res_config_0.decimals, metadata.decimals); assert_eq!(res_config_0.c_factor, metadata.c_factor); assert_eq!(res_config_0.l_factor, metadata.l_factor); @@ -314,39 +276,9 @@ mod tests { assert_eq!(res_config_0.r_three, metadata.r_three); assert_eq!(res_config_0.reactivity, metadata.reactivity); assert_eq!(res_config_0.index, 0); - assert_eq!(res_config_1.index, 1); }); } - #[test] - #[should_panic(expected = "Error(Contract, #3)")] - fn test_initialize_initial_reserves_panics_if_reserves_exist() { - let e = Env::default(); - let pool = testutils::create_pool(&e); - let bombadil = Address::generate(&e); - - let (asset_id_0, _) = testutils::create_token_contract(&e, &bombadil); - let (asset_id_1, _) = testutils::create_token_contract(&e, &bombadil); - let metadata = ReserveConfig { - index: 0, - decimals: 7, - c_factor: 0_7500000, - l_factor: 0_7500000, - util: 0_5000000, - max_util: 0_9500000, - r_one: 0_0500000, - r_two: 0_5000000, - r_three: 1_5000000, - reactivity: 100, - }; - e.as_contract(&pool, || { - initialize_reserve(&e, &asset_id_0, &metadata); - execute_initialize_initial_reserves( - &e, - &vec![&e, (asset_id_1.clone(), metadata.clone())], - ); - }); - } #[test] fn test_execute_queue_reserve_initialization() { let e = Env::default(); @@ -367,9 +299,15 @@ mod tests { r_three: 1_5000000, reactivity: 100, }; + let pool_config = PoolConfig { + oracle: Address::generate(&e), + bstop_rate: 0_100_000_000, + status: 0, + }; e.as_contract(&pool, || { - execute_queue_reserve_initialization(&e, &asset_id_0, &metadata); - let queued_init = storage::get_queued_reserve_init(&e, &asset_id_0); + storage::set_pool_config(&e, &pool_config); + execute_queue_set_reserve(&e, &asset_id_0, &metadata); + let queued_init = storage::get_queued_reserve_set(&e, &asset_id_0); assert_eq!(queued_init.new_config.decimals, metadata.decimals); assert_eq!(queued_init.new_config.c_factor, metadata.c_factor); assert_eq!(queued_init.new_config.l_factor, metadata.l_factor); @@ -408,7 +346,7 @@ mod tests { reactivity: 100, }; e.as_contract(&pool, || { - storage::set_queued_reserve_init( + storage::set_queued_reserve_set( &e, &QueuedReserveInit { new_config: metadata.clone(), @@ -416,8 +354,8 @@ mod tests { }, &asset_id_0, ); - execute_cancel_queued_reserve_initialization(&e, &asset_id_0); - storage::get_queued_reserve_init(&e, &asset_id_0); + execute_cancel_queued_set_reserve(&e, &asset_id_0); + storage::get_queued_reserve_set(&e, &asset_id_0); }); } #[test] @@ -441,7 +379,7 @@ mod tests { reactivity: 100, }; e.as_contract(&pool, || { - storage::set_queued_reserve_init( + storage::set_queued_reserve_set( &e, &QueuedReserveInit { new_config: metadata.clone(), @@ -449,7 +387,7 @@ mod tests { }, &asset_id_0, ); - execute_initialize_queued_reserve(&e, &asset_id_0); + execute_set_queued_reserve(&e, &asset_id_0); let res_config_0: ReserveConfig = storage::get_res_config(&e, &asset_id_0); assert_eq!(res_config_0.decimals, metadata.decimals); assert_eq!(res_config_0.c_factor, metadata.c_factor); @@ -485,7 +423,7 @@ mod tests { reactivity: 100, }; e.as_contract(&pool, || { - storage::set_queued_reserve_init( + storage::set_queued_reserve_set( &e, &QueuedReserveInit { new_config: metadata.clone(), @@ -493,7 +431,7 @@ mod tests { }, &asset_id_0, ); - execute_initialize_queued_reserve(&e, &asset_id_0); + execute_set_queued_reserve(&e, &asset_id_0); }); } #[test] @@ -537,37 +475,9 @@ mod tests { }); } - #[test] - #[should_panic(expected = "Error(Contract, #3)")] - fn test_initialize_reserve_blocks_duplicates() { - let e = Env::default(); - let pool = testutils::create_pool(&e); - let bombadil = Address::generate(&e); - let (asset_id, _) = testutils::create_token_contract(&e, &bombadil); - - let metadata = ReserveConfig { - index: 0, - decimals: 7, - c_factor: 0_7500000, - l_factor: 0_7500000, - util: 0_5000000, - max_util: 0_9500000, - r_one: 0_0500000, - r_two: 0_5000000, - r_three: 1_5000000, - reactivity: 100, - }; - e.as_contract(&pool, || { - initialize_reserve(&e, &asset_id, &metadata); - let res_config = storage::get_res_config(&e, &asset_id); - assert_eq!(res_config.index, 0); - initialize_reserve(&e, &asset_id, &metadata); - }); - } - #[test] #[should_panic(expected = "Error(Contract, #6)")] - fn test_initialize_reserve_validates_metadata() { + fn test_queue_set_reserve_validates_metadata() { let e = Env::default(); let pool = testutils::create_pool(&e); let bombadil = Address::generate(&e); @@ -577,7 +487,7 @@ mod tests { index: 0, decimals: 7, c_factor: 0_7500000, - l_factor: 0_7500000, + l_factor: 1_7500000, util: 1_0000000, max_util: 0_9500000, r_one: 0_0500000, @@ -585,11 +495,14 @@ mod tests { r_three: 1_5000000, reactivity: 100, }; + let pool_config = PoolConfig { + oracle: Address::generate(&e), + bstop_rate: 0_100_000_000, + status: 0, + }; e.as_contract(&pool, || { - initialize_reserve(&e, &asset_id, &metadata); - let res_config = storage::get_res_config(&e, &asset_id); - assert_eq!(res_config.index, 0); - initialize_reserve(&e, &asset_id, &metadata); + storage::set_pool_config(&e, &pool_config); + execute_queue_set_reserve(&e, &asset_id, &metadata); }); } @@ -648,8 +561,15 @@ mod tests { storage::set_pool_config(&e, &pool_config); let res_config_old = storage::get_res_config(&e, &underlying); - - execute_update_reserve(&e, &underlying, &new_metadata); + storage::set_queued_reserve_set( + &e, + &QueuedReserveInit { + new_config: new_metadata.clone(), + unlock_time: e.ledger().timestamp(), + }, + &underlying, + ); + execute_set_queued_reserve(&e, &underlying); let res_config_updated = storage::get_res_config(&e, &underlying); assert_eq!(res_config_updated.decimals, new_metadata.decimals); assert_eq!(res_config_updated.c_factor, new_metadata.c_factor); @@ -672,7 +592,7 @@ mod tests { #[test] #[should_panic(expected = "Error(Contract, #6)")] - fn test_execute_update_reserve_validates_metadata() { + fn test_execute_update_reserve_validates_decimals() { let e = Env::default(); e.mock_all_auths(); e.ledger().set(LedgerInfo { @@ -695,7 +615,7 @@ mod tests { let new_metadata = ReserveConfig { index: 99, - decimals: 7, + decimals: 8, c_factor: 0_7500000, l_factor: 0_7500000, util: 1_0777777, @@ -714,7 +634,15 @@ mod tests { e.as_contract(&pool, || { storage::set_pool_config(&e, &pool_config); - execute_update_reserve(&e, &underlying, &new_metadata); + storage::set_queued_reserve_set( + &e, + &QueuedReserveInit { + new_config: new_metadata.clone(), + unlock_time: e.ledger().timestamp(), + }, + &underlying, + ); + execute_set_queued_reserve(&e, &underlying); }); } diff --git a/pool/src/pool/mod.rs b/pool/src/pool/mod.rs index 8baf272a..9097e5e1 100644 --- a/pool/src/pool/mod.rs +++ b/pool/src/pool/mod.rs @@ -6,9 +6,8 @@ pub use bad_debt::{burn_backstop_bad_debt, transfer_bad_debt_to_backstop}; mod config; pub use config::{ - execute_cancel_queued_reserve_initialization, execute_initialize, - execute_initialize_initial_reserves, execute_initialize_queued_reserve, - execute_queue_reserve_initialization, execute_update_pool, execute_update_reserve, + execute_cancel_queued_set_reserve, execute_initialize, execute_queue_set_reserve, + execute_set_queued_reserve, execute_update_pool, }; mod health_factor; diff --git a/pool/src/pool/status.rs b/pool/src/pool/status.rs index 283d8da0..c50e4092 100644 --- a/pool/src/pool/status.rs +++ b/pool/src/pool/status.rs @@ -23,6 +23,11 @@ pub fn execute_update_pool_status(e: &Env) -> u32 { } match pool_config.status { + // Setup + 6 => { + // Setup supersedes all other statuses + panic_with_error!(e, PoolError::StatusNotAllowed); + } // Admin frozen 4 => { // Admin frozen supersedes all other statuses @@ -71,10 +76,7 @@ pub fn execute_set_pool_status(e: &Env, pool_status: u32) { let backstop_client = BackstopClient::new(e, &backstop_id); let pool_backstop_data = backstop_client.pool_data(&e.current_contract_address()); - // Admins cannot set non-admin status' - if pool_status % 2 != 0 { - panic_with_error!(e, PoolError::BadRequest); - } + match pool_status { 0 => { // Threshold must be met and q4w must be under 50% for the admin to set Active @@ -94,6 +96,14 @@ pub fn execute_set_pool_status(e: &Env, pool_status: u32) { // Admin On-Ice pool_config.status = 2; } + 3 => { + // Q4w must be under 75% for admin to set permissionless On-Ice + if pool_backstop_data.q4w_pct >= 0_7500000 { + panic_with_error!(e, PoolError::StatusNotAllowed); + } + // Admin On-Ice + pool_config.status = 3; + } 4 => { // Admin can always freeze the pool // Admin Frozen @@ -891,11 +901,11 @@ mod tests { } #[test] - #[should_panic(expected = "Error(Auth, InvalidAction)")] + #[should_panic(expected = "Error(Contract, #8)")] fn test_update_pool_status_admin_frozen() { let e = Env::default(); e.budget().reset_unlimited(); - // e.mock_all_auths_allowing_non_root_auth(); + e.mock_all_auths_allowing_non_root_auth(); let pool_id = create_pool(&e); let oracle_id = Address::generate(&e); @@ -934,6 +944,50 @@ mod tests { }); } + #[test] + #[should_panic(expected = "Error(Contract, #8)")] + fn test_update_pool_status_setup() { + let e = Env::default(); + e.budget().reset_unlimited(); + e.mock_all_auths_allowing_non_root_auth(); + let pool_id = create_pool(&e); + let oracle_id = Address::generate(&e); + + let bombadil = Address::generate(&e); + let samwise = Address::generate(&e); + + let (blnd, blnd_client) = create_token_contract(&e, &bombadil); + let (usdc, usdc_client) = create_token_contract(&e, &bombadil); + let (lp_token, lp_token_client) = create_comet_lp_pool(&e, &bombadil, &blnd, &usdc); + let (backstop_id, backstop_client) = create_backstop(&e); + setup_backstop(&e, &pool_id, &backstop_id, &lp_token, &usdc, &blnd); + + // mint lp tokens + blnd_client.mint(&samwise, &500_001_0000000); + blnd_client.approve(&samwise, &lp_token, &i128::MAX, &99999); + usdc_client.mint(&samwise, &12_501_0000000); + usdc_client.approve(&samwise, &lp_token, &i128::MAX, &99999); + lp_token_client.join_pool( + &50_000_0000000, + &vec![&e, 500_001_0000000, 12_501_0000000], + &samwise, + ); + backstop_client.deposit(&samwise, &pool_id, &50_000_0000000); + backstop_client.update_tkn_val(); + + let pool_config = PoolConfig { + oracle: oracle_id, + bstop_rate: 0, + status: 6, + }; + e.as_contract(&pool_id, || { + storage::set_admin(&e, &bombadil); + storage::set_pool_config(&e, &pool_config); + + execute_update_pool_status(&e); + }); + } + #[test] fn test_admin_update_pool_status_unfreeze() { let e = Env::default(); diff --git a/pool/src/storage.rs b/pool/src/storage.rs index c4225163..5635b51c 100644 --- a/pool/src/storage.rs +++ b/pool/src/storage.rs @@ -367,14 +367,14 @@ pub fn has_res(e: &Env, asset: &Address) -> bool { e.storage().persistent().has(&key) } -/// Fetch a queued reserve initialization +/// Fetch a queued reserve set /// /// ### Arguments /// * `asset` - The contract address of the asset /// /// ### Panics -/// If the reserve initialization has not been queued -pub fn get_queued_reserve_init(e: &Env, asset: &Address) -> QueuedReserveInit { +/// If the reserve set has not been queued +pub fn get_queued_reserve_set(e: &Env, asset: &Address) -> QueuedReserveInit { let key = PoolDataKey::ResInit(asset.clone()); e.storage() .persistent() @@ -385,12 +385,12 @@ pub fn get_queued_reserve_init(e: &Env, asset: &Address) -> QueuedReserveInit { .unwrap_optimized() } -/// Set a new queued reserve initialization +/// Set a new queued reserve set /// /// ### Arguments /// * `asset` - The contract address of the asset /// * `config` - The reserve configuration for the asset -pub fn set_queued_reserve_init(e: &Env, res_init: &QueuedReserveInit, asset: &Address) { +pub fn set_queued_reserve_set(e: &Env, res_init: &QueuedReserveInit, asset: &Address) { let key = PoolDataKey::ResInit(asset.clone()); e.storage() .persistent() @@ -400,14 +400,14 @@ pub fn set_queued_reserve_init(e: &Env, res_init: &QueuedReserveInit, asset: &Ad .extend_ttl(&key, LEDGER_THRESHOLD_SHARED, LEDGER_BUMP_SHARED); } -/// Delete a queued reserve initialization +/// Delete a queued reserve set /// /// ### Arguments /// * `asset` - The contract address of the asset /// /// ### Panics -/// If the reserve initialization has not been queued -pub fn del_queued_reserve_init(e: &Env, asset: &Address) { +/// If the reserve set has not been queued +pub fn del_queued_reserve_set(e: &Env, asset: &Address) { let key = PoolDataKey::ResInit(asset.clone()); e.storage().persistent().remove(&key); } diff --git a/test-suites/src/pool.rs b/test-suites/src/pool.rs index ed029dde..f290593c 100644 --- a/test-suites/src/pool.rs +++ b/test-suites/src/pool.rs @@ -15,7 +15,7 @@ pub fn default_reserve_metadata() -> ReserveConfig { r_one: 0_0500000, r_two: 0_5000000, r_three: 1_5000000, - reactivity: 0_000_002_000, // 10e-5 + reactivity: 0, // 10e-5 0_000_002_000 index: 0, } } diff --git a/test-suites/src/setup.rs b/test-suites/src/setup.rs index d213d654..1e98c32f 100644 --- a/test-suites/src/setup.rs +++ b/test-suites/src/setup.rs @@ -33,41 +33,27 @@ pub fn create_fixture_with_data<'a>(wasm: bool) -> TestFixture<'a> { ); // create pool + fixture.create_pool(Symbol::new(&fixture.env, "Teapot"), 0_100_000_000); let mut stable_config = default_reserve_metadata(); stable_config.decimals = 6; stable_config.c_factor = 0_900_0000; stable_config.l_factor = 0_950_0000; stable_config.util = 0_850_0000; + fixture.create_pool_reserve(0, TokenIndex::STABLE, &stable_config); let mut xlm_config = default_reserve_metadata(); xlm_config.c_factor = 0_750_0000; xlm_config.l_factor = 0_750_0000; xlm_config.util = 0_500_0000; + fixture.create_pool_reserve(0, TokenIndex::XLM, &xlm_config); let mut weth_config = default_reserve_metadata(); weth_config.decimals = 9; weth_config.c_factor = 0_800_0000; weth_config.l_factor = 0_800_0000; weth_config.util = 0_700_0000; - - fixture.create_pool( - Symbol::new(&fixture.env, "Teapot"), - 0_100_000_000, - svec![ - &fixture.env, - ( - fixture.tokens[TokenIndex::STABLE].address.clone(), - stable_config - ), - (fixture.tokens[TokenIndex::XLM].address.clone(), xlm_config), - ( - fixture.tokens[TokenIndex::WETH].address.clone(), - weth_config - ), - ], - vec![TokenIndex::STABLE, TokenIndex::XLM, TokenIndex::WETH], - ); + fixture.create_pool_reserve(0, TokenIndex::WETH, &weth_config); // enable emissions for pool let pool_fixture = &fixture.pools[0]; @@ -95,6 +81,7 @@ pub fn create_fixture_with_data<'a>(wasm: bool) -> TestFixture<'a> { fixture .backstop .add_reward(&pool_fixture.pool.address, &Address::generate(&fixture.env)); + pool_fixture.pool.set_status(&3); pool_fixture.pool.update_status(); // enable emissions diff --git a/test-suites/src/test_fixture.rs b/test-suites/src/test_fixture.rs index ddf11fed..8cc4a87b 100644 --- a/test-suites/src/test_fixture.rs +++ b/test-suites/src/test_fixture.rs @@ -18,7 +18,7 @@ use pool_factory::{PoolFactoryClient, PoolInitMeta}; use sep_40_oracle::testutils::{Asset, MockPriceOracleClient}; use sep_41_token::testutils::MockTokenClient; use soroban_sdk::testutils::{Address as _, BytesN as _, Ledger, LedgerInfo}; -use soroban_sdk::{vec as svec, Address, BytesN, Env, Map, Symbol, Vec as SVec}; +use soroban_sdk::{vec as svec, Address, BytesN, Env, Map, Symbol}; pub const SCALAR_7: i128 = 1_000_0000; pub const SCALAR_9: i128 = 1_000_000_000; @@ -167,18 +167,7 @@ impl TestFixture<'_> { fixture } - pub fn create_pool( - &mut self, - name: Symbol, - backstop_take_rate: u64, - reserves: SVec<(Address, ReserveConfig)>, - asset_indexes: Vec, - ) { - let mut fixture_reserves = HashMap::new(); - for i in 0..reserves.len() { - fixture_reserves.insert(*asset_indexes.get(i as usize).unwrap(), i as u32); - } - + pub fn create_pool(&mut self, name: Symbol, backstop_take_rate: u64) { let pool_id = self.pool_factory.deploy( &self.bombadil, &name, @@ -186,10 +175,9 @@ impl TestFixture<'_> { &self.oracle.address, &backstop_take_rate, ); - PoolClient::new(&self.env, &pool_id).init_initial_reserves(&reserves); self.pools.push(PoolFixture { pool: PoolClient::new(&self.env, &pool_id), - reserves: fixture_reserves, + reserves: HashMap::new(), }); } @@ -203,9 +191,8 @@ impl TestFixture<'_> { let token = &self.tokens[asset_index]; pool_fixture .pool - .queue_init_reserve(&token.address, reserve_config); - self.jump(604800); - let index = pool_fixture.pool.init_reserve(&token.address); + .queue_set_reserve(&token.address, reserve_config); + let index = pool_fixture.pool.set_reserve(&token.address); pool_fixture.reserves.insert(asset_index, index); self.pools.insert(pool_index, pool_fixture); } diff --git a/test-suites/tests/test_liquidation.rs b/test-suites/tests/test_liquidation.rs index 705f2720..a4cb1fd0 100644 --- a/test-suites/tests/test_liquidation.rs +++ b/test-suites/tests/test_liquidation.rs @@ -19,22 +19,31 @@ fn test_liquidations() { let pool_fixture = &fixture.pools[0]; // Disable rate modifiers - let mut usdc_config: ReserveConfig = fixture.read_reserve_config(0, TokenIndex::STABLE); - usdc_config.reactivity = 0; - pool_fixture - .pool - .update_reserve(&fixture.tokens[TokenIndex::STABLE].address, &usdc_config); - let mut xlm_config: ReserveConfig = fixture.read_reserve_config(0, TokenIndex::XLM); - xlm_config.reactivity = 0; - pool_fixture - .pool - .update_reserve(&fixture.tokens[TokenIndex::XLM].address, &xlm_config); - let mut weth_config: ReserveConfig = fixture.read_reserve_config(0, TokenIndex::WETH); - weth_config.reactivity = 0; - pool_fixture - .pool - .update_reserve(&fixture.tokens[TokenIndex::WETH].address, &weth_config); - + // let mut usdc_config: ReserveConfig = fixture.read_reserve_config(0, TokenIndex::STABLE); + // usdc_config.reactivity = 0; + // pool_fixture + // .pool + // .queue_set_reserve(&fixture.tokens[TokenIndex::STABLE].address, &usdc_config); + // let mut xlm_config: ReserveConfig = fixture.read_reserve_config(0, TokenIndex::XLM); + // xlm_config.reactivity = 0; + // pool_fixture + // .pool + // .queue_set_reserve(&fixture.tokens[TokenIndex::XLM].address, &xlm_config); + // let mut weth_config: ReserveConfig = fixture.read_reserve_config(0, TokenIndex::WETH); + // weth_config.reactivity = 0; + // pool_fixture + // .pool + // .queue_set_reserve(&fixture.tokens[TokenIndex::WETH].address, &weth_config); + // fixture.jump(60 * 60 * 24 * 7); + // pool_fixture + // .pool + // .set_reserve(&fixture.tokens[TokenIndex::STABLE].address); + // pool_fixture + // .pool + // .set_reserve(&fixture.tokens[TokenIndex::XLM].address); + // pool_fixture + // .pool + // .set_reserve(&fixture.tokens[TokenIndex::WETH].address); // Create a user let samwise = Address::generate(&fixture.env); //sam will be supplying XLM and borrowing STABLE diff --git a/test-suites/tests/test_pool.rs b/test-suites/tests/test_pool.rs index 65076f15..2426c96a 100644 --- a/test-suites/tests/test_pool.rs +++ b/test-suites/tests/test_pool.rs @@ -593,7 +593,7 @@ fn test_pool_config() { reserve_config.c_factor = 0_200_0000; pool_fixture .pool - .queue_init_reserve(&blnd.address, &reserve_config); + .queue_set_reserve(&blnd.address, &reserve_config); assert_eq!( fixture.env.auths()[0], ( @@ -613,7 +613,7 @@ fn test_pool_config() { ) ); fixture.jump(604800); // 1 week - pool_fixture.pool.init_reserve(&blnd.address); + pool_fixture.pool.set_reserve(&blnd.address); let new_reserve_config = fixture.read_reserve_config(0, TokenIndex::BLND); assert_eq!(new_reserve_config.l_factor, 0_500_0000); @@ -631,7 +631,7 @@ fn test_pool_config() { &fixture.env, ( pool_fixture.pool.address.clone(), - (Symbol::new(&fixture.env, "init_reserve"),).into_val(&fixture.env), + (Symbol::new(&fixture.env, "set_reserve"),).into_val(&fixture.env), event_data.into_val(&fixture.env) ) ] @@ -641,7 +641,7 @@ fn test_pool_config() { reserve_config.c_factor = 0; pool_fixture .pool - .update_reserve(&blnd.address, &reserve_config); + .queue_set_reserve(&blnd.address, &reserve_config); assert_eq!( fixture.env.auths()[0], ( @@ -649,7 +649,7 @@ fn test_pool_config() { AuthorizedInvocation { function: AuthorizedFunction::Contract(( pool_fixture.pool.address.clone(), - Symbol::new(&fixture.env, "update_reserve"), + Symbol::new(&fixture.env, "queue_set_reserve"), vec![ &fixture.env, blnd.address.to_val(), @@ -660,6 +660,19 @@ fn test_pool_config() { } ) ); + fixture.jump(604800); // 1 week + pool_fixture.pool.set_reserve(&blnd.address); + assert_eq!( + event, + vec![ + &fixture.env, + ( + pool_fixture.pool.address.clone(), + (Symbol::new(&fixture.env, "set_reserve"),).into_val(&fixture.env), + event_data.into_val(&fixture.env) + ) + ] + ); let new_reserve_config = fixture.read_reserve_config(0, TokenIndex::BLND); assert_eq!(new_reserve_config.l_factor, 0_500_0000); assert_eq!(new_reserve_config.c_factor, 0);