From b645bd08368b86800f338edbaf6b1c5255fa508c Mon Sep 17 00:00:00 2001 From: markuspluna <59978114+markuspluna@users.noreply.github.com> Date: Fri, 19 Jan 2024 20:35:19 +0300 Subject: [PATCH 1/3] Completed logic - still fixing tests --- backstop/src/backstop/fund_management.rs | 212 ----------- backstop/src/backstop/mod.rs | 5 +- backstop/src/contract.rs | 39 -- backstop/src/emissions/manager.rs | 5 +- backstop/src/storage.rs | 24 -- pool/src/auctions/auction.rs | 61 ++-- .../src/auctions/backstop_interest_auction.rs | 336 ++++++++++-------- pool/src/contract.rs | 35 +- pool/src/pool/status.rs | 8 +- pool/src/testutils.rs | 3 +- test-suites/src/test_fixture.rs | 24 +- test-suites/tests/test_liquidation.rs | 21 +- test-suites/tests/test_overflow_flag.rs | 24 +- 13 files changed, 308 insertions(+), 489 deletions(-) diff --git a/backstop/src/backstop/fund_management.rs b/backstop/src/backstop/fund_management.rs index e59c8bc7..18d68c4f 100644 --- a/backstop/src/backstop/fund_management.rs +++ b/backstop/src/backstop/fund_management.rs @@ -38,46 +38,6 @@ pub fn execute_donate(e: &Env, from: &Address, pool_address: &Address, amount: i storage::set_pool_balance(e, pool_address, &pool_balance); } -/// Perform a donation of USDC to a pool's backstop -pub fn execute_donate_usdc(e: &Env, from: &Address, pool_address: &Address, amount: i128) { - require_nonnegative(e, amount); - if from == pool_address || from == &e.current_contract_address() { - panic_with_error!(e, &BackstopError::BadRequest) - } - - let mut pool_usdc = storage::get_pool_usdc(e, pool_address); - require_is_from_pool_factory(e, pool_address, pool_usdc); - - let usdc_token = TokenClient::new(e, &storage::get_usdc_token(e)); - usdc_token.transfer(from, &e.current_contract_address(), &amount); - - pool_usdc += amount; - storage::set_pool_usdc(e, pool_address, &pool_usdc); -} - -/// Perform a mint of backstop LP tokens with USDC and deposit the LP tokens to the pool -pub fn execute_gulp_usdc(e: &Env, pool_address: &Address) { - let pool_usdc = storage::get_pool_usdc(e, pool_address); - if pool_usdc != 0 { - // mint LP tokens with USDC - let backstop_token = storage::get_backstop_token(e); - let usdc_token = storage::get_usdc_token(e); - let lp_tokens_minted = CometClient::new(e, &backstop_token) - .dep_tokn_amt_in_get_lp_tokns_out( - &usdc_token, - &pool_usdc, - &0, - &e.current_contract_address(), - ); - - // attribute shares to the pool's backstop - let mut pool_balance = storage::get_pool_balance(e, pool_address); - pool_balance.deposit(lp_tokens_minted, 0); - storage::set_pool_balance(e, pool_address, &pool_balance); - storage::set_pool_usdc(e, pool_address, &0); - } -} - /// Perform an update to the Comet LP token underlying value pub fn execute_update_comet_token_value( e: &Env, @@ -358,178 +318,6 @@ mod tests { }); } - #[test] - fn test_execute_donate_usdc() { - let e = Env::default(); - e.mock_all_auths_allowing_non_root_auth(); - e.budget().reset_unlimited(); - - let backstop_id = create_backstop(&e); - let pool_0_id = Address::generate(&e); - let bombadil = Address::generate(&e); - let samwise = Address::generate(&e); - let frodo = Address::generate(&e); - - let (_, usdc_token_client) = create_usdc_token(&e, &backstop_id, &bombadil); - usdc_token_client.mint(&samwise, &100_0000000); - usdc_token_client.mint(&frodo, &100_0000000); - - let (_, mock_pool_factory_client) = create_mock_pool_factory(&e, &backstop_id); - mock_pool_factory_client.set_pool(&pool_0_id); - - e.as_contract(&backstop_id, || { - execute_donate_usdc(&e, &samwise, &pool_0_id, 30_0000000); - let new_pool_usdc = storage::get_pool_usdc(&e, &pool_0_id); - assert_eq!(new_pool_usdc, 30_0000000); - assert_eq!(usdc_token_client.balance(&samwise), 70_0000000); - assert_eq!(usdc_token_client.balance(&backstop_id), 30_0000000); - - execute_donate_usdc(&e, &frodo, &pool_0_id, 10_0000000); - let new_pool_usdc = storage::get_pool_usdc(&e, &pool_0_id); - assert_eq!(new_pool_usdc, 40_0000000); - assert_eq!(usdc_token_client.balance(&frodo), 90_0000000); - assert_eq!(usdc_token_client.balance(&backstop_id), 40_0000000); - }); - } - - #[test] - #[should_panic(expected = "Error(Contract, #8)")] - fn test_execute_donate_usdc_negative_amount() { - let e = Env::default(); - e.mock_all_auths_allowing_non_root_auth(); - e.budget().reset_unlimited(); - - let backstop_id = create_backstop(&e); - let pool_0_id = Address::generate(&e); - let bombadil = Address::generate(&e); - let samwise = Address::generate(&e); - - let (_, usdc_token_client) = create_usdc_token(&e, &backstop_id, &bombadil); - usdc_token_client.mint(&samwise, &100_0000000); - - let (_, mock_pool_factory_client) = create_mock_pool_factory(&e, &backstop_id); - mock_pool_factory_client.set_pool(&pool_0_id); - - e.as_contract(&backstop_id, || { - execute_donate_usdc(&e, &samwise, &pool_0_id, -30_0000000); - }); - } - - #[test] - #[should_panic(expected = "Error(Contract, #1000)")] - fn test_execute_donate_usdc_from_is_to() { - let e = Env::default(); - e.mock_all_auths_allowing_non_root_auth(); - e.budget().reset_unlimited(); - - let backstop_id = create_backstop(&e); - let pool_0_id = Address::generate(&e); - let bombadil = Address::generate(&e); - let samwise = Address::generate(&e); - - let (_, usdc_token_client) = create_usdc_token(&e, &backstop_id, &bombadil); - usdc_token_client.mint(&samwise, &100_0000000); - - let (_, mock_pool_factory_client) = create_mock_pool_factory(&e, &backstop_id); - mock_pool_factory_client.set_pool(&pool_0_id); - - e.as_contract(&backstop_id, || { - execute_donate_usdc(&e, &pool_0_id, &pool_0_id, 10_0000000); - }); - } - - #[test] - #[should_panic(expected = "Error(Contract, #1000)")] - fn test_execute_donate_usdc_from_is_self() { - let e = Env::default(); - e.mock_all_auths_allowing_non_root_auth(); - e.budget().reset_unlimited(); - - let backstop_id = create_backstop(&e); - let pool_0_id = Address::generate(&e); - let bombadil = Address::generate(&e); - let samwise = Address::generate(&e); - - let (_, usdc_token_client) = create_usdc_token(&e, &backstop_id, &bombadil); - usdc_token_client.mint(&samwise, &100_0000000); - - let (_, mock_pool_factory_client) = create_mock_pool_factory(&e, &backstop_id); - mock_pool_factory_client.set_pool(&pool_0_id); - - e.as_contract(&backstop_id, || { - execute_donate_usdc(&e, &backstop_id, &pool_0_id, 10_0000000); - }); - } - - #[test] - #[should_panic(expected = "Error(Contract, #1004)")] - fn test_execute_donate_usdc_not_pool() { - let e = Env::default(); - e.mock_all_auths_allowing_non_root_auth(); - e.budget().reset_unlimited(); - - let backstop_id = create_backstop(&e); - let pool_0_id = Address::generate(&e); - let bombadil = Address::generate(&e); - let samwise = Address::generate(&e); - - let (_, usdc_token_client) = create_usdc_token(&e, &backstop_id, &bombadil); - usdc_token_client.mint(&samwise, &100_0000000); - - create_mock_pool_factory(&e, &backstop_id); - - e.as_contract(&backstop_id, || { - execute_donate_usdc(&e, &samwise, &pool_0_id, 30_0000000); - }); - } - - #[test] - fn test_execute_gulp_usdc() { - let e = Env::default(); - e.mock_all_auths_allowing_non_root_auth(); - e.budget().reset_unlimited(); - - let backstop_id = create_backstop(&e); - let pool_0_id = Address::generate(&e); - let bombadil = Address::generate(&e); - let samwise = Address::generate(&e); - - let (usdc_token, usdc_token_client) = create_usdc_token(&e, &backstop_id, &bombadil); - usdc_token_client.mint(&samwise, &100_0000000); - - let (blnd_token, blnd_token_client) = create_blnd_token(&e, &backstop_id, &bombadil); - blnd_token_client.mint(&samwise, &100_0000000); - - let (_, mock_pool_factory_client) = create_mock_pool_factory(&e, &backstop_id); - mock_pool_factory_client.set_pool(&pool_0_id); - - let (comet_id, comet_client) = - create_comet_lp_pool(&e, &bombadil, &blnd_token, &usdc_token); - - // initialize pool 0 with funds and a donation - e.as_contract(&backstop_id, || { - storage::set_backstop_token(&e, &comet_id); - execute_deposit(&e, &bombadil, &pool_0_id, 10_0000000); - execute_donate_usdc(&e, &samwise, &pool_0_id, 5_0000000); - usdc_token_client.approve(&e.current_contract_address(), &comet_id, &i128::MAX, &500); - }); - - e.as_contract(&backstop_id, || { - execute_gulp_usdc(&e, &pool_0_id); - - let new_pool_usdc = storage::get_pool_usdc(&e, &pool_0_id); - assert_eq!(new_pool_usdc, 0); - assert_eq!(usdc_token_client.balance(&backstop_id), 0); - - let new_pool_balance = storage::get_pool_balance(&e, &pool_0_id); - assert_eq!(new_pool_balance.shares, 10_0000000); - assert_eq!(new_pool_balance.tokens, 13_9904000); - - let comet_balance = comet_client.balance(&backstop_id); - assert_eq!(comet_balance, 13_9904000); - }); - } - #[test] fn test_execute_update_comet_token_value() { let e = Env::default(); diff --git a/backstop/src/backstop/mod.rs b/backstop/src/backstop/mod.rs index 87fbc736..34d08db8 100644 --- a/backstop/src/backstop/mod.rs +++ b/backstop/src/backstop/mod.rs @@ -2,10 +2,7 @@ mod deposit; pub use deposit::execute_deposit; mod fund_management; -pub use fund_management::{ - execute_donate, execute_donate_usdc, execute_draw, execute_gulp_usdc, - execute_update_comet_token_value, -}; +pub use fund_management::{execute_donate, execute_draw, execute_update_comet_token_value}; mod withdrawal; pub use withdrawal::{execute_dequeue_withdrawal, execute_queue_withdrawal, execute_withdraw}; diff --git a/backstop/src/contract.rs b/backstop/src/contract.rs index 8bdefd74..d3037c37 100644 --- a/backstop/src/contract.rs +++ b/backstop/src/contract.rs @@ -160,28 +160,6 @@ pub trait Backstop { /// If the `pool_address` is not valid fn donate(e: Env, from: Address, pool_address: Address, amount: i128); - /// Sends USDC from "from" to a pools backstop to be queued for donation - /// - /// NOTE: This is not a deposit, and "from" will permanently lose access to the funds - /// - /// ### Arguments - /// * `from` - tge - /// * `pool_address` - The address of the pool - /// * `amount` - The amount of BLND to add - /// - /// ### Errors - /// If the `pool_address` is not valid - fn donate_usdc(e: Env, from: Address, pool_address: Address, amount: i128); - - /// Consume donated USDC for a pool and mint LP tokens into the pool's backstop - /// - /// ### Arguments - /// * `pool_address` - The address of the pool - /// - /// ### Errors - /// If the `pool_address` is not valid - fn gulp_usdc(e: Env, pool_address: Address); - /// Updates the underlying value of 1 backstop token /// /// ### Returns @@ -352,23 +330,6 @@ impl Backstop for BackstopContract { .publish((Symbol::new(&e, "donate"), pool_address, from), amount); } - fn donate_usdc(e: Env, from: Address, pool_address: Address, amount: i128) { - storage::extend_instance(&e); - from.require_auth(); - - backstop::execute_donate_usdc(&e, &from, &pool_address, amount); - e.events() - .publish((Symbol::new(&e, "donate_usdc"), pool_address, from), amount); - } - - fn gulp_usdc(e: Env, pool_address: Address) { - storage::extend_instance(&e); - - backstop::execute_gulp_usdc(&e, &pool_address); - e.events() - .publish((Symbol::new(&e, "gulp_usdc"), pool_address), ()); - } - fn update_tkn_val(e: Env) -> (i128, i128) { storage::extend_instance(&e); diff --git a/backstop/src/emissions/manager.rs b/backstop/src/emissions/manager.rs index 04cffd62..4130c6cc 100644 --- a/backstop/src/emissions/manager.rs +++ b/backstop/src/emissions/manager.rs @@ -105,14 +105,14 @@ pub fn gulp_emissions(e: &Env) -> i128 { .fixed_div_floor(total_non_queued_tokens, SCALAR_7) .unwrap_optimized(); - // store pool EPS and distribute pool's emissions via allowances to pool + // store new emissions for pool let new_pool_emissions = share .fixed_mul_floor(total_pool_emissions, SCALAR_7) .unwrap_optimized(); let current_emissions = storage::get_pool_emissions(e, &rz_pool); storage::set_pool_emissions(e, &rz_pool, current_emissions + new_pool_emissions); - // distribute backstop depositor emissions + // distribute backstop depositor emissions and store backstop EPS let new_pool_backstop_tokens = share .fixed_mul_floor(total_backstop_emissions, SCALAR_7) .unwrap_optimized(); @@ -128,6 +128,7 @@ pub fn gulp_pool_emissions(e: &Env, pool_id: &Address) -> i128 { panic_with_error!(e, BackstopError::BadRequest); } + // distribute pool emissions via allowance to pools let blnd_token_client = TokenClient::new(e, &storage::get_blnd_token(e)); let current_allowance = blnd_token_client.allowance(&e.current_contract_address(), pool_id); let new_tokens = current_allowance + pool_emissions; diff --git a/backstop/src/storage.rs b/backstop/src/storage.rs index dea989c5..b0febc17 100644 --- a/backstop/src/storage.rs +++ b/backstop/src/storage.rs @@ -278,30 +278,6 @@ pub fn set_pool_balance(e: &Env, pool: &Address, balance: &PoolBalance) { .extend_ttl(&key, LEDGER_THRESHOLD_SHARED, LEDGER_BUMP_SHARED); } -/// Fetch the balances for a given pool -/// -/// ### Arguments -/// * `pool` - The pool the deposit is associated with -pub fn get_pool_usdc(e: &Env, pool: &Address) -> i128 { - let key = BackstopDataKey::PoolUSDC(pool.clone()); - get_persistent_default(e, &key, 0i128, LEDGER_THRESHOLD_SHARED, LEDGER_BUMP_SHARED) -} - -/// Set the balances for a pool -/// -/// ### Arguments -/// * `pool` - The pool the deposit is associated with -/// * `balance` - The pool balances -pub fn set_pool_usdc(e: &Env, pool: &Address, balance: &i128) { - let key = BackstopDataKey::PoolUSDC(pool.clone()); - e.storage() - .persistent() - .set::(&key, balance); - e.storage() - .persistent() - .extend_ttl(&key, LEDGER_THRESHOLD_SHARED, LEDGER_BUMP_SHARED); -} - /********** Distribution / Reward Zone **********/ /// Get the timestamp of when the next emission cycle begins diff --git a/pool/src/auctions/auction.rs b/pool/src/auctions/auction.rs index 53dc5dd6..cc5e6ba2 100644 --- a/pool/src/auctions/auction.rs +++ b/pool/src/auctions/auction.rs @@ -7,7 +7,7 @@ use crate::{ use cast::i128; use soroban_fixed_point_math::FixedPoint; use soroban_sdk::{ - contracttype, map, panic_with_error, unwrap::UnwrapOptimized, Address, Env, Map, + contracttype, map, panic_with_error, unwrap::UnwrapOptimized, Address, Env, Map, Vec, }; use super::{ @@ -43,26 +43,45 @@ pub struct AuctionData { pub block: u32, } -/// Create an auction. Stores the resulting auction to the ledger to begin on the next block +/// Create a bad debt auction. Stores the resulting auction to the ledger to begin on the next block +/// +/// Returns the AuctionData object created. +/// +/// ### Panics +/// If the auction is unable to be created +pub fn create_bad_debt_auction(e: &Env) -> AuctionData { + let backstop = storage::get_backstop(e); + let auction_data = create_bad_debt_auction_data(e, &backstop); + + storage::set_auction( + e, + &(AuctionType::BadDebtAuction as u32), + &backstop, + &auction_data, + ); + + auction_data +} + +/// Create an interest auction. Stores the resulting auction to the ledger to begin on the next block /// /// Returns the AuctionData object created. /// /// ### Arguments -/// * `auction_type` - The type of auction being created +/// * `assets` - The assets interest is being auctioned off from /// /// ### Panics /// If the auction is unable to be created -pub fn create(e: &Env, auction_type: u32) -> AuctionData { +pub fn create_interest_auction(e: &Env, assets: &Vec
) -> AuctionData { let backstop = storage::get_backstop(e); - let auction_data = match AuctionType::from_u32(e, auction_type) { - AuctionType::UserLiquidation => { - panic_with_error!(e, PoolError::BadRequest); - } - AuctionType::BadDebtAuction => create_bad_debt_auction_data(e, &backstop), - AuctionType::InterestAuction => create_interest_auction_data(e, &backstop), - }; + let auction_data = create_interest_auction_data(e, &backstop, assets); - storage::set_auction(e, &auction_type, &backstop, &auction_data); + storage::set_auction( + e, + &(AuctionType::InterestAuction as u32), + &backstop, + &auction_data, + ); auction_data } @@ -396,7 +415,7 @@ mod tests { storage::set_pool_config(&e, &pool_config); storage::set_user_positions(&e, &backstop_address, &positions); - create(&e, 1); + create_bad_debt_auction(&e); assert!(storage::has_auction(&e, &1, &backstop_address)); }); } @@ -500,7 +519,7 @@ mod tests { e.as_contract(&pool_address, || { storage::set_pool_config(&e, &pool_config); - create(&e, 2); + create_interest_auction(&e, &vec![&e, underlying_0, underlying_1]); assert!(storage::has_auction(&e, &2, &backstop_address)); }); } @@ -612,20 +631,6 @@ mod tests { }); } - #[test] - #[should_panic(expected = "Error(Contract, #1200)")] - fn test_create_user_liquidation_errors() { - let e = Env::default(); - let pool_id = create_pool(&e); - let backstop_id = Address::generate(&e); - - e.as_contract(&pool_id, || { - storage::set_backstop(&e, &backstop_id); - - create(&e, AuctionType::UserLiquidation as u32); - }); - } - #[test] fn test_delete_user_liquidation() { let e = Env::default(); diff --git a/pool/src/auctions/backstop_interest_auction.rs b/pool/src/auctions/backstop_interest_auction.rs index 36cd5565..f0ea8601 100644 --- a/pool/src/auctions/backstop_interest_auction.rs +++ b/pool/src/auctions/backstop_interest_auction.rs @@ -4,11 +4,15 @@ use crate::{ use cast::i128; use sep_41_token::TokenClient; use soroban_fixed_point_math::FixedPoint; -use soroban_sdk::{map, panic_with_error, unwrap::UnwrapOptimized, Address, Env}; +use soroban_sdk::{map, panic_with_error, unwrap::UnwrapOptimized, Address, Env, Vec}; use super::{AuctionData, AuctionType}; -pub fn create_interest_auction_data(e: &Env, backstop: &Address) -> AuctionData { +pub fn create_interest_auction_data( + e: &Env, + backstop: &Address, + assets: &Vec
, +) -> AuctionData { if storage::has_auction(e, &(AuctionType::InterestAuction as u32), backstop) { panic_with_error!(e, PoolError::AuctionInProgress); } @@ -20,10 +24,8 @@ pub fn create_interest_auction_data(e: &Env, backstop: &Address) -> AuctionData block: e.ledger().sequence() + 1, }; - let reserve_list = storage::get_res_list(e); let mut interest_value = 0; // expressed in the oracle's decimals - for i in 0..reserve_list.len() { - let res_asset_address = reserve_list.get_unchecked(i); + for res_asset_address in assets.iter() { // don't store updated reserve data back to ledger. This will occur on the the auction's fill. let reserve = pool.load_reserve(e, &res_asset_address, false); if reserve.backstop_credit > 0 { @@ -48,13 +50,19 @@ pub fn create_interest_auction_data(e: &Env, backstop: &Address) -> AuctionData let usdc_token = storage::get_usdc_token(e); let usdc_to_base = pool.load_price(e, &usdc_token); + let backstop_client = BackstopClient::new(&e, &storage::get_backstop(e)); + let pool_backstop_data = backstop_client.pool_data(&e.current_contract_address()); + let backstop_token_value_base = (pool_backstop_data.usdc * 5) + .fixed_div_floor(pool_backstop_data.tokens, usdc_to_base) + .unwrap_optimized(); let bid_amount = interest_value .fixed_mul_floor(1_4000000, SCALAR_7) .unwrap_optimized() - .fixed_div_floor(i128(usdc_to_base), SCALAR_7) + .fixed_div_floor(backstop_token_value_base, SCALAR_7) .unwrap_optimized(); - // u32::MAX is the key for the USDC lot - auction_data.bid.set(storage::get_usdc_token(e), bid_amount); + auction_data + .bid + .set(backstop_client.backstop_token(), bid_amount); auction_data } @@ -65,16 +73,20 @@ pub fn fill_interest_auction( auction_data: &AuctionData, filler: &Address, ) { - // bid only contains the USDC token + // bid only contains the Backstop token let backstop = storage::get_backstop(e); if filler.clone() == backstop { panic_with_error!(e, PoolError::BadRequest); } - let usdc_token = storage::get_usdc_token(e); - let usdc_bid_amount = auction_data.bid.get_unchecked(usdc_token); - let backstop_client = BackstopClient::new(&e, &backstop); - backstop_client.donate_usdc(&filler, &e.current_contract_address(), &usdc_bid_amount); + let backstop_token: Address = backstop_client.backstop_token(); + let backstop_token_bid_amount = auction_data.bid.get_unchecked(backstop_token); + + backstop_client.donate( + &filler, + &e.current_contract_address(), + &backstop_token_bid_amount, + ); // 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() { @@ -95,7 +107,7 @@ mod tests { use crate::{ auctions::auction::AuctionType, storage::{self, PoolConfig}, - testutils::{self, create_pool}, + testutils::{self, create_comet_lp_pool, create_pool}, }; use super::*; @@ -137,7 +149,7 @@ mod tests { &auction_data, ); - create_interest_auction_data(&e, &backstop_address); + create_interest_auction_data(&e, &backstop_address, &vec![&e]); }); } @@ -239,13 +251,7 @@ mod tests { e.as_contract(&pool_address, || { storage::set_pool_config(&e, &pool_config); - let result = create_interest_auction_data(&e, &backstop_address); - assert_eq!(result.block, 51); - assert_eq!(result.bid.get_unchecked(usdc_id), 42_0000000); - assert_eq!(result.bid.len(), 1); - assert_eq!(result.lot.get_unchecked(underlying_0), 10_0000000); - assert_eq!(result.lot.get_unchecked(underlying_1), 2_5000000); - assert_eq!(result.lot.len(), 2); + let result = create_interest_auction_data(&e, &backstop_address, &vec![&e]); }); } @@ -269,16 +275,22 @@ mod tests { let bombadil = Address::generate(&e); let pool_address = create_pool(&e); - let (usdc_id, _) = testutils::create_usdc_token(&e, &pool_address, &bombadil); - let (backstop_address, _backstop_client) = testutils::create_backstop(&e); + let (usdc_id, usdc_client) = testutils::create_usdc_token(&e, &pool_address, &bombadil); + let (blnd_id, blnd_client) = testutils::create_blnd_token(&e, &pool_address, &bombadil); + + let (backstop_token_id, backstop_token_client) = + create_comet_lp_pool(&e, &bombadil, &blnd_id, &usdc_id); + let (backstop_address, backstop_client) = testutils::create_backstop(&e); testutils::setup_backstop( &e, &pool_address, &backstop_address, - &Address::generate(&e), + &backstop_token_id, &usdc_id, - &Address::generate(&e), + &blnd_id, ); + backstop_client.deposit(&bombadil, &pool_address, &(50 * SCALAR_7)); + backstop_client.update_tkn_val(); let (oracle_id, oracle_client) = testutils::create_mock_oracle(&e); let (underlying_0, _) = testutils::create_token_contract(&e, &bombadil); @@ -347,9 +359,13 @@ mod tests { e.as_contract(&pool_address, || { storage::set_pool_config(&e, &pool_config); - let result = create_interest_auction_data(&e, &backstop_address); + let result = create_interest_auction_data( + &e, + &backstop_address, + &vec![&e, underlying_0.clone(), underlying_1.clone()], + ); assert_eq!(result.block, 51); - assert_eq!(result.bid.get_unchecked(usdc_id), 420_0000000); + assert_eq!(result.bid.get_unchecked(backstop_token_id), 336_0000000); assert_eq!(result.bid.len(), 1); assert_eq!(result.lot.get_unchecked(underlying_0), 100_0000000); assert_eq!(result.lot.get_unchecked(underlying_1), 25_0000000); @@ -377,16 +393,23 @@ mod tests { let bombadil = Address::generate(&e); let pool_address = create_pool(&e); - let (usdc_id, _) = testutils::create_usdc_token(&e, &pool_address, &bombadil); - let (backstop_address, _backstop_client) = testutils::create_backstop(&e); + let (usdc_id, usdc_client) = testutils::create_usdc_token(&e, &pool_address, &bombadil); + let (blnd_id, blnd_client) = testutils::create_blnd_token(&e, &pool_address, &bombadil); + + let (backstop_token_id, backstop_token_client) = + create_comet_lp_pool(&e, &bombadil, &blnd_id, &usdc_id); + let (backstop_address, backstop_client) = testutils::create_backstop(&e); testutils::setup_backstop( &e, &pool_address, &backstop_address, - &Address::generate(&e), + &backstop_token_id, &usdc_id, - &Address::generate(&e), + &blnd_id, ); + backstop_client.deposit(&bombadil, &pool_address, &(50 * SCALAR_7)); + backstop_client.update_tkn_val(); + let (oracle_id, oracle_client) = testutils::create_mock_oracle(&e); let (underlying_0, _) = testutils::create_token_contract(&e, &bombadil); @@ -455,9 +478,18 @@ mod tests { e.as_contract(&pool_address, || { storage::set_pool_config(&e, &pool_config); - let result = create_interest_auction_data(&e, &backstop_address); + let result = create_interest_auction_data( + &e, + &backstop_address, + &vec![ + &e, + underlying_0.clone(), + underlying_1.clone(), + underlying_2.clone(), + ], + ); assert_eq!(result.block, 151); - assert_eq!(result.bid.get_unchecked(usdc_id), 420_0012936); + assert_eq!(result.bid.get_unchecked(backstop_token_id), 336_0010348); assert_eq!(result.bid.len(), 1); assert_eq!(result.lot.get_unchecked(underlying_0), 100_0000714); assert_eq!(result.lot.get_unchecked(underlying_1), 25_0000178); @@ -466,116 +498,132 @@ mod tests { }); } - #[test] - fn test_fill_interest_auction() { - let e = Env::default(); - e.mock_all_auths_allowing_non_root_auth(); - e.budget().reset_unlimited(); - - e.ledger().set(LedgerInfo { - timestamp: 12345, - protocol_version: 20, - sequence_number: 301, - network_id: Default::default(), - base_reserve: 10, - min_temp_entry_ttl: 10, - min_persistent_entry_ttl: 10, - max_entry_ttl: 2000000, - }); - - let bombadil = Address::generate(&e); - let samwise = Address::generate(&e); - - let pool_address = create_pool(&e); - - let (usdc_id, usdc_client) = testutils::create_usdc_token(&e, &pool_address, &bombadil); - let (backstop_address, _backstop_client) = testutils::create_backstop(&e); - testutils::setup_backstop( - &e, - &pool_address, - &backstop_address, - &Address::generate(&e), - &usdc_id, - &Address::generate(&e), - ); - - let (underlying_0, underlying_0_client) = testutils::create_token_contract(&e, &bombadil); - let (mut reserve_config_0, mut reserve_data_0) = testutils::default_reserve_meta(); - reserve_data_0.b_rate = 1_100_000_000; - reserve_data_0.b_supply = 200_000_0000000; - reserve_data_0.d_supply = 100_000_0000000; - reserve_data_0.last_time = 12345; - reserve_data_0.backstop_credit = 100_0000000; - reserve_config_0.index = 0; - testutils::create_reserve( - &e, - &pool_address, - &underlying_0, - &reserve_config_0, - &reserve_data_0, - ); - underlying_0_client.mint(&pool_address, &1_000_0000000); - - let (underlying_1, underlying_1_client) = testutils::create_token_contract(&e, &bombadil); - let (mut reserve_config_1, mut reserve_data_1) = testutils::default_reserve_meta(); - reserve_data_1.b_rate = 1_100_000_000; - reserve_data_0.b_supply = 10_000_0000000; - reserve_data_0.b_supply = 7_000_0000000; - reserve_data_1.last_time = 12345; - reserve_data_1.backstop_credit = 30_0000000; - reserve_config_1.index = 1; - testutils::create_reserve( - &e, - &pool_address, - &underlying_1, - &reserve_config_1, - &reserve_data_1, - ); - underlying_1_client.mint(&pool_address, &1_000_0000000); - - let pool_config = PoolConfig { - oracle: Address::generate(&e), - bstop_rate: 0_1000000, - status: 0, - max_positions: 4, - }; - let mut auction_data = AuctionData { - bid: map![&e, (usdc_id.clone(), 95_0000000)], - lot: map![ - &e, - (underlying_0.clone(), 100_0000000), - (underlying_1.clone(), 25_0000000) - ], - block: 51, - }; - usdc_client.mint(&samwise, &100_0000000); - e.as_contract(&pool_address, || { - e.mock_all_auths_allowing_non_root_auth(); - storage::set_auction( - &e, - &(AuctionType::InterestAuction as u32), - &backstop_address, - &auction_data, - ); - storage::set_pool_config(&e, &pool_config); - storage::set_backstop(&e, &backstop_address); - storage::set_usdc_token(&e, &usdc_id); - - let mut pool = Pool::load(&e); - fill_interest_auction(&e, &mut pool, &mut auction_data, &samwise); - pool.store_cached_reserves(&e); - - assert_eq!(usdc_client.balance(&samwise), 5_0000000); - assert_eq!(usdc_client.balance(&backstop_address), 95_0000000); - assert_eq!(underlying_0_client.balance(&samwise), 100_0000000); - assert_eq!(underlying_1_client.balance(&samwise), 25_0000000); - // verify only filled backstop credits get deducted from total - let reserve_0_data = storage::get_res_data(&e, &underlying_0); - assert_eq!(reserve_0_data.backstop_credit, 0); - let reserve_1_data = storage::get_res_data(&e, &underlying_1); - assert_eq!(reserve_1_data.backstop_credit, 5_0000000); - }); - } + // #[test] + // fn test_fill_interest_auction() { + // let e = Env::default(); + // e.mock_all_auths_allowing_non_root_auth(); + // e.budget().reset_unlimited(); + + // e.ledger().set(LedgerInfo { + // timestamp: 12345, + // protocol_version: 20, + // sequence_number: 301, + // network_id: Default::default(), + // base_reserve: 10, + // min_temp_entry_ttl: 10, + // min_persistent_entry_ttl: 10, + // max_entry_ttl: 2000000, + // }); + + // let bombadil = Address::generate(&e); + // let samwise = Address::generate(&e); + + // let pool_address = create_pool(&e); + + // let (usdc_id, usdc_client) = testutils::create_usdc_token(&e, &pool_address, &bombadil); + // let (blnd_id, blnd_client) = testutils::create_blnd_token(&e, &pool_address, &bombadil); + + // let (backstop_token_id, backstop_token_client) = + // create_comet_lp_pool(&e, &bombadil, &blnd_id, &usdc_id); + // blnd_client.mint(&samwise, &10_000_0000000); + // usdc_client.mint(&samwise, &250_0000000); + // let exp_ledger = e.ledger().sequence() + 100; + // blnd_client.approve(&bombadil, &backstop_token_id, &2_000_0000000, &exp_ledger); + // usdc_client.approve(&bombadil, &backstop_token_id, &2_000_0000000, &exp_ledger); + // backstop_token_client.join_pool( + // &(500 * SCALAR_7), + // &vec![&e, 10_000_0000000, 250_0000000], + // &samwise, + // ); + // let (backstop_address, backstop_client) = testutils::create_backstop(&e); + // testutils::setup_backstop( + // &e, + // &pool_address, + // &backstop_address, + // &backstop_token_id, + // &usdc_id, + // &blnd_id, + // ); + // backstop_client.deposit(&bombadil, &pool_address, &(50 * SCALAR_7)); + // backstop_client.update_tkn_val(); + + // let (underlying_0, underlying_0_client) = testutils::create_token_contract(&e, &bombadil); + // let (mut reserve_config_0, mut reserve_data_0) = testutils::default_reserve_meta(); + // reserve_data_0.b_rate = 1_100_000_000; + // reserve_data_0.b_supply = 200_000_0000000; + // reserve_data_0.d_supply = 100_000_0000000; + // reserve_data_0.last_time = 12345; + // reserve_data_0.backstop_credit = 100_0000000; + // reserve_config_0.index = 0; + // testutils::create_reserve( + // &e, + // &pool_address, + // &underlying_0, + // &reserve_config_0, + // &reserve_data_0, + // ); + // underlying_0_client.mint(&pool_address, &1_000_0000000); + + // let (underlying_1, underlying_1_client) = testutils::create_token_contract(&e, &bombadil); + // let (mut reserve_config_1, mut reserve_data_1) = testutils::default_reserve_meta(); + // reserve_data_1.b_rate = 1_100_000_000; + // reserve_data_0.b_supply = 10_000_0000000; + // reserve_data_0.b_supply = 7_000_0000000; + // reserve_data_1.last_time = 12345; + // reserve_data_1.backstop_credit = 30_0000000; + // reserve_config_1.index = 1; + // testutils::create_reserve( + // &e, + // &pool_address, + // &underlying_1, + // &reserve_config_1, + // &reserve_data_1, + // ); + // underlying_1_client.mint(&pool_address, &1_000_0000000); + + // let pool_config = PoolConfig { + // oracle: Address::generate(&e), + // bstop_rate: 0_1000000, + // status: 0, + // max_positions: 4, + // }; + // let mut auction_data = AuctionData { + // bid: map![&e, (usdc_id.clone(), 95_0000000)], + // lot: map![ + // &e, + // (underlying_0.clone(), 100_0000000), + // (underlying_1.clone(), 25_0000000) + // ], + // block: 51, + // }; + // usdc_client.mint(&samwise, &100_0000000); + // e.as_contract(&pool_address, || { + // e.mock_all_auths_allowing_non_root_auth(); + // storage::set_auction( + // &e, + // &(AuctionType::InterestAuction as u32), + // &backstop_address, + // &auction_data, + // ); + // storage::set_pool_config(&e, &pool_config); + // storage::set_backstop(&e, &backstop_address); + // storage::set_usdc_token(&e, &usdc_id); + + // let mut pool = Pool::load(&e); + // fill_interest_auction(&e, &mut pool, &mut auction_data, &samwise); + // pool.store_cached_reserves(&e); + + // assert_eq!(usdc_client.balance(&samwise), 5_0000000); + // assert_eq!(usdc_client.balance(&backstop_address), 95_0000000); + // assert_eq!(underlying_0_client.balance(&samwise), 100_0000000); + // assert_eq!(underlying_1_client.balance(&samwise), 25_0000000); + // // verify only filled backstop credits get deducted from total + // let reserve_0_data = storage::get_res_data(&e, &underlying_0); + // assert_eq!(reserve_0_data.backstop_credit, 0); + // let reserve_1_data = storage::get_res_data(&e, &underlying_1); + // assert_eq!(reserve_1_data.backstop_credit, 5_0000000); + // }); + // } #[test] #[should_panic(expected = "Error(Contract, #1200)")] diff --git a/pool/src/contract.rs b/pool/src/contract.rs index 7d22bc8b..515faab3 100644 --- a/pool/src/contract.rs +++ b/pool/src/contract.rs @@ -208,21 +208,28 @@ pub trait Pool { /// Fetch an auction from the ledger. Returns a quote based on the current block. /// /// ### Arguments - /// * `auction_type` - The type of auction + /// * `auction_type` - The type of auction, 0 for liquidation auction, 1 for bad debt auction, and 2 for interest auction /// * `user` - The Address involved in the auction /// /// ### Panics /// If the auction does not exist fn get_auction(e: Env, auction_type: u32, user: Address) -> AuctionData; - /// Creates a new auction + /// Creates a new bad debt auction + /// + /// + /// ### Panics + /// If the auction was unable to be created + fn new_bad_debt_auction(e: Env) -> AuctionData; + + /// Creates a new interest auction /// /// ### Arguments - /// * `auction_type` - The type of auction + /// * `assets` - The assets interest is being auctioned off for /// /// ### Panics /// If the auction was unable to be created - fn new_auction(e: Env, auction_type: u32) -> AuctionData; + fn new_interest_auction(e: Env, assets: Vec
) -> AuctionData; } #[contractimpl] @@ -401,14 +408,22 @@ impl Pool for PoolContract { storage::get_auction(&e, &auction_type, &user) } - fn new_auction(e: Env, auction_type: u32) -> AuctionData { + fn new_bad_debt_auction(e: Env) -> AuctionData { storage::extend_instance(&e); - let auction_data = auctions::create(&e, auction_type); + let auction_data = auctions::create_bad_debt_auction(&e); - e.events().publish( - (Symbol::new(&e, "new_auction"), auction_type), - auction_data.clone(), - ); + e.events() + .publish((Symbol::new(&e, "new_auction"), 1), auction_data.clone()); + + auction_data + } + + fn new_interest_auction(e: Env, assets: Vec
) -> AuctionData { + storage::extend_instance(&e); + let auction_data = auctions::create_interest_auction(&e, &assets); + + e.events() + .publish((Symbol::new(&e, "new_auction"), 2), auction_data.clone()); auction_data } diff --git a/pool/src/pool/status.rs b/pool/src/pool/status.rs index e4ac0c44..0a3b040b 100644 --- a/pool/src/pool/status.rs +++ b/pool/src/pool/status.rs @@ -50,13 +50,13 @@ pub fn execute_update_pool_status(e: &Env) -> u32 { // Admin status isn't set _ => { if pool_backstop_data.q4w_pct >= 0_6000000 { - // Q4w over 60% freezes the pool + // Q4w over 60% sets pool to Frozen pool_config.status = 5; } else if pool_backstop_data.q4w_pct >= 0_3000000 || !met_threshold { - // Q4w over 30% or being under threshold puts the pool on-ice + // Q4w over 30% sets pool to On-Ice pool_config.status = 3; } else { - // Backstop is healthy and the pool can be activated + // Backstop is healthy and the pool is set to Active pool_config.status = 1; } } @@ -101,7 +101,7 @@ pub fn execute_set_pool_status(e: &Env, pool_status: u32) { if pool_backstop_data.q4w_pct >= 0_7500000 { panic_with_error!(e, PoolError::StatusNotAllowed); } - // Admin On-Ice + // On-Ice pool_config.status = 3; } 4 => { diff --git a/pool/src/testutils.rs b/pool/src/testutils.rs index 48240298..b03d65f0 100644 --- a/pool/src/testutils.rs +++ b/pool/src/testutils.rs @@ -123,7 +123,8 @@ pub(crate) fn setup_backstop( let (pool_factory, mock_pool_factory_client) = create_mock_pool_factory(e); mock_pool_factory_client.set_pool(pool_address); let (emitter, _) = create_emitter(e, backstop_id, backstop_token, blnd_token); - BackstopClient::new(e, backstop_id).initialize( + let backstop_client: BackstopClient = BackstopClient::new(e, backstop_id); + backstop_client.initialize( backstop_token, &emitter, usdc_token, diff --git a/test-suites/src/test_fixture.rs b/test-suites/src/test_fixture.rs index 5504cc61..22dee63e 100644 --- a/test-suites/src/test_fixture.rs +++ b/test-suites/src/test_fixture.rs @@ -30,6 +30,10 @@ pub enum TokenIndex { WETH = 2, XLM = 3, STABLE = 4, + AQUA = 5, + TEST1 = 6, + TEST2 = 7, + TEST3 = 8, } pub struct PoolFixture<'a> { @@ -87,6 +91,10 @@ impl TestFixture<'_> { let (usdc_id, usdc_client) = create_stellar_token(&e, &bombadil); let (xlm_id, xlm_client) = create_stellar_token(&e, &bombadil); // TODO: make native let (stable_id, stable_client) = create_token(&e, &bombadil, 6, "STABLE"); + let (aqua_id, aqua_client) = create_token(&e, &bombadil, 7, "AQUA"); + let (test1_id, test1_client) = create_token(&e, &bombadil, 7, "TEST1"); + let (test2_id, test2_client) = create_token(&e, &bombadil, 7, "TEST2"); + let (test3_id, test3_client) = create_token(&e, &bombadil, 7, "TEST3"); // deploy Blend Protocol contracts let (backstop_id, backstop_client) = create_backstop(&e, wasm); @@ -132,7 +140,11 @@ impl TestFixture<'_> { Asset::Stellar(eth_id.clone()), Asset::Stellar(usdc_id), Asset::Stellar(xlm_id.clone()), - Asset::Stellar(stable_id.clone()) + Asset::Stellar(stable_id.clone()), + Asset::Stellar(aqua_id.clone()), + Asset::Stellar(test1_id.clone()), + Asset::Stellar(test2_id.clone()), + Asset::Stellar(test3_id.clone()), ], &7, &300, @@ -142,7 +154,11 @@ impl TestFixture<'_> { 2000_0000000, // eth 1_0000000, // usdc 0_1000000, // xlm - 1_0000000 // stable + 1_0000000, // stable + 0_0100000, // aqua + 0_0100000, // test1 + 0_0100000, // test2 + 0_0100000, // test3 ]); let fixture = TestFixture { @@ -161,6 +177,10 @@ impl TestFixture<'_> { eth_client, xlm_client, stable_client, + aqua_client, + test1_client, + test2_client, + test3_client, ], }; fixture.jump(7 * 24 * 60 * 60); diff --git a/test-suites/tests/test_liquidation.rs b/test-suites/tests/test_liquidation.rs index 24219ec5..67c1b4eb 100644 --- a/test-suites/tests/test_liquidation.rs +++ b/test-suites/tests/test_liquidation.rs @@ -1,6 +1,9 @@ #![cfg(test)] use cast::i128; -use pool::{PoolDataKey, Positions, Request, RequestType, ReserveConfig, ReserveData}; +use pool::{ + PoolDataKey, Positions, Request, RequestType, ReserveConfig, ReserveData, + ReserveEmissionMetadata, +}; use soroban_fixed_point_math::FixedPoint; use soroban_sdk::{ testutils::{Address as AddressTestTrait, Events}, @@ -9,6 +12,7 @@ use soroban_sdk::{ use test_suites::{ assertions::assert_approx_eq_abs, create_fixture_with_data, + pool::default_reserve_metadata, test_fixture::{TokenIndex, SCALAR_7}, }; @@ -153,8 +157,12 @@ fn test_liquidations() { } // Start an interest auction // type 2 is an interest auction - let auction_type: u32 = 2; - let auction_data = pool_fixture.pool.new_auction(&auction_type); + let auction_data = pool_fixture.pool.new_interest_auction(&vec![ + &fixture.env, + fixture.tokens[TokenIndex::STABLE].address.clone(), + fixture.tokens[TokenIndex::WETH].address.clone(), + fixture.tokens[TokenIndex::XLM].address.clone(), + ]); let stable_interest_lot_amount = auction_data .lot .get_unchecked(fixture.tokens[TokenIndex::STABLE].address.clone()); @@ -182,7 +190,7 @@ fn test_liquidations() { &fixture.env, ( pool_fixture.pool.address.clone(), - (Symbol::new(&fixture.env, "new_auction"), auction_type).into_val(&fixture.env), + (Symbol::new(&fixture.env, "new_auction"), 2).into_val(&fixture.env), auction_data.into_val(&fixture.env) ) ] @@ -548,7 +556,7 @@ fn test_liquidations() { // create a bad debt auction let auction_type: u32 = 1; - let bad_debt_auction_data = pool_fixture.pool.new_auction(&auction_type); + let bad_debt_auction_data = pool_fixture.pool.new_bad_debt_auction(); assert_eq!(bad_debt_auction_data.bid.len(), 2); assert_eq!(bad_debt_auction_data.lot.len(), 1); @@ -887,8 +895,7 @@ fn test_liquidations() { ); // Create bad debt auction - let auction_type: u32 = 1; - pool_fixture.pool.new_auction(&auction_type); + pool_fixture.pool.new_bad_debt_auction(); //fill bad debt auction fixture.jump_with_sequence(401 * 5); diff --git a/test-suites/tests/test_overflow_flag.rs b/test-suites/tests/test_overflow_flag.rs index 5c991b4d..08af44e7 100644 --- a/test-suites/tests/test_overflow_flag.rs +++ b/test-suites/tests/test_overflow_flag.rs @@ -8,24 +8,24 @@ use test_suites::{ #[test] #[should_panic(expected = "Error(WasmVm, InvalidAction)")] -fn test_backstop_donate_overflow_panics() { +fn test_pool_deposit_overflow_panics() { let fixture = create_fixture_with_data(true); let pool_fixture = &fixture.pools[0]; + let pool_balance = fixture.tokens[TokenIndex::STABLE].balance(&pool_fixture.pool.address); + fixture.tokens[TokenIndex::STABLE].burn(&pool_fixture.pool.address, &pool_balance); // Create a user let samwise = Address::generate(&fixture.env); + fixture.tokens[TokenIndex::STABLE].mint(&samwise, &(i128::MAX)); + let request = Request { + request_type: RequestType::Supply as u32, + address: fixture.tokens[TokenIndex::STABLE].address.clone(), + amount: i128::MAX - 10, + }; - fixture.tokens[TokenIndex::USDC].mint(&samwise, &(i128::MAX - 100)); - - // donate tokens - fixture - .backstop - .donate_usdc(&samwise, &pool_fixture.pool.address, &(i128::MAX - 100)); - fixture.tokens[TokenIndex::USDC].mint(&samwise, &(500)); - fixture.tokens[TokenIndex::USDC].burn(&fixture.backstop.address, &500); - fixture - .backstop - .donate_usdc(&samwise, &pool_fixture.pool.address, &201); + pool_fixture + .pool + .submit(&samwise, &samwise, &samwise, &vec![&fixture.env, request]); } // This test ensures that an accessible underflow in the auction flow cannot be hit due to the overflow-checks flag being set From bfe22b9995dedf97bc44692b8580c88ea19d9405 Mon Sep 17 00:00:00 2001 From: markuspluna <59978114+markuspluna@users.noreply.github.com> Date: Sat, 20 Jan 2024 18:28:23 +0300 Subject: [PATCH 2/3] fixed tests --- pool/src/auctions/auction.rs | 15 +- .../src/auctions/backstop_interest_auction.rs | 270 +++++++++--------- pool/src/contract.rs | 12 +- pool/src/pool/actions.rs | 40 ++- test-suites/tests/test_liquidation.rs | 17 +- 5 files changed, 188 insertions(+), 166 deletions(-) diff --git a/pool/src/auctions/auction.rs b/pool/src/auctions/auction.rs index cc5e6ba2..8ec87f85 100644 --- a/pool/src/auctions/auction.rs +++ b/pool/src/auctions/auction.rs @@ -274,7 +274,7 @@ mod tests { use crate::{ pool::Positions, storage::PoolConfig, - testutils::{self, create_pool}, + testutils::{self, create_comet_lp_pool, create_pool}, }; use super::*; @@ -441,15 +441,20 @@ mod tests { let pool_address = create_pool(&e); let (usdc_id, _) = testutils::create_usdc_token(&e, &pool_address, &bombadil); - let (backstop_address, _backstop_client) = testutils::create_backstop(&e); + let (blnd_id, _) = testutils::create_blnd_token(&e, &pool_address, &bombadil); + + let (backstop_token_id, _) = create_comet_lp_pool(&e, &bombadil, &blnd_id, &usdc_id); + let (backstop_address, backstop_client) = testutils::create_backstop(&e); testutils::setup_backstop( &e, &pool_address, &backstop_address, - &Address::generate(&e), - &Address::generate(&e), - &Address::generate(&e), + &backstop_token_id, + &usdc_id, + &blnd_id, ); + backstop_client.deposit(&bombadil, &pool_address, &(50 * SCALAR_7)); + backstop_client.update_tkn_val(); let (oracle_id, oracle_client) = testutils::create_mock_oracle(&e); let (underlying_0, _) = testutils::create_token_contract(&e, &bombadil); diff --git a/pool/src/auctions/backstop_interest_auction.rs b/pool/src/auctions/backstop_interest_auction.rs index f0ea8601..f21b709f 100644 --- a/pool/src/auctions/backstop_interest_auction.rs +++ b/pool/src/auctions/backstop_interest_auction.rs @@ -251,7 +251,7 @@ mod tests { e.as_contract(&pool_address, || { storage::set_pool_config(&e, &pool_config); - let result = create_interest_auction_data(&e, &backstop_address, &vec![&e]); + create_interest_auction_data(&e, &backstop_address, &vec![&e]); }); } @@ -275,11 +275,10 @@ mod tests { let bombadil = Address::generate(&e); let pool_address = create_pool(&e); - let (usdc_id, usdc_client) = testutils::create_usdc_token(&e, &pool_address, &bombadil); - let (blnd_id, blnd_client) = testutils::create_blnd_token(&e, &pool_address, &bombadil); + let (usdc_id, _) = testutils::create_usdc_token(&e, &pool_address, &bombadil); + let (blnd_id, _) = testutils::create_blnd_token(&e, &pool_address, &bombadil); - let (backstop_token_id, backstop_token_client) = - create_comet_lp_pool(&e, &bombadil, &blnd_id, &usdc_id); + let (backstop_token_id, _) = create_comet_lp_pool(&e, &bombadil, &blnd_id, &usdc_id); let (backstop_address, backstop_client) = testutils::create_backstop(&e); testutils::setup_backstop( &e, @@ -393,11 +392,10 @@ mod tests { let bombadil = Address::generate(&e); let pool_address = create_pool(&e); - let (usdc_id, usdc_client) = testutils::create_usdc_token(&e, &pool_address, &bombadil); - let (blnd_id, blnd_client) = testutils::create_blnd_token(&e, &pool_address, &bombadil); + let (usdc_id, _) = testutils::create_usdc_token(&e, &pool_address, &bombadil); + let (blnd_id, _) = testutils::create_blnd_token(&e, &pool_address, &bombadil); - let (backstop_token_id, backstop_token_client) = - create_comet_lp_pool(&e, &bombadil, &blnd_id, &usdc_id); + let (backstop_token_id, _) = create_comet_lp_pool(&e, &bombadil, &blnd_id, &usdc_id); let (backstop_address, backstop_client) = testutils::create_backstop(&e); testutils::setup_backstop( &e, @@ -498,132 +496,134 @@ mod tests { }); } - // #[test] - // fn test_fill_interest_auction() { - // let e = Env::default(); - // e.mock_all_auths_allowing_non_root_auth(); - // e.budget().reset_unlimited(); - - // e.ledger().set(LedgerInfo { - // timestamp: 12345, - // protocol_version: 20, - // sequence_number: 301, - // network_id: Default::default(), - // base_reserve: 10, - // min_temp_entry_ttl: 10, - // min_persistent_entry_ttl: 10, - // max_entry_ttl: 2000000, - // }); - - // let bombadil = Address::generate(&e); - // let samwise = Address::generate(&e); - - // let pool_address = create_pool(&e); - - // let (usdc_id, usdc_client) = testutils::create_usdc_token(&e, &pool_address, &bombadil); - // let (blnd_id, blnd_client) = testutils::create_blnd_token(&e, &pool_address, &bombadil); - - // let (backstop_token_id, backstop_token_client) = - // create_comet_lp_pool(&e, &bombadil, &blnd_id, &usdc_id); - // blnd_client.mint(&samwise, &10_000_0000000); - // usdc_client.mint(&samwise, &250_0000000); - // let exp_ledger = e.ledger().sequence() + 100; - // blnd_client.approve(&bombadil, &backstop_token_id, &2_000_0000000, &exp_ledger); - // usdc_client.approve(&bombadil, &backstop_token_id, &2_000_0000000, &exp_ledger); - // backstop_token_client.join_pool( - // &(500 * SCALAR_7), - // &vec![&e, 10_000_0000000, 250_0000000], - // &samwise, - // ); - // let (backstop_address, backstop_client) = testutils::create_backstop(&e); - // testutils::setup_backstop( - // &e, - // &pool_address, - // &backstop_address, - // &backstop_token_id, - // &usdc_id, - // &blnd_id, - // ); - // backstop_client.deposit(&bombadil, &pool_address, &(50 * SCALAR_7)); - // backstop_client.update_tkn_val(); - - // let (underlying_0, underlying_0_client) = testutils::create_token_contract(&e, &bombadil); - // let (mut reserve_config_0, mut reserve_data_0) = testutils::default_reserve_meta(); - // reserve_data_0.b_rate = 1_100_000_000; - // reserve_data_0.b_supply = 200_000_0000000; - // reserve_data_0.d_supply = 100_000_0000000; - // reserve_data_0.last_time = 12345; - // reserve_data_0.backstop_credit = 100_0000000; - // reserve_config_0.index = 0; - // testutils::create_reserve( - // &e, - // &pool_address, - // &underlying_0, - // &reserve_config_0, - // &reserve_data_0, - // ); - // underlying_0_client.mint(&pool_address, &1_000_0000000); - - // let (underlying_1, underlying_1_client) = testutils::create_token_contract(&e, &bombadil); - // let (mut reserve_config_1, mut reserve_data_1) = testutils::default_reserve_meta(); - // reserve_data_1.b_rate = 1_100_000_000; - // reserve_data_0.b_supply = 10_000_0000000; - // reserve_data_0.b_supply = 7_000_0000000; - // reserve_data_1.last_time = 12345; - // reserve_data_1.backstop_credit = 30_0000000; - // reserve_config_1.index = 1; - // testutils::create_reserve( - // &e, - // &pool_address, - // &underlying_1, - // &reserve_config_1, - // &reserve_data_1, - // ); - // underlying_1_client.mint(&pool_address, &1_000_0000000); - - // let pool_config = PoolConfig { - // oracle: Address::generate(&e), - // bstop_rate: 0_1000000, - // status: 0, - // max_positions: 4, - // }; - // let mut auction_data = AuctionData { - // bid: map![&e, (usdc_id.clone(), 95_0000000)], - // lot: map![ - // &e, - // (underlying_0.clone(), 100_0000000), - // (underlying_1.clone(), 25_0000000) - // ], - // block: 51, - // }; - // usdc_client.mint(&samwise, &100_0000000); - // e.as_contract(&pool_address, || { - // e.mock_all_auths_allowing_non_root_auth(); - // storage::set_auction( - // &e, - // &(AuctionType::InterestAuction as u32), - // &backstop_address, - // &auction_data, - // ); - // storage::set_pool_config(&e, &pool_config); - // storage::set_backstop(&e, &backstop_address); - // storage::set_usdc_token(&e, &usdc_id); - - // let mut pool = Pool::load(&e); - // fill_interest_auction(&e, &mut pool, &mut auction_data, &samwise); - // pool.store_cached_reserves(&e); - - // assert_eq!(usdc_client.balance(&samwise), 5_0000000); - // assert_eq!(usdc_client.balance(&backstop_address), 95_0000000); - // assert_eq!(underlying_0_client.balance(&samwise), 100_0000000); - // assert_eq!(underlying_1_client.balance(&samwise), 25_0000000); - // // verify only filled backstop credits get deducted from total - // let reserve_0_data = storage::get_res_data(&e, &underlying_0); - // assert_eq!(reserve_0_data.backstop_credit, 0); - // let reserve_1_data = storage::get_res_data(&e, &underlying_1); - // assert_eq!(reserve_1_data.backstop_credit, 5_0000000); - // }); - // } + #[test] + fn test_fill_interest_auction() { + let e = Env::default(); + e.mock_all_auths_allowing_non_root_auth(); + e.budget().reset_unlimited(); + + e.ledger().set(LedgerInfo { + timestamp: 12345, + protocol_version: 20, + sequence_number: 301, + network_id: Default::default(), + base_reserve: 10, + min_temp_entry_ttl: 10, + min_persistent_entry_ttl: 10, + max_entry_ttl: 2000000, + }); + + let bombadil = Address::generate(&e); + let samwise = Address::generate(&e); + + let pool_address = create_pool(&e); + + let (usdc_id, usdc_client) = testutils::create_usdc_token(&e, &pool_address, &bombadil); + let (blnd_id, blnd_client) = testutils::create_blnd_token(&e, &pool_address, &bombadil); + + let (backstop_token_id, backstop_token_client) = + create_comet_lp_pool(&e, &bombadil, &blnd_id, &usdc_id); + blnd_client.mint(&samwise, &10_000_0000000); + usdc_client.mint(&samwise, &250_0000000); + let exp_ledger = e.ledger().sequence() + 100; + blnd_client.approve(&bombadil, &backstop_token_id, &2_000_0000000, &exp_ledger); + usdc_client.approve(&bombadil, &backstop_token_id, &2_000_0000000, &exp_ledger); + backstop_token_client.join_pool( + &(100 * SCALAR_7), + &vec![&e, 10_000_0000000, 250_0000000], + &samwise, + ); + let (backstop_address, backstop_client) = testutils::create_backstop(&e); + testutils::setup_backstop( + &e, + &pool_address, + &backstop_address, + &backstop_token_id, + &usdc_id, + &blnd_id, + ); + backstop_client.deposit(&bombadil, &pool_address, &(50 * SCALAR_7)); + backstop_client.update_tkn_val(); + + let (underlying_0, underlying_0_client) = testutils::create_token_contract(&e, &bombadil); + let (mut reserve_config_0, mut reserve_data_0) = testutils::default_reserve_meta(); + reserve_data_0.b_rate = 1_100_000_000; + reserve_data_0.b_supply = 200_000_0000000; + reserve_data_0.d_supply = 100_000_0000000; + reserve_data_0.last_time = 12345; + reserve_data_0.backstop_credit = 100_0000000; + reserve_config_0.index = 0; + testutils::create_reserve( + &e, + &pool_address, + &underlying_0, + &reserve_config_0, + &reserve_data_0, + ); + underlying_0_client.mint(&pool_address, &1_000_0000000); + + let (underlying_1, underlying_1_client) = testutils::create_token_contract(&e, &bombadil); + let (mut reserve_config_1, mut reserve_data_1) = testutils::default_reserve_meta(); + reserve_data_1.b_rate = 1_100_000_000; + reserve_data_0.b_supply = 10_000_0000000; + reserve_data_0.b_supply = 7_000_0000000; + reserve_data_1.last_time = 12345; + reserve_data_1.backstop_credit = 30_0000000; + reserve_config_1.index = 1; + testutils::create_reserve( + &e, + &pool_address, + &underlying_1, + &reserve_config_1, + &reserve_data_1, + ); + underlying_1_client.mint(&pool_address, &1_000_0000000); + + let pool_config = PoolConfig { + oracle: Address::generate(&e), + bstop_rate: 0_1000000, + status: 0, + max_positions: 4, + }; + let mut auction_data = AuctionData { + bid: map![&e, (backstop_token_id.clone(), 75_0000000)], + lot: map![ + &e, + (underlying_0.clone(), 100_0000000), + (underlying_1.clone(), 25_0000000) + ], + block: 51, + }; + e.as_contract(&pool_address, || { + e.mock_all_auths_allowing_non_root_auth(); + storage::set_auction( + &e, + &(AuctionType::InterestAuction as u32), + &backstop_address, + &auction_data, + ); + storage::set_pool_config(&e, &pool_config); + storage::set_backstop(&e, &backstop_address); + storage::set_usdc_token(&e, &usdc_id); + let mut pool = Pool::load(&e); + let backstop_token_balance_pre_fill = backstop_token_client.balance(&backstop_address); + fill_interest_auction(&e, &mut pool, &mut auction_data, &samwise); + pool.store_cached_reserves(&e); + + assert_eq!(backstop_token_client.balance(&samwise), 25_0000000); + assert_eq!( + backstop_token_client.balance(&backstop_address), + backstop_token_balance_pre_fill + 75_0000000 + ); + assert_eq!(underlying_0_client.balance(&samwise), 100_0000000); + assert_eq!(underlying_1_client.balance(&samwise), 25_0000000); + // verify only filled backstop credits get deducted from total + let reserve_0_data = storage::get_res_data(&e, &underlying_0); + assert_eq!(reserve_0_data.backstop_credit, 0); + let reserve_1_data = storage::get_res_data(&e, &underlying_1); + assert_eq!(reserve_1_data.backstop_credit, 5_0000000); + }); + } #[test] #[should_panic(expected = "Error(Contract, #1200)")] diff --git a/pool/src/contract.rs b/pool/src/contract.rs index 515faab3..ab9761c4 100644 --- a/pool/src/contract.rs +++ b/pool/src/contract.rs @@ -412,8 +412,10 @@ impl Pool for PoolContract { storage::extend_instance(&e); let auction_data = auctions::create_bad_debt_auction(&e); - e.events() - .publish((Symbol::new(&e, "new_auction"), 1), auction_data.clone()); + e.events().publish( + (Symbol::new(&e, "new_auction"), 1 as u32), + auction_data.clone(), + ); auction_data } @@ -422,8 +424,10 @@ impl Pool for PoolContract { storage::extend_instance(&e); let auction_data = auctions::create_interest_auction(&e, &assets); - e.events() - .publish((Symbol::new(&e, "new_auction"), 2), auction_data.clone()); + e.events().publish( + (Symbol::new(&e, "new_auction"), 2 as u32), + auction_data.clone(), + ); auction_data } diff --git a/pool/src/pool/actions.rs b/pool/src/pool/actions.rs index 0f60cce7..4bafadb0 100644 --- a/pool/src/pool/actions.rs +++ b/pool/src/pool/actions.rs @@ -320,8 +320,9 @@ pub fn build_actions_from_request( mod tests { use crate::{ + constants::SCALAR_7, storage::{self, PoolConfig}, - testutils::{self, create_pool}, + testutils::{self, create_comet_lp_pool, create_pool}, AuctionData, AuctionType, Positions, }; @@ -1348,7 +1349,7 @@ mod tests { e.ledger().set(LedgerInfo { timestamp: 12345, protocol_version: 20, - sequence_number: 51 + 200, + sequence_number: 51 + 250, network_id: Default::default(), base_reserve: 10, min_temp_entry_ttl: 10, @@ -1361,15 +1362,31 @@ mod tests { let pool_address = create_pool(&e); let (usdc_id, usdc_client) = testutils::create_usdc_token(&e, &pool_address, &bombadil); - let (backstop_address, _backstop_client) = testutils::create_backstop(&e); + let (blnd_id, blnd_client) = testutils::create_blnd_token(&e, &pool_address, &bombadil); + + let (backstop_token_id, backstop_token_client) = + create_comet_lp_pool(&e, &bombadil, &blnd_id, &usdc_id); + let (backstop_address, backstop_client) = testutils::create_backstop(&e); + blnd_client.mint(&samwise, &10_000_0000000); + usdc_client.mint(&samwise, &250_0000000); + let exp_ledger = e.ledger().sequence() + 100; + blnd_client.approve(&bombadil, &backstop_token_id, &2_000_0000000, &exp_ledger); + usdc_client.approve(&bombadil, &backstop_token_id, &2_000_0000000, &exp_ledger); + backstop_token_client.join_pool( + &(100 * SCALAR_7), + &vec![&e, 10_000_0000000, 250_0000000], + &samwise, + ); testutils::setup_backstop( &e, &pool_address, &backstop_address, - &Address::generate(&e), + &backstop_token_id, &usdc_id, - &Address::generate(&e), + &blnd_id, ); + backstop_client.deposit(&bombadil, &pool_address, &(50 * SCALAR_7)); + backstop_client.update_tkn_val(); let (underlying_0, underlying_0_client) = testutils::create_token_contract(&e, &bombadil); let (mut reserve_config_0, mut reserve_data_0) = testutils::default_reserve_meta(); @@ -1420,7 +1437,7 @@ mod tests { max_positions: 2, }; let auction_data = AuctionData { - bid: map![&e, (usdc_id.clone(), 952_0000000)], + bid: map![&e, (backstop_token_id.clone(), 100_0000000)], lot: map![ &e, (underlying_0.clone(), 100_0000000), @@ -1428,7 +1445,6 @@ mod tests { ], block: 51, }; - usdc_client.mint(&samwise, &952_0000000); e.as_contract(&pool_address, || { e.mock_all_auths_allowing_non_root_auth(); @@ -1439,6 +1455,7 @@ mod tests { &backstop_address, &auction_data, ); + storage::set_backstop(&e, &backstop_address); let mut pool = Pool::load(&e); @@ -1450,14 +1467,17 @@ mod tests { amount: 100, }, ]; + let pre_fill_backstop_token_balance = backstop_token_client.balance(&backstop_address); let (actions, _, health_check) = build_actions_from_request(&e, &mut pool, &samwise, requests); - assert_eq!(usdc_client.balance(&samwise), 0); - assert_eq!(usdc_client.balance(&backstop_address), 952_0000000); + assert_eq!(backstop_token_client.balance(&samwise), 25_0000000); + assert_eq!( + backstop_token_client.balance(&backstop_address), + pre_fill_backstop_token_balance + 75_0000000 + ); assert_eq!(underlying_0_client.balance(&samwise), 100_0000000); assert_eq!(underlying_1_client.balance(&samwise), 25_0000000); - assert_eq!(usdc_client.balance(&samwise), 0); assert_eq!(health_check, false); assert_eq!( storage::has_auction( diff --git a/test-suites/tests/test_liquidation.rs b/test-suites/tests/test_liquidation.rs index 67c1b4eb..975a2b5a 100644 --- a/test-suites/tests/test_liquidation.rs +++ b/test-suites/tests/test_liquidation.rs @@ -1,9 +1,6 @@ #![cfg(test)] use cast::i128; -use pool::{ - PoolDataKey, Positions, Request, RequestType, ReserveConfig, ReserveData, - ReserveEmissionMetadata, -}; +use pool::{PoolDataKey, Positions, Request, RequestType, ReserveConfig, ReserveData}; use soroban_fixed_point_math::FixedPoint; use soroban_sdk::{ testutils::{Address as AddressTestTrait, Events}, @@ -12,7 +9,6 @@ use soroban_sdk::{ use test_suites::{ assertions::assert_approx_eq_abs, create_fixture_with_data, - pool::default_reserve_metadata, test_fixture::{TokenIndex, SCALAR_7}, }; @@ -175,11 +171,9 @@ fn test_liquidations() { .lot .get_unchecked(fixture.tokens[TokenIndex::WETH].address.clone()); assert_approx_eq_abs(weth_interest_lot_amount, 0_002671545, 5000); - let usdc_donate_bid_amount = auction_data - .bid - .get_unchecked(fixture.tokens[TokenIndex::USDC].address.clone()); + let lp_donate_bid_amount = auction_data.bid.get_unchecked(fixture.lp.address.clone()); //NOTE: bid STABLE amount is seven decimals whereas reserve(and lot) STABLE has 6 decomals - assert_approx_eq_abs(usdc_donate_bid_amount, 392_1769961, SCALAR_7); + assert_approx_eq_abs(lp_donate_bid_amount, 313_7415968, SCALAR_7); assert_eq!(auction_data.block, 151); let liq_pct = 30; let events = fixture.env.events().all(); @@ -190,7 +184,7 @@ fn test_liquidations() { &fixture.env, ( pool_fixture.pool.address.clone(), - (Symbol::new(&fixture.env, "new_auction"), 2).into_val(&fixture.env), + (Symbol::new(&fixture.env, "new_auction"), 2 as u32).into_val(&fixture.env), auction_data.into_val(&fixture.env) ) ] @@ -199,7 +193,6 @@ fn test_liquidations() { let auction_data = pool_fixture .pool .new_liquidation_auction(&samwise, &liq_pct); - let usdc_bid_amount = auction_data .bid .get_unchecked(fixture.tokens[TokenIndex::STABLE].address.clone()); @@ -780,7 +773,7 @@ fn test_liquidations() { .withdraw(&frodo, &pool_fixture.pool.address, &original_deposit); assert_approx_eq_abs( fixture.lp.balance(&frodo) - pre_withdraw_frodo_bstp, - original_deposit - 717_1043530 - 4302_6261190, + original_deposit - 717_1043530 - 4302_6261190 + 313_7415968, SCALAR_7, ); fixture From da49e306b01c6c9cdadf4c8931a70fdbbfa94ea5 Mon Sep 17 00:00:00 2001 From: markuspluna <59978114+markuspluna@users.noreply.github.com> Date: Mon, 22 Jan 2024 14:39:22 +0300 Subject: [PATCH 3/3] test_cleanup --- .../src/auctions/backstop_interest_auction.rs | 24 +++++++++++++++++++ test-suites/src/test_fixture.rs | 20 ---------------- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/pool/src/auctions/backstop_interest_auction.rs b/pool/src/auctions/backstop_interest_auction.rs index f21b709f..d8ea7f11 100644 --- a/pool/src/auctions/backstop_interest_auction.rs +++ b/pool/src/auctions/backstop_interest_auction.rs @@ -153,6 +153,30 @@ mod tests { }); } + #[test] + #[should_panic] + fn test_create_interest_auction_no_reserve() { + let e = Env::default(); + + let pool_address = create_pool(&e); + let backstop_address = Address::generate(&e); + + e.ledger().set(LedgerInfo { + timestamp: 12345, + protocol_version: 20, + sequence_number: 100, + network_id: Default::default(), + base_reserve: 10, + min_temp_entry_ttl: 10, + min_persistent_entry_ttl: 10, + max_entry_ttl: 2000000, + }); + + e.as_contract(&pool_address, || { + create_interest_auction_data(&e, &backstop_address, &vec![&e, Address::generate(&e)]); + }); + } + #[test] #[should_panic(expected = "Error(Contract, #1215)")] fn test_create_interest_auction_under_threshold() { diff --git a/test-suites/src/test_fixture.rs b/test-suites/src/test_fixture.rs index 22dee63e..8f92c449 100644 --- a/test-suites/src/test_fixture.rs +++ b/test-suites/src/test_fixture.rs @@ -30,10 +30,6 @@ pub enum TokenIndex { WETH = 2, XLM = 3, STABLE = 4, - AQUA = 5, - TEST1 = 6, - TEST2 = 7, - TEST3 = 8, } pub struct PoolFixture<'a> { @@ -91,10 +87,6 @@ impl TestFixture<'_> { let (usdc_id, usdc_client) = create_stellar_token(&e, &bombadil); let (xlm_id, xlm_client) = create_stellar_token(&e, &bombadil); // TODO: make native let (stable_id, stable_client) = create_token(&e, &bombadil, 6, "STABLE"); - let (aqua_id, aqua_client) = create_token(&e, &bombadil, 7, "AQUA"); - let (test1_id, test1_client) = create_token(&e, &bombadil, 7, "TEST1"); - let (test2_id, test2_client) = create_token(&e, &bombadil, 7, "TEST2"); - let (test3_id, test3_client) = create_token(&e, &bombadil, 7, "TEST3"); // deploy Blend Protocol contracts let (backstop_id, backstop_client) = create_backstop(&e, wasm); @@ -141,10 +133,6 @@ impl TestFixture<'_> { Asset::Stellar(usdc_id), Asset::Stellar(xlm_id.clone()), Asset::Stellar(stable_id.clone()), - Asset::Stellar(aqua_id.clone()), - Asset::Stellar(test1_id.clone()), - Asset::Stellar(test2_id.clone()), - Asset::Stellar(test3_id.clone()), ], &7, &300, @@ -155,10 +143,6 @@ impl TestFixture<'_> { 1_0000000, // usdc 0_1000000, // xlm 1_0000000, // stable - 0_0100000, // aqua - 0_0100000, // test1 - 0_0100000, // test2 - 0_0100000, // test3 ]); let fixture = TestFixture { @@ -177,10 +161,6 @@ impl TestFixture<'_> { eth_client, xlm_client, stable_client, - aqua_client, - test1_client, - test2_client, - test3_client, ], }; fixture.jump(7 * 24 * 60 * 60);