From 73e070c2d139382ed15b6a09460096f491f02f2d Mon Sep 17 00:00:00 2001 From: Vid Kersic Date: Wed, 23 Oct 2024 10:36:16 +0200 Subject: [PATCH 1/8] fix: calculations with collateral asset and base asset decimals --- contracts/market/src/main.sw | 23 +++++++++-------------- scripts/README.md | 4 ---- scripts/src/activate_market.rs | 5 ----- scripts/src/update_collateral_assets.rs | 5 ----- 4 files changed, 9 insertions(+), 28 deletions(-) diff --git a/contracts/market/src/main.sw b/contracts/market/src/main.sw index e62b3e5f..9d53215e 100644 --- a/contracts/market/src/main.sw +++ b/contracts/market/src/main.sw @@ -701,7 +701,6 @@ impl Market for Contract { let len = storage.collateral_configurations_keys.len(); let market_configuration = storage.market_configuration.read(); - while index < len { let collateral_configuration = storage.collateral_configurations.get(storage.collateral_configurations_keys.get(index).unwrap().read()).read(); @@ -714,13 +713,13 @@ impl Market for Contract { let price = get_price_internal(collateral_configuration.price_feed_id, PricePosition::LowerBound); // decimals: price.exponent let price_exponent = price.exponent; + let price_scale = u256::from(10_u64).pow(price.exponent); let price = u256::from(price.price); // decimals: price.exponent let amount = balance * collateral_configuration.borrow_collateral_factor / FACTOR_SCALE_18; // decimals: collateral_configuration.decimals - let scale = u256::from(10_u64).pow( - collateral_configuration.decimals + price_exponent - market_configuration.base_token_decimals, - ); + let collateral_scale = u256::from(10_u64).pow(collateral_configuration.decimals); + let base_asset_scale = u256::from(10_u64).pow(market_configuration.base_token_decimals); - borrow_limit += amount * price / scale; // decimals: base_token_decimals + borrow_limit += amount * price * base_asset_scale / collateral_scale / price_scale; // decimals: base_token_decimals index += 1; }; @@ -876,7 +875,7 @@ impl Market for Contract { /// # Number of Storage Accesses /// * Reads: `5` #[storage(read)] - fn collateral_value_to_sell(asset_id: AssetId, collateral_amount: u64) -> u64 { // decimals: base_token_decimals + fn collateral_value_to_sell(asset_id: AssetId, collateral_amount: u64) -> u64 { // decimals: collateral_asset.decimals let collateral_configuration = storage.collateral_configurations.get(asset_id).read(); let market_configuration = storage.market_configuration.read(); @@ -891,15 +890,11 @@ impl Market for Contract { let base_price = get_price_internal(market_configuration.base_token_price_feed_id, PricePosition::Middle); // decimals: base_price.exponent let base_price_scale = u256::from(10_u64).pow(base_price.exponent); let base_price = u256::from(base_price.price); // decimals: base_price.exponent - let scale = u256::from(10_u64).pow( - collateral_configuration - .decimals - storage - .market_configuration - .read() - .base_token_decimals, - ); + let collateral_scale = u256::from(10_u64).pow(collateral_configuration.decimals); + let base_asset_scale = u256::from(10_u64).pow(market_configuration.base_token_decimals); - let collateral_value = asset_price_discounted * collateral_amount.into() * base_price_scale / asset_price_scale / base_price / scale; + let asset_discounted = asset_price_discounted * collateral_amount.into() / asset_price_scale; // decimals: collateral_asset.decimals + let collateral_value = asset_discounted * base_asset_scale * base_price_scale / base_price / collateral_scale; // Native assets are in u64 >::try_from(collateral_value).unwrap() diff --git a/scripts/README.md b/scripts/README.md index 0b2475bc..e12ac7b3 100644 --- a/scripts/README.md +++ b/scripts/README.md @@ -39,8 +39,6 @@ This script will activate the contract - setup the market configuration, owner o cargo run --bin activate_market -- --config-path ./configs/testnet_usdc_config.json ``` -**Note:** Make sure the base asset decimals is strictly smaller than collateral asset decimals (for each collateral asset). - ### Update collateral assets This script will update the collateral asset configuration (add new collateral assets, pause collateral assets, unpause collateral assets, update collateral asset configuration ...). @@ -49,8 +47,6 @@ This script will update the collateral asset configuration (add new collateral a cargo run --bin update_collateral_assets -- --config-path ./configs/testnet_usdc_config.json ``` -**Note:** Make sure the base asset decimals is strictly smaller than collateral asset decimals (for each collateral asset). - ### Upgrade market contract When you want to upgrade the market contract, make the changes to the contract, build it, and use the deploy command below. You also need to set the addres of the proxy in the `Forc.toml` in the `../contracts/market` folder. Make sure the address is written in property `address` within the `[proxy]` section. diff --git a/scripts/src/activate_market.rs b/scripts/src/activate_market.rs index 27006358..f2f49cc9 100644 --- a/scripts/src/activate_market.rs +++ b/scripts/src/activate_market.rs @@ -60,11 +60,6 @@ async fn main() -> anyhow::Result<()> { println!("Market configuration: {:#?}", market_config); - // verify explicitly assets decimals - for collateral_asset in &market_config.collateral_assets { - assert!(collateral_asset.decimals > market_config.base_asset.decimals); - } - if !get_yes_no_input("Do you want to activate market with the config above? (yes/no): ") { return Ok(()); } diff --git a/scripts/src/update_collateral_assets.rs b/scripts/src/update_collateral_assets.rs index ad2fb69c..c49215bd 100644 --- a/scripts/src/update_collateral_assets.rs +++ b/scripts/src/update_collateral_assets.rs @@ -58,11 +58,6 @@ async fn main() -> anyhow::Result<()> { let market_config = read_market_config(&args.config_path)?; - // verify explicitly assets decimals - for collateral_asset in &market_config.collateral_assets { - assert!(collateral_asset.decimals >= market_config.base_asset.decimals); - } - // get current collateral assets configurations let collateral_asset_configurations = market_instance .methods() From ed21111f856a67bb96cddd792034e1f2889a7029 Mon Sep 17 00:00:00 2001 From: Vid Kersic Date: Wed, 30 Oct 2024 18:10:31 +0100 Subject: [PATCH 2/8] wip: eth base asset test --- .../tests/local_tests/main_test_eth_base.rs | 608 ++++++++++++++++++ .../market/tests/local_tests/main_test_uni.rs | 4 +- .../main_test_uni_no_debug_mode.rs | 4 +- .../tests/local_tests/main_test_usdt.rs | 4 +- contracts/market/tests/local_tests/mod.rs | 1 + .../scenarios/collateral_borrow.rs | 6 +- .../local_tests/scenarios/configuration.rs | 6 +- .../local_tests/scenarios/liquidation.rs | 8 +- .../multicall_absorb_buy_collateral.rs | 4 +- .../scenarios/multicall_withdraw_supply.rs | 4 +- .../scenarios/negative_reserves.rs | 4 +- .../tests/local_tests/scenarios/owner.rs | 4 +- .../tests/local_tests/scenarios/pause.rs | 3 +- .../local_tests/scenarios/price_changes.rs | 4 +- .../tests/local_tests/scenarios/reserves.rs | 6 +- .../tests/local_tests/scenarios/rewards.rs | 4 +- .../local_tests/scenarios/supply_withdraw.rs | 4 +- .../local_tests/scenarios/utilization.rs | 4 +- contracts/market/tests/utils/mod.rs | 28 +- libs/market_sdk/src/market_utils.rs | 69 +- 20 files changed, 708 insertions(+), 71 deletions(-) create mode 100644 contracts/market/tests/local_tests/main_test_eth_base.rs diff --git a/contracts/market/tests/local_tests/main_test_eth_base.rs b/contracts/market/tests/local_tests/main_test_eth_base.rs new file mode 100644 index 00000000..1548b795 --- /dev/null +++ b/contracts/market/tests/local_tests/main_test_eth_base.rs @@ -0,0 +1,608 @@ +use crate::utils::{print_case_title, setup, TestBaseAsset, TestData}; +use chrono::Utc; +use fuels::{ + prelude::ViewOnlyAccount, + programs::{ + calls::{CallHandler, CallParameters}, + responses::CallResponse, + }, + types::{transaction::TxPolicies, transaction_builders::VariableOutputPolicy}, +}; +use market::PriceDataUpdate; +use market_sdk::{convert_i256_to_u64, is_i256_negative, parse_units}; + +// Multiplies all values by this number +// It is necessary in order to test how the protocol works with large amounts +const AMOUNT_COEFFICIENT: u64 = 10u64.pow(0); + +#[tokio::test] +async fn main_test() { + let scale_6 = 10u64.pow(6) as f64; + let scale_9 = 10u64.pow(9) as f64; + + let TestData { + wallets, + alice, + alice_account, + bob, + bob_account, + chad, + chad_account, + usdc_contract, + usdc, + market, + uni, + uni_contract, + oracle, + price_feed_ids, + assets, + publish_time, + prices, + eth, + usdt, + usdt_contract, + .. + } = setup(None, TestBaseAsset::ETH).await; + + let price_data_update = PriceDataUpdate { + update_fee: 1, + price_feed_ids, + publish_times: vec![publish_time; assets.len()], + update_data: oracle.create_update_data(&prices).await.unwrap(), + }; + + // ================================================= + // ==================== Step #0 ==================== + // πŸ‘› Wallet: Bob πŸ§› + // πŸ€™ Call: supply_base + // πŸ’° Amount: 10.00 ETH + + let amount = parse_units(10 * AMOUNT_COEFFICIENT, eth.decimals); + let log_amount = format!("{} ETH", amount as f64 / scale_9); + print_case_title(0, "Bob", "supply_base", log_amount.as_str()); + println!("πŸ’Έ Bob + {log_amount}"); + + // Bob calls supply_base + market + .with_account(&bob) + .await + .unwrap() + .supply_base(eth.asset_id, amount) + .await + .unwrap(); + + // Π‘heck supply balance equal to 10 ETH + let (supply_balance, _) = market.get_user_supply_borrow(bob_account).await.unwrap(); + assert!(supply_balance == amount as u128); + + market + .print_debug_state(&wallets, ð, &usdt) + .await + .unwrap(); + market.debug_increment_timestamp().await.unwrap(); + + // ================================================= + // ==================== Step #1 ==================== + // πŸ‘› Wallet: Alice 🦹 + // πŸ€™ Call: supply_collateral + // πŸ’° Amount: 10000 USDT ~ $10000.00 + + let amount = parse_units(10000 * AMOUNT_COEFFICIENT, usdt.decimals); + let log_amount = format!("{} USDT", amount as f64 / scale_6); + print_case_title(1, "Alice", "supply_collateral", log_amount.as_str()); + println!("πŸ’Έ Alice + {log_amount}"); + + // Transfer of 10000 USDT to the Alice's wallet + usdt_contract.mint(alice_account, amount).await.unwrap(); + + let balance = alice.get_asset_balance(&usdt.asset_id).await.unwrap(); + assert!(balance == amount); + + // Alice calls supply_collateral + market + .with_account(&alice) + .await + .unwrap() + .supply_collateral(usdt.asset_id, amount) + .await + .unwrap(); + + // Π‘heck supply balance equal to 10000 USDT + let res = market + .get_user_collateral(alice_account, usdt.asset_id) + .await + .unwrap() + .value; + assert!(res == amount); + + market + .print_debug_state(&wallets, ð, &usdt) + .await + .unwrap(); + market.debug_increment_timestamp().await.unwrap(); + + // ================================================= + // ==================== Step #2 ==================== + // πŸ‘› Wallet: Alice 🦹 + // πŸ€™ Call: withdraw_base + // πŸ’° Amount: 1 ETH + + let amount = parse_units(1 * AMOUNT_COEFFICIENT, eth.decimals); + let log_amount = format!("{} ETH", amount as f64 / scale_9); + print_case_title(2, "Alice", "withdraw_base", log_amount.as_str()); + + let old_balance = alice.get_asset_balance(ð.asset_id).await.unwrap(); + + // Alice calls withdraw_base + market + .with_account(&alice) + .await + .unwrap() + .withdraw_base(&[&oracle.instance], amount, &price_data_update) + .await + .unwrap(); + + // ETH balance check + let balance = alice.get_asset_balance(ð.asset_id).await.unwrap(); + assert!((balance - old_balance) == amount - 1); + + market + .print_debug_state(&wallets, ð, &usdt) + .await + .unwrap(); + market.debug_increment_timestamp().await.unwrap(); + + // ================================================= + // ==================== Step #3 ==================== + // πŸ‘› Wallet: Chad 🀡 + // πŸ€™ Call: supply_collateral + // πŸ’° Amount: 15000 USDT ~ $15000.00 + + let amount = parse_units(15000 * AMOUNT_COEFFICIENT, usdt.decimals); + let log_amount = format!("{} USDT", amount as f64 / scale_6); + print_case_title(3, "Chad", "supply_collateral", log_amount.as_str()); + println!("πŸ’Έ Chad + {log_amount}"); + + // Transfer of 15000 USDT to the Chad's wallet + usdt_contract.mint(chad_account, amount).await.unwrap(); + + let balance = chad.get_asset_balance(&usdt.asset_id).await.unwrap(); + assert!(balance == amount); + + // Chad calls supply_collateral + market + .with_account(&chad) + .await + .unwrap() + .supply_collateral(usdt.asset_id, amount) + .await + .unwrap(); + + // Π‘heck supply balance equal to 15000 USDT + let res = market + .get_user_collateral(chad_account, usdt.asset_id) + .await + .unwrap() + .value; + assert!(res == amount); + + market + .print_debug_state(&wallets, ð, &usdt) + .await + .unwrap(); + market.debug_increment_timestamp().await.unwrap(); + + // ================================================= + // ==================== Step #4 ==================== + // πŸ‘› Wallet: Chad 🀡 + // πŸ€™ Call: supply_base + // πŸ’° Amount: 20 ETH + + let amount = parse_units(20 * AMOUNT_COEFFICIENT, eth.decimals); + let log_amount = format!("{} ETH", amount as f64 / scale_9); + print_case_title(4, "Chad", "supply_base", log_amount.as_str()); + println!("πŸ’Έ Chad + {log_amount}"); + + // Chad calls supply_base + market + .with_account(&chad) + .await + .unwrap() + .supply_base(eth.asset_id, amount) + .await + .unwrap(); + + // Π‘heck supply balance equal to 20 ETH + let (supply_balance, _) = market.get_user_supply_borrow(chad_account).await.unwrap(); + assert!((amount as u128) - 5 < supply_balance); + + market + .print_debug_state(&wallets, ð, &usdt) + .await + .unwrap(); + market.debug_increment_timestamp().await.unwrap(); + + // ================================================= + // ==================== Step #5 ==================== + // πŸ‘› Wallet: Alice 🦹 + // πŸ€™ Call: withdraw_base + // πŸ’° Amount: ~1.57 ETH (available_to_borrow) + let amount = market + .available_to_borrow(&[&oracle.instance], alice_account) + .await + .unwrap(); + let log_amount = format!("{} ETH", amount as f64 / scale_9); + print_case_title(5, "Alice", "withdraw_base", log_amount.as_str()); + + let old_balance = alice.get_asset_balance(ð.asset_id).await.unwrap(); + + // Alice calls withdraw_base + market + .with_account(&alice) + .await + .unwrap() + .withdraw_base( + &[&oracle.instance], + (amount - u128::from(parse_units(1, eth.decimals - 3))) + .try_into() + .unwrap(), + &price_data_update, + ) + .await + .unwrap(); + + // available_to_borrow should be 0.00100000 ETH + let res = market + .available_to_borrow(&[&oracle.instance], alice_account) + .await + .unwrap(); + + assert!(res == u128::from(parse_units(1, eth.decimals - 3)) - 1); + + // Withdrawing more than available should fail (0.00200000 ETH) + let res = market + .with_account(&alice) + .await + .unwrap() + .withdraw_base( + &[&oracle.instance], + parse_units(2, eth.decimals - 3), + &price_data_update, + ) + .await + .is_err(); + assert!(res); + + // ETH balance should be amount - ~1.57 ETH + 1 ETH from case #2 + let balance = alice.get_asset_balance(ð.asset_id).await.unwrap(); + let amount: u64 = amount.try_into().unwrap(); + assert!(old_balance + amount - parse_units(1, eth.decimals - 3) - 1 == balance); + + market + .print_debug_state(&wallets, ð, &usdt) + .await + .unwrap(); + market.debug_increment_timestamp().await.unwrap(); + + // ================================================= + // ==================== Step #6 ==================== + // πŸ‘› Wallet: Admin πŸ—Ώ + // πŸ€™ Drop of collateral price + // πŸ’° Amount: -30% + + print_case_title(6, "Admin", "Drop of collateral price", "-30%"); + let res = oracle.price(usdt.price_feed_id).await.unwrap().value; + let new_price = (res.price as f64 * 0.7) as u64; + let prices = Vec::from([( + usdt.price_feed_id, + ( + new_price, + usdt.price_feed_decimals, + res.publish_time, + res.confidence, + ), + )]); + + let price_data_update_old = price_data_update.clone(); + oracle.update_prices(&prices).await.unwrap(); + + // New `price_data_update` that will be used in the next steps + let price_data_update = PriceDataUpdate { + update_fee: 1, + price_feed_ids: vec![usdt.price_feed_id], + publish_times: vec![tai64::Tai64::from_unix(Utc::now().timestamp().try_into().unwrap()).0], + update_data: oracle.create_update_data(&prices).await.unwrap(), + }; + + println!( + "πŸ”» USDT price drops: ${} -> ${}", + res.price as f64 / 10_u64.pow(usdt.price_feed_decimals) as f64, + new_price as f64 / 10_u64.pow(usdt.price_feed_decimals) as f64 + ); + let res = oracle.price(usdt.price_feed_id).await.unwrap().value; + assert!(new_price == res.price); + + market + .print_debug_state(&wallets, ð, &usdt) + .await + .unwrap(); + market.debug_increment_timestamp().await.unwrap(); + + // ================================================= + // ==================== Step #7 ==================== + // πŸ‘› Wallet: Bob 🦹 + // πŸ€™ Call: absorb + // πŸ”₯ Target: Alice + + print_case_title(7, "Bob", "absorb", "Alice"); + + assert!( + market + .is_liquidatable(&[&oracle.instance], alice_account) + .await + .unwrap() + .value + ); + + market + .with_account(&bob) + .await + .unwrap() + .absorb(&[&oracle.instance], vec![alice_account], &price_data_update) + .await + .unwrap(); + + // Check if absorb was ok + let (_, borrow) = market.get_user_supply_borrow(alice_account).await.unwrap(); + assert!(borrow == 0); + + let amount = market + .get_user_collateral(alice_account, usdt.asset_id) + .await + .unwrap() + .value; + assert!(amount == 0); + + market + .print_debug_state(&wallets, ð, &usdt) + .await + .unwrap(); + market.debug_increment_timestamp().await.unwrap(); + + // ================================================= + // ==================== Step #8 ==================== + // πŸ‘› Wallet: Bob 🀡 + // πŸ€™ Call: buy_collateral + // πŸ’° Amount: 1.94 ETH + + let reserves = market + .with_account(&bob) + .await + .unwrap() + .get_collateral_reserves(usdt.asset_id) + .await + .unwrap() + .value; + assert!(!is_i256_negative(&reserves)); + + let amount = market + .collateral_value_to_sell( + &[&oracle.instance], + usdt.asset_id, + convert_i256_to_u64(&reserves), + ) + .await + .unwrap() + .value; + + let log_amount = format!("{} ETH", amount as f64 / scale_9); + print_case_title(8, "Bob", "buy_collateral", log_amount.as_str()); + + // Reset prices back to old values + // This is used to test that multi_call_handler works correctly + market + .update_price_feeds_if_necessary(&[&oracle.instance], &price_data_update_old) + .await + .unwrap(); + + // Prepare calls for multi_call_handler + let tx_policies = TxPolicies::default().with_script_gas_limit(1_000_000); + + // Params for update_price_feeds_if_necessary + let call_params_update_price = + CallParameters::default().with_amount(price_data_update.update_fee); + + // Update price feeds if necessary + let update_balance_call = market + .instance + .methods() + .update_price_feeds_if_necessary(price_data_update.clone()) + .with_contracts(&[&oracle.instance]) + .with_tx_policies(tx_policies) + .call_params(call_params_update_price) + .unwrap(); + + // Params for buy_collateral + let call_params_base_asset = CallParameters::default() + .with_amount(amount as u64) + .with_asset_id(eth.asset_id); + + // Buy collateral with base asset + let buy_collateral_call = market + .instance + .methods() + .buy_collateral(usdt.asset_id, 1u64.into(), bob_account) + .with_contracts(&[&oracle.instance]) + .with_tx_policies(tx_policies) + .call_params(call_params_base_asset) + .unwrap(); + + let mutli_call_handler = CallHandler::new_multi_call(bob.clone()) + .add_call(update_balance_call) + .add_call(buy_collateral_call) + .with_variable_output_policy(VariableOutputPolicy::Exactly(2)); + + // Sumbit tx + let submitted_tx = mutli_call_handler.submit().await.unwrap(); + + // Wait for response + let _: CallResponse<((), ())> = submitted_tx.response().await.unwrap(); + + // Check + let balance = bob.get_asset_balance(&usdt.asset_id).await.unwrap(); + assert!(balance == parse_units(10000, usdt.decimals) * AMOUNT_COEFFICIENT); + + market + .print_debug_state(&wallets, ð, &usdt) + .await + .unwrap(); + market.debug_increment_timestamp().await.unwrap(); + + // ================================================= + // ==================== Step #9 ==================== + // πŸ‘› Wallet: Bob πŸ§› + // πŸ€™ Call: withdraw_base + // πŸ’° Amount: 10.000050048 ETH + + let (amount, _) = market.get_user_supply_borrow(bob_account).await.unwrap(); + let log_amount = format!("{} ETH", amount as f64 / scale_9); + print_case_title(9, "Bob", "withdraw_base", log_amount.as_str()); + + let old_balance = bob.get_asset_balance(ð.asset_id).await.unwrap(); + + // Bob calls withdraw_base + market + .with_account(&bob) + .await + .unwrap() + .withdraw_base( + &[&oracle.instance], + amount.try_into().unwrap(), + &price_data_update, + ) + .await + .unwrap(); + + // Check supplied is 0 + let (supplied, _) = market.get_user_supply_borrow(bob_account).await.unwrap(); + assert!(supplied == 0); + + // ETH balance check + let balance = bob.get_asset_balance(ð.asset_id).await.unwrap(); + assert!((balance - old_balance) == amount as u64 - 1); + + market + .print_debug_state(&wallets, ð, &usdt) + .await + .unwrap(); + market.debug_increment_timestamp().await.unwrap(); + + // ================================================= + // ==================== Step #10 ==================== + // πŸ‘› Wallet: Chad πŸ§› + // πŸ€™ Call: withdraw_base + // πŸ’° Amount: 20.000050627 ETH + + let (amount, _) = market.get_user_supply_borrow(chad_account).await.unwrap(); + let log_amount = format!("{} ETH", amount as f64 / scale_9); + print_case_title(10, "Chad", "withdraw_base", log_amount.as_str()); + + let old_balance = chad.get_asset_balance(ð.asset_id).await.unwrap(); + + // Chad calls withdraw_base + market + .with_account(&chad) + .await + .unwrap() + .withdraw_base( + &[&oracle.instance], + amount.try_into().unwrap(), + &price_data_update, + ) + .await + .unwrap(); + + // Check supplied is 0 + let (supplied, _) = market.get_user_supply_borrow(chad_account).await.unwrap(); + assert!(supplied == 0); + + // ETH balance check + let balance = chad.get_asset_balance(ð.asset_id).await.unwrap(); + assert!((balance - old_balance) == amount as u64 - 1); + + market + .print_debug_state(&wallets, ð, &usdt) + .await + .unwrap(); + market.debug_increment_timestamp().await.unwrap(); + + // // ================================================= + // // ==================== Step #11 ==================== + // // πŸ‘› Wallet: Alice πŸ§› + // // πŸ€™ Call: withdraw_base + // // πŸ’° Amount: 17.276598 USDC + + // let (amount, _) = market.get_user_supply_borrow(alice_account).await.unwrap(); + // let log_amount = format!("{} USDC", amount as f64 / scale_6); + // print_case_title(11, "Alice", "withdraw_base", log_amount.as_str()); + + // // Alice calls withdraw_base + // market + // .with_account(&alice) + // .await + // .unwrap() + // .withdraw_base( + // &[&oracle.instance], + // amount.try_into().unwrap(), + // &price_data_update, + // ) + // .await + // .unwrap(); + + // // USDC balance check + // let (supplied, _) = market.get_user_supply_borrow(alice_account).await.unwrap(); + // assert!(supplied == 0); + + // market + // .print_debug_state(&wallets, &usdc, &uni) + // .await + // .unwrap(); + // market.debug_increment_timestamp().await.unwrap(); + + // // ================================================= + // // ==================== Step #12 ==================== + // // πŸ‘› Wallet: Chad 🀡 + // // πŸ€™ Call: withdraw_collateral + // // πŸ’° Amount: 270 UNI + + // let amount = market + // .get_user_collateral(chad_account, uni.asset_id) + // .await + // .unwrap() + // .value; + // let log_amount = format!("{} UNI", amount as f64 / scale_9); + // print_case_title(12, "Chad", "withdraw_collateral", log_amount.as_str()); + + // // Chad calls withdraw_collateral + // market + // .with_account(&chad) + // .await + // .unwrap() + // .withdraw_collateral( + // &[&oracle.instance], + // uni.asset_id, + // amount.try_into().unwrap(), + // &price_data_update, + // ) + // .await + // .unwrap(); + + // // UNI balance check + // let balance = chad.get_asset_balance(&uni.asset_id).await.unwrap(); + // assert!(balance == amount); + + // market + // .print_debug_state(&wallets, &usdc, &uni) + // .await + // .unwrap(); +} diff --git a/contracts/market/tests/local_tests/main_test_uni.rs b/contracts/market/tests/local_tests/main_test_uni.rs index 69893929..6eb554dc 100644 --- a/contracts/market/tests/local_tests/main_test_uni.rs +++ b/contracts/market/tests/local_tests/main_test_uni.rs @@ -1,4 +1,4 @@ -use crate::utils::{print_case_title, setup, TestData}; +use crate::utils::{print_case_title, setup, TestBaseAsset, TestData}; use chrono::Utc; use fuels::{ prelude::ViewOnlyAccount, @@ -39,7 +39,7 @@ async fn main_test() { publish_time, prices, .. - } = setup(None).await; + } = setup(None, TestBaseAsset::USDC).await; let price_data_update = PriceDataUpdate { update_fee: 1, diff --git a/contracts/market/tests/local_tests/main_test_uni_no_debug_mode.rs b/contracts/market/tests/local_tests/main_test_uni_no_debug_mode.rs index ac12fc26..c1993afb 100644 --- a/contracts/market/tests/local_tests/main_test_uni_no_debug_mode.rs +++ b/contracts/market/tests/local_tests/main_test_uni_no_debug_mode.rs @@ -1,4 +1,4 @@ -use crate::utils::{print_case_title, setup, TestData}; +use crate::utils::{print_case_title, setup, TestBaseAsset, TestData}; use chrono::Utc; use fuels::prelude::ViewOnlyAccount; use fuels::programs::calls::{CallHandler, CallParameters}; @@ -35,7 +35,7 @@ async fn main_test_no_debug() { publish_time, prices, .. - } = setup(None).await; + } = setup(None, TestBaseAsset::USDC).await; let price_data_update = PriceDataUpdate { update_fee: 1, diff --git a/contracts/market/tests/local_tests/main_test_usdt.rs b/contracts/market/tests/local_tests/main_test_usdt.rs index eb886158..a45cde04 100644 --- a/contracts/market/tests/local_tests/main_test_usdt.rs +++ b/contracts/market/tests/local_tests/main_test_usdt.rs @@ -1,4 +1,4 @@ -use crate::utils::{print_case_title, setup, TestData}; +use crate::utils::{print_case_title, setup, TestBaseAsset, TestData}; use chrono::Utc; use fuels::{ prelude::ViewOnlyAccount, @@ -39,7 +39,7 @@ async fn main_test() { publish_time, prices, .. - } = setup(None).await; + } = setup(None, TestBaseAsset::USDC).await; let price_data_update = PriceDataUpdate { update_fee: 1, diff --git a/contracts/market/tests/local_tests/mod.rs b/contracts/market/tests/local_tests/mod.rs index 53880125..dce29a75 100644 --- a/contracts/market/tests/local_tests/mod.rs +++ b/contracts/market/tests/local_tests/mod.rs @@ -1,3 +1,4 @@ +mod main_test_eth_base; mod main_test_uni; mod main_test_uni_no_debug_mode; mod main_test_usdt; diff --git a/contracts/market/tests/local_tests/scenarios/collateral_borrow.rs b/contracts/market/tests/local_tests/scenarios/collateral_borrow.rs index 2c9b3b22..7da6b44b 100644 --- a/contracts/market/tests/local_tests/scenarios/collateral_borrow.rs +++ b/contracts/market/tests/local_tests/scenarios/collateral_borrow.rs @@ -1,4 +1,4 @@ -use crate::utils::{print_case_title, setup, TestData}; +use crate::utils::{print_case_title, setup, TestBaseAsset, TestData}; use fuels::accounts::ViewOnlyAccount; use market::PriceDataUpdate; use market_sdk::parse_units; @@ -26,7 +26,7 @@ async fn collateral_borrow_test() { uni, uni_contract, .. - } = setup(None).await; + } = setup(None, TestBaseAsset::USDC).await; let price_data_update = PriceDataUpdate { update_fee: 0, @@ -256,7 +256,7 @@ async fn collateral_borrow_timeskip_test() { uni, uni_contract, .. - } = setup(None).await; + } = setup(None, TestBaseAsset::USDC).await; let price_data_update = PriceDataUpdate { update_fee: 0, diff --git a/contracts/market/tests/local_tests/scenarios/configuration.rs b/contracts/market/tests/local_tests/scenarios/configuration.rs index 946a52b6..71ca52ad 100644 --- a/contracts/market/tests/local_tests/scenarios/configuration.rs +++ b/contracts/market/tests/local_tests/scenarios/configuration.rs @@ -1,4 +1,4 @@ -use crate::utils::{setup, TestData}; +use crate::utils::{setup, TestBaseAsset, TestData}; use fuels::types::U256; use market::{CollateralConfiguration, MarketConfiguration, PriceDataUpdate}; use market_sdk::parse_units; @@ -22,7 +22,7 @@ async fn collateral_configuration_test() { usdc_contract, eth, .. - } = setup(None).await; + } = setup(None, TestBaseAsset::USDC).await; let price_data_update = PriceDataUpdate { update_fee: 0, @@ -164,7 +164,7 @@ async fn market_configuration_test() { market, usdc, .. - } = setup(None).await; + } = setup(None, TestBaseAsset::USDC).await; let old_market_config = market.get_market_configuration().await.unwrap().value; let new_market_config = MarketConfiguration { diff --git a/contracts/market/tests/local_tests/scenarios/liquidation.rs b/contracts/market/tests/local_tests/scenarios/liquidation.rs index 1f27f398..e687c1de 100644 --- a/contracts/market/tests/local_tests/scenarios/liquidation.rs +++ b/contracts/market/tests/local_tests/scenarios/liquidation.rs @@ -1,4 +1,4 @@ -use crate::utils::{print_case_title, setup, TestData}; +use crate::utils::{print_case_title, setup, TestBaseAsset, TestData}; use chrono::Utc; use fuels::{ accounts::ViewOnlyAccount, @@ -37,7 +37,7 @@ async fn absorb_and_liquidate() { prices, usdc_contract, .. - } = setup(None).await; + } = setup(None, TestBaseAsset::USDC).await; let price_data_update = PriceDataUpdate { update_fee: 0, @@ -322,7 +322,7 @@ async fn all_assets_liquidated() { prices, usdc_contract, .. - } = setup(None).await; + } = setup(None, TestBaseAsset::USDC).await; let price_data_update = PriceDataUpdate { update_fee: 0, @@ -597,7 +597,7 @@ async fn is_liquidatable_internal_uses_correct_index() { usdc_contract, uni_contract, .. - } = setup(Some(100_000_000)).await; + } = setup(Some(100_000_000), TestBaseAsset::USDC).await; let price_data_update = PriceDataUpdate { update_fee: 0, diff --git a/contracts/market/tests/local_tests/scenarios/multicall_absorb_buy_collateral.rs b/contracts/market/tests/local_tests/scenarios/multicall_absorb_buy_collateral.rs index 9f67e31c..6f72ac06 100644 --- a/contracts/market/tests/local_tests/scenarios/multicall_absorb_buy_collateral.rs +++ b/contracts/market/tests/local_tests/scenarios/multicall_absorb_buy_collateral.rs @@ -1,4 +1,4 @@ -use crate::utils::{print_case_title, setup, TestData}; +use crate::utils::{print_case_title, setup, TestBaseAsset, TestData}; use chrono::Utc; use fuels::{ accounts::ViewOnlyAccount, @@ -35,7 +35,7 @@ async fn multicall_absorb_buy_collateral_test() { prices, assets, .. - } = setup(None).await; + } = setup(None, TestBaseAsset::USDC).await; let price_data_update = PriceDataUpdate { update_fee: 1, diff --git a/contracts/market/tests/local_tests/scenarios/multicall_withdraw_supply.rs b/contracts/market/tests/local_tests/scenarios/multicall_withdraw_supply.rs index 6f214cc3..da072184 100644 --- a/contracts/market/tests/local_tests/scenarios/multicall_withdraw_supply.rs +++ b/contracts/market/tests/local_tests/scenarios/multicall_withdraw_supply.rs @@ -1,4 +1,4 @@ -use crate::utils::{print_case_title, setup, TestData}; +use crate::utils::{print_case_title, setup, TestBaseAsset, TestData}; use fuels::{ accounts::ViewOnlyAccount, programs::{ @@ -32,7 +32,7 @@ async fn multicall_withdraw_supply_test() { prices, assets, .. - } = setup(None).await; + } = setup(None, TestBaseAsset::USDC).await; let price_data_update = PriceDataUpdate { update_fee: 1, diff --git a/contracts/market/tests/local_tests/scenarios/negative_reserves.rs b/contracts/market/tests/local_tests/scenarios/negative_reserves.rs index 2201e93a..1fd10f25 100644 --- a/contracts/market/tests/local_tests/scenarios/negative_reserves.rs +++ b/contracts/market/tests/local_tests/scenarios/negative_reserves.rs @@ -1,4 +1,4 @@ -use crate::utils::{print_case_title, setup, TestData}; +use crate::utils::{print_case_title, setup, TestBaseAsset, TestData}; use chrono::Utc; use fuels::accounts::ViewOnlyAccount; use market::PriceDataUpdate; @@ -27,7 +27,7 @@ async fn negative_reserves_test() { prices, assets, .. - } = setup(None).await; + } = setup(None, TestBaseAsset::USDC).await; let price_data_update = PriceDataUpdate { update_fee: 1, diff --git a/contracts/market/tests/local_tests/scenarios/owner.rs b/contracts/market/tests/local_tests/scenarios/owner.rs index 1cb0ac85..70780190 100644 --- a/contracts/market/tests/local_tests/scenarios/owner.rs +++ b/contracts/market/tests/local_tests/scenarios/owner.rs @@ -13,7 +13,7 @@ use std::str::FromStr; -use crate::utils::{setup, TestData}; +use crate::utils::{setup, TestBaseAsset, TestData}; use fuels::types::{ContractId, U256}; use market::{CollateralConfiguration, PauseConfiguration}; use market_sdk::get_market_config; @@ -31,7 +31,7 @@ async fn owner_test() { assets, usdc, .. - } = setup(None).await; + } = setup(None, TestBaseAsset::USDC).await; let asset_id = assets["ETH"].asset_id; diff --git a/contracts/market/tests/local_tests/scenarios/pause.rs b/contracts/market/tests/local_tests/scenarios/pause.rs index 76e87de2..e404a0ed 100644 --- a/contracts/market/tests/local_tests/scenarios/pause.rs +++ b/contracts/market/tests/local_tests/scenarios/pause.rs @@ -1,3 +1,4 @@ +use crate::utils::TestBaseAsset; use crate::utils::{setup, TestData}; use chrono::Utc; use fuels::prelude::ViewOnlyAccount; @@ -26,7 +27,7 @@ async fn pause_test() { publish_time, prices, .. - } = setup(None).await; + } = setup(None, TestBaseAsset::USDC).await; let price_data_update = PriceDataUpdate { update_fee: 1, diff --git a/contracts/market/tests/local_tests/scenarios/price_changes.rs b/contracts/market/tests/local_tests/scenarios/price_changes.rs index 7c57b2fc..8b05c4b7 100644 --- a/contracts/market/tests/local_tests/scenarios/price_changes.rs +++ b/contracts/market/tests/local_tests/scenarios/price_changes.rs @@ -1,7 +1,7 @@ // **Scenario #12 - Collateral asset price increases** // Description: Check that if collateral asset price increases, you can now borrow more base asset. -use crate::utils::{print_case_title, setup, TestData}; +use crate::utils::{print_case_title, setup, TestBaseAsset, TestData}; use chrono::Utc; use fuels::accounts::ViewOnlyAccount; use market::PriceDataUpdate; @@ -28,7 +28,7 @@ async fn price_changes() { prices, usdc_contract, .. - } = setup(None).await; + } = setup(None, TestBaseAsset::USDC).await; let price_data_update = PriceDataUpdate { update_fee: 0, diff --git a/contracts/market/tests/local_tests/scenarios/reserves.rs b/contracts/market/tests/local_tests/scenarios/reserves.rs index fb3b277a..59856540 100644 --- a/contracts/market/tests/local_tests/scenarios/reserves.rs +++ b/contracts/market/tests/local_tests/scenarios/reserves.rs @@ -1,4 +1,4 @@ -use crate::utils::{setup, TestData}; +use crate::utils::{setup, TestBaseAsset, TestData}; use fuels::{accounts::Account, types::transaction::TxPolicies}; use market::PriceDataUpdate; use market_sdk::{convert_i256_to_i128, convert_i256_to_i64, parse_units}; @@ -24,7 +24,7 @@ async fn reserves_test() { admin, admin_account, .. - } = setup(None).await; + } = setup(None, TestBaseAsset::USDC).await; let price_data_update = PriceDataUpdate { update_fee: 0, @@ -151,7 +151,7 @@ async fn add_reserves_test() { usdc, usdc_contract, .. - } = setup(None).await; + } = setup(None, TestBaseAsset::USDC).await; let mint_amount = parse_units(150, usdc.decimals); usdc_contract diff --git a/contracts/market/tests/local_tests/scenarios/rewards.rs b/contracts/market/tests/local_tests/scenarios/rewards.rs index b5a5775c..3acc4d82 100644 --- a/contracts/market/tests/local_tests/scenarios/rewards.rs +++ b/contracts/market/tests/local_tests/scenarios/rewards.rs @@ -1,4 +1,4 @@ -use crate::utils::{setup, TestData}; +use crate::utils::{setup, TestBaseAsset, TestData}; use fuels::types::U256; use market::PriceDataUpdate; use market_sdk::parse_units; @@ -22,7 +22,7 @@ async fn rewards_test() { prices, eth, .. - } = setup(None).await; + } = setup(None, TestBaseAsset::USDC).await; let price_data_update = PriceDataUpdate { update_fee: 0, diff --git a/contracts/market/tests/local_tests/scenarios/supply_withdraw.rs b/contracts/market/tests/local_tests/scenarios/supply_withdraw.rs index 1a55d965..b65d52b7 100644 --- a/contracts/market/tests/local_tests/scenarios/supply_withdraw.rs +++ b/contracts/market/tests/local_tests/scenarios/supply_withdraw.rs @@ -1,4 +1,4 @@ -use crate::utils::{print_case_title, setup, TestData}; +use crate::utils::{print_case_title, setup, TestBaseAsset, TestData}; use fuels::prelude::ViewOnlyAccount; use market::PriceDataUpdate; use market_sdk::parse_units; @@ -21,7 +21,7 @@ async fn supply_withdraw_test() { publish_time, prices, .. - } = setup(None).await; + } = setup(None, TestBaseAsset::USDC).await; let price_data_update = PriceDataUpdate { update_fee: 1, diff --git a/contracts/market/tests/local_tests/scenarios/utilization.rs b/contracts/market/tests/local_tests/scenarios/utilization.rs index 8bb94c26..d6513ac0 100644 --- a/contracts/market/tests/local_tests/scenarios/utilization.rs +++ b/contracts/market/tests/local_tests/scenarios/utilization.rs @@ -5,7 +5,7 @@ // Code: // Steps: -use crate::utils::{print_case_title, setup, TestData}; +use crate::utils::{print_case_title, setup, TestBaseAsset, TestData}; use fuels::{accounts::ViewOnlyAccount, types::U256}; use market::PriceDataUpdate; use market_sdk::parse_units; @@ -31,7 +31,7 @@ async fn utilization_above_kinks() { prices, assets, .. - } = setup(None).await; + } = setup(None, TestBaseAsset::USDC).await; let price_data_update = PriceDataUpdate { update_fee: 1, diff --git a/contracts/market/tests/utils/mod.rs b/contracts/market/tests/utils/mod.rs index a4061956..49b9fec5 100644 --- a/contracts/market/tests/utils/mod.rs +++ b/contracts/market/tests/utils/mod.rs @@ -1,7 +1,7 @@ use chrono::Utc; use fuels::accounts::wallet::WalletUnlocked; use fuels::test_helpers::{ - launch_custom_provider_and_get_wallets, NodeConfig, Trigger, WalletsConfig, + launch_custom_provider_and_get_wallets, ChainConfig, NodeConfig, Trigger, WalletsConfig }; use fuels::types::{Bits256, ContractId, Identity}; use market_sdk::{get_market_config, Market}; @@ -21,11 +21,12 @@ pub fn print_case_title(num: u8, name: &str, call: &str, amount: &str) { ); } -pub async fn init_wallets() -> Vec { - let wallets_config = WalletsConfig::new(Some(5), Some(10), Some(1_000_000_000)); +pub async fn init_wallets(use_gas_price: bool) -> Vec { + let wallets_config = WalletsConfig::new(Some(5), Some(1000), Some(1_000_000_000)); let provider_config = NodeConfig { block_production: Trigger::Instant, + starting_gas_price: if use_gas_price { 0 } else { 1 }, ..NodeConfig::default() }; @@ -37,6 +38,12 @@ pub async fn init_wallets() -> Vec { }; } +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum TestBaseAsset { + USDC, + ETH, +} + pub struct TestData { pub admin: WalletUnlocked, pub admin_account: Identity, @@ -62,9 +69,10 @@ pub struct TestData { pub prices: Vec<(Bits256, (u64, u32, u64, u64))>, } -pub async fn setup(debug_step: Option) -> TestData { +pub async fn setup(debug_step: Option, base_asset: TestBaseAsset) -> TestData { //--------------- WALLETS --------------- - let wallets = init_wallets().await; + let no_fees = base_asset == TestBaseAsset::ETH; + let wallets = init_wallets(no_fees).await; let admin = &wallets[0]; let alice = &wallets[1]; let bob = &wallets[2]; @@ -100,8 +108,14 @@ pub async fn setup(debug_step: Option) -> TestData { let eth = assets.get("ETH").unwrap().clone(); //--------------- MARKET --------------- - let market_config = - get_market_config(usdc.asset_id, usdc.decimals as u32, usdc.price_feed_id).unwrap(); + let market_config = match base_asset { + TestBaseAsset::USDC => { + get_market_config(usdc.asset_id, usdc.decimals as u32, usdc.price_feed_id).unwrap() + } + TestBaseAsset::ETH => { + get_market_config(eth.asset_id, eth.decimals as u32, eth.price_feed_id).unwrap() + } + }; // debug step let debug_step: u64 = debug_step.unwrap_or(10_000); diff --git a/libs/market_sdk/src/market_utils.rs b/libs/market_sdk/src/market_utils.rs index a9f8592d..21f5bcd8 100644 --- a/libs/market_sdk/src/market_utils.rs +++ b/libs/market_sdk/src/market_utils.rs @@ -823,10 +823,13 @@ impl Market { pub async fn print_debug_state( &self, wallets: &Vec, - usdc: &Asset, + base: &Asset, collateral: &Asset, ) -> anyhow::Result<()> { - let usdc_asset_id = usdc.asset_id; + let base_asset_id = base.asset_id; + let base_decimals = base.decimals; + let base_symbol = base.symbol.clone(); + let collateral_asset_id = collateral.asset_id; let collateral_decimals = collateral.decimals; let collateral_symbol = collateral.symbol.clone(); @@ -844,7 +847,8 @@ impl Market { let scale18 = 10u64.pow(18) as f64; let market_basic = self.get_market_basics().await?.value; - let usdc_balance = self.balance_of(usdc.asset_id).await?.value as f64 / 10u64.pow(6) as f64; + let base_balance = self.balance_of(base_asset_id).await?.value as f64 + / 10u64.pow(base_decimals.try_into().unwrap()) as f64; let collateral_balance = format_units( self.balance_of(collateral.asset_id).await?.value, collateral_decimals, @@ -854,9 +858,12 @@ impl Market { let b_rate = convert_u256_to_u128(market_basic.base_borrow_index) as f64 / scale15; let total_collateral = self.totals_collateral(collateral.asset_id).await?.value; let last_accrual_time = market_basic.last_accrual_time; - let usdc_reserves = convert_i256_to_i128(&self.get_reserves().await?.value); + let base_reserves = convert_i256_to_i128(&self.get_reserves().await?.value); - let usdc_reserves = format!("{} USDC", usdc_reserves as f64 / 10u64.pow(6) as f64); + let base_reserves = format!( + "{} {base_symbol}", + base_reserves as f64 / 10u64.pow(base_decimals.try_into().unwrap()) as f64 + ); let collateral_reserves = convert_i256_to_i128( &self .get_collateral_reserves(collateral.asset_id) @@ -868,14 +875,14 @@ impl Market { collateral_reserves as f64 / 10u64.pow(collateral_decimals as u32) as f64 ); let supply_base = convert_u256_to_u128(market_basic.total_supply_base) as f64 * s_rate - / 10u64.pow(6) as f64; + / 10u64.pow(base_decimals.try_into().unwrap()) as f64; let borrow_base = convert_u256_to_u128(market_basic.total_borrow_base) as f64 * b_rate - / 10u64.pow(6) as f64; + / 10u64.pow(base_decimals.try_into().unwrap()) as f64; - println!("🏦 Market\n Total supply {supply_base} USDC | Total borrow {borrow_base} USDC",); + println!("🏦 Market\n Total supply {supply_base} {base_symbol} | Total borrow {borrow_base} {base_symbol}"); println!( - " Total USDC balance = {usdc_balance} USDC | Total {collateral_symbol} balance = {collateral_balance} {collateral_symbol}"); - println!(" reserves: {usdc_reserves} | {collateral_reserves}"); + " Total {base_symbol} balance = {base_balance} {base_symbol} | Total {collateral_symbol} balance = {collateral_balance} {collateral_symbol}"); + println!(" reserves: {base_reserves} | {collateral_reserves}"); println!(" sRate {s_rate} | bRate {b_rate}"); println!( " Total collateral {} {collateral_symbol}", @@ -885,10 +892,10 @@ impl Market { let basic = self.get_user_basic(alice_account).await?.value; let (supply, borrow) = self.get_user_supply_borrow(alice_account).await?; - let supply = format_units_u128(supply, 6); - let borrow = format_units_u128(borrow, 6); - let usdc_balance = - alice.get_asset_balance(&usdc_asset_id).await? as f64 / 10u64.pow(6) as f64; + let supply = format_units_u128(supply, base_decimals); + let borrow = format_units_u128(borrow, base_decimals); + let usdc_balance = alice.get_asset_balance(&base_asset_id).await? as f64 + / 10u64.pow(base_decimals.try_into().unwrap()) as f64; let collateral_balance = alice.get_asset_balance(&collateral_asset_id).await? as f64 / 10u64.pow(collateral_decimals as u32) as f64; let collateral_amount = self @@ -897,19 +904,21 @@ impl Market { .value; println!("\nAlice 🦹"); println!(" Principal = {}", convert_i256_to_i128(&basic.principal)); - println!(" Present supply = {supply} USDC | borrow = {borrow} USDC"); + println!(" Present supply = {supply} {base_symbol} | borrow = {borrow} {base_symbol}"); println!( " Supplied collateral {} {collateral_symbol}", format_units(collateral_amount, collateral_decimals) ); - println!(" Balance {usdc_balance} USDC | {collateral_balance} {collateral_symbol}"); + println!( + " Balance {usdc_balance} {base_symbol} | {collateral_balance} {collateral_symbol}" + ); let basic = self.get_user_basic(bob_account).await?.value; let (supply, borrow) = self.get_user_supply_borrow(bob_account).await?; - let supply = format_units_u128(supply, 6); - let borrow = format_units_u128(borrow, 6); - let usdc_balance = - bob.get_asset_balance(&usdc_asset_id).await? as f64 / 10u64.pow(6) as f64; + let supply = format_units_u128(supply, base_decimals); + let borrow = format_units_u128(borrow, base_decimals); + let usdc_balance = bob.get_asset_balance(&base_asset_id).await? as f64 + / 10u64.pow(base_decimals.try_into().unwrap()) as f64; let collateral_balance = bob.get_asset_balance(&collateral_asset_id).await? as f64 / 10u64.pow(collateral_decimals as u32) as f64; let collateral_amount = self @@ -919,19 +928,21 @@ impl Market { println!("\nBob πŸ§›"); println!(" Principal = {}", convert_i256_to_i128(&basic.principal)); - println!(" Present supply = {supply} USDC | borrow = {borrow} USDC"); + println!(" Present supply = {supply} {base_symbol} | borrow = {borrow} {base_symbol}"); println!( " Supplied collateral {} {collateral_symbol}", format_units(collateral_amount, collateral_decimals) ); - println!(" Balance {usdc_balance} USDC | {collateral_balance} {collateral_symbol}"); + println!( + " Balance {usdc_balance} {base_symbol} | {collateral_balance} {collateral_symbol}" + ); let basic = self.get_user_basic(chad_account).await?.value; let (supply, borrow) = self.get_user_supply_borrow(chad_account).await?; - let supply = format_units_u128(supply, 6); - let borrow = format_units_u128(borrow, 6); - let usdc_balance = - chad.get_asset_balance(&usdc_asset_id).await? as f64 / 10u64.pow(6) as f64; + let supply = format_units_u128(supply, base_decimals); + let borrow = format_units_u128(borrow, base_decimals); + let usdc_balance = chad.get_asset_balance(&base_asset_id).await? as f64 + / 10u64.pow(base_decimals.try_into().unwrap()) as f64; let collateral_balance = chad.get_asset_balance(&collateral_asset_id).await? as f64 / 10u64.pow(collateral_decimals as u32) as f64; let collateral_amount = self @@ -940,12 +951,14 @@ impl Market { .value; println!("\nChad 🀡"); println!(" Principal = {}", convert_i256_to_i128(&basic.principal)); - println!(" Present supply = {supply} USDC | borrow = {borrow} USDC"); + println!(" Present supply = {supply} {base_symbol} | borrow = {borrow} {base_symbol}"); println!( " Supplied collateral {} {collateral_symbol}", format_units(collateral_amount, collateral_decimals) ); - println!(" Balance {usdc_balance} USDC | {collateral_balance} {collateral_symbol}"); + println!( + " Balance {usdc_balance} {base_symbol} | {collateral_balance} {collateral_symbol}" + ); Ok(()) } From 378c17fc5376e926e353fb5d28ede37f6889e0d1 Mon Sep 17 00:00:00 2001 From: martines3000 Date: Wed, 6 Nov 2024 08:33:30 +0100 Subject: [PATCH 3/8] fix: add transfert eth to contract in eth base asset test --- .../tests/local_tests/main_test_eth_base.rs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/contracts/market/tests/local_tests/main_test_eth_base.rs b/contracts/market/tests/local_tests/main_test_eth_base.rs index 1548b795..e3a870cb 100644 --- a/contracts/market/tests/local_tests/main_test_eth_base.rs +++ b/contracts/market/tests/local_tests/main_test_eth_base.rs @@ -1,6 +1,7 @@ use crate::utils::{print_case_title, setup, TestBaseAsset, TestData}; use chrono::Utc; use fuels::{ + accounts::Account, prelude::ViewOnlyAccount, programs::{ calls::{CallHandler, CallParameters}, @@ -22,17 +23,14 @@ async fn main_test() { let TestData { wallets, + admin, alice, alice_account, bob, bob_account, chad, chad_account, - usdc_contract, - usdc, market, - uni, - uni_contract, oracle, price_feed_ids, assets, @@ -509,6 +507,18 @@ async fn main_test() { let old_balance = chad.get_asset_balance(ð.asset_id).await.unwrap(); + // Reserves are negative and we can't withdraw more ETH than is available + // So we need to send some ETH to the contract to make the reserves positive + admin + .force_transfer_to_contract( + market.contract_id(), + parse_units(10, eth.decimals), + eth.asset_id, + tx_policies, + ) + .await + .unwrap(); + // Chad calls withdraw_base market .with_account(&chad) From c086ba6524172e3338b6af70a10843dcbcd5a73a Mon Sep 17 00:00:00 2001 From: martines3000 Date: Wed, 6 Nov 2024 08:59:52 +0100 Subject: [PATCH 4/8] chore: fix comment --- contracts/market/src/main.sw | 2 +- liquidations copy 2.sql | 69 ++++++++++++++++++++++++++++++++++ liquidations copy.sql | 73 ++++++++++++++++++++++++++++++++++++ liquidations.sql | 65 ++++++++++++++++++++++++++++++++ 4 files changed, 208 insertions(+), 1 deletion(-) create mode 100644 liquidations copy 2.sql create mode 100644 liquidations copy.sql create mode 100644 liquidations.sql diff --git a/contracts/market/src/main.sw b/contracts/market/src/main.sw index 9d53215e..4445e254 100644 --- a/contracts/market/src/main.sw +++ b/contracts/market/src/main.sw @@ -875,7 +875,7 @@ impl Market for Contract { /// # Number of Storage Accesses /// * Reads: `5` #[storage(read)] - fn collateral_value_to_sell(asset_id: AssetId, collateral_amount: u64) -> u64 { // decimals: collateral_asset.decimals + fn collateral_value_to_sell(asset_id: AssetId, collateral_amount: u64) -> u64 { // decimals: base_token_decimals let collateral_configuration = storage.collateral_configurations.get(asset_id).read(); let market_configuration = storage.market_configuration.read(); diff --git a/liquidations copy 2.sql b/liquidations copy 2.sql new file mode 100644 index 00000000..12f980ed --- /dev/null +++ b/liquidations copy 2.sql @@ -0,0 +1,69 @@ +with user_position as ( + SELECT userAddress, + poolAddress, + borrowedAmountUsd + FROM `BasePositionSnapshot` + WHERE borrowedAmountUsd > 0 +), +user_collateral_positions as ( + SELECT userAddress, + poolAddress, + SUM( + collateralAmountUsd * CollateralPoolSnapshot.liquidationFactor + ) as totalCollateralValue + FROM `CollateralPositionSnapshot` + LEFT JOIN `CollateralPoolSnapshot` ON CollateralPositionSnapshot.underlyingTokenAddress = CollateralPoolSnapshot.underlyingTokenAddress + AND CollateralPositionSnapshot.poolAddress = CollateralPoolSnapshot.poolAddress + GROUP BY userAddress, + poolAddress +), +user_selected_collateral_position as ( + SELECT userAddress, + poolAddress, + SUM(collateralAmountNormalized) as selectedCollateralAmountNormalized, + SUM(collateralAmountUsd) as selectedCollateralAmountUsd, + SUM( + collateralAmountNormalized * CollateralPoolSnapshot.liquidationFactor + ) as selectedCollateralAmount, + SUM( + collateralAmountUsd * CollateralPoolSnapshot.liquidationFactor + ) as selectedCollateralValue + FROM `CollateralPositionSnapshot` + LEFT JOIN `CollateralPoolSnapshot` ON CollateralPositionSnapshot.underlyingTokenAddress = CollateralPoolSnapshot.underlyingTokenAddress + AND CollateralPositionSnapshot.poolAddress = CollateralPoolSnapshot.poolAddress + WHERE underlyingTokenSymbol = 'ETH' + GROUP BY userAddress, + poolAddress +), +calculations as( + SELECT + borrowedAmountUsd, + totalCollateralValue, + selectedCollateralAmountNormalized, + selectedCollateralAmountUsd, + -- ALREADY MULTIPLIED BY LIQUIDATION FACTOR + selectedCollateralAmount, + -- ALREADY MULTIPLIED BY LIQUIDATION FACTOR + COALESCE(selectedCollateralValue, 0) as selectedCollateralValue, + (totalCollateralValue - selectedCollateralValue) as otherCollateralValue, + (borrowedAmountUsd - otherCollateralValue) as diffDebt, + ROUND( + toFloat64(diffDebt) / toFloat64(selectedCollateralAmount) / 10 + ) * 10 as liqPrice + FROM user_position + LEFT JOIN user_collateral_positions ON user_position.userAddress = user_collateral_positions.userAddress + AND user_position.poolAddress = user_collateral_positions.poolAddress + LEFT JOIN user_selected_collateral_position ON user_position.userAddress = user_selected_collateral_position.userAddress + AND user_position.poolAddress = user_selected_collateral_position.poolAddress + WHERE selectedCollateralValue > 0 + AND diffDebt > 0 +) + +SELECT + liqPrice, + count(*) as count, + ROUND(SUM(SUM(borrowedAmountUsd)) OVER (ORDER BY liqPrice DESC)) as cumulative_liquidated_amount, + SUM(count(*)) OVER (ORDER BY liqPrice DESC) as cumulative_count +FROM calculations +GROUP BY liqPrice +ORDER BY liqPrice DESC \ No newline at end of file diff --git a/liquidations copy.sql b/liquidations copy.sql new file mode 100644 index 00000000..b43c42de --- /dev/null +++ b/liquidations copy.sql @@ -0,0 +1,73 @@ +with tokens as ( + SELECT arrayJoin(['ETH']) as token +), +user_position as ( + SELECT + userAddress as user, + poolAddress as pool, + borrowedAmountUsd + FROM `BasePositionSnapshot` + WHERE borrowedAmountUsd > 0 +), +user_collateral_positions as ( + SELECT + CollateralPositionSnapshot.userAddress as user, + CollateralPositionSnapshot.poolAddress as pool, + SUM( + collateralAmountUsd * CollateralPoolSnapshot.liquidationFactor + ) as totalCollateralValue + FROM `CollateralPositionSnapshot` + LEFT JOIN `CollateralPoolSnapshot` ON CollateralPositionSnapshot.underlyingTokenAddress = CollateralPoolSnapshot.underlyingTokenAddress + AND CollateralPositionSnapshot.poolAddress = CollateralPoolSnapshot.poolAddress + GROUP BY CollateralPositionSnapshot.userAddress, + CollateralPositionSnapshot.poolAddress +), +user_selected_collateral_position as ( + SELECT + tokens.token as tokenSymbol, + CollateralPositionSnapshot.userAddress as user, + CollateralPositionSnapshot.poolAddress as pool, + SUM(CollateralPositionSnapshot.collateralAmountNormalized) as selectedCollateralAmountNormalized, + SUM(CollateralPositionSnapshot.collateralAmountUsd) as selectedCollateralAmountUsd, + SUM( + CollateralPositionSnapshot.collateralAmountNormalized * CollateralPoolSnapshot.liquidationFactor + ) as selectedCollateralAmount, + SUM( + CollateralPositionSnapshot.collateralAmountUsd * CollateralPoolSnapshot.liquidationFactor + ) as selectedCollateralValue + FROM tokens + CROSS JOIN `CollateralPositionSnapshot` + LEFT JOIN `CollateralPoolSnapshot` ON CollateralPositionSnapshot.underlyingTokenAddress = CollateralPoolSnapshot.underlyingTokenAddress + AND CollateralPositionSnapshot.poolAddress = CollateralPoolSnapshot.poolAddress + WHERE CollateralPositionSnapshot.underlyingTokenSymbol = tokens.token + GROUP BY tokens.token, CollateralPositionSnapshot.userAddress, CollateralPositionSnapshot.poolAddress +), +calculations as( + SELECT + usp.tokenSymbol, + up.borrowedAmountUsd, + ucp.totalCollateralValue, + usp.selectedCollateralAmountNormalized, + usp.selectedCollateralAmountUsd, + usp.selectedCollateralAmount, + COALESCE(usp.selectedCollateralValue, 0) as selectedCollateralValue, + (ucp.totalCollateralValue - COALESCE(usp.selectedCollateralValue, 0)) as otherCollateralValue, + (up.borrowedAmountUsd - (ucp.totalCollateralValue - COALESCE(usp.selectedCollateralValue, 0))) as diffDebt, + ROUND( + toFloat64(up.borrowedAmountUsd - (ucp.totalCollateralValue - COALESCE(usp.selectedCollateralValue, 0))) / + toFloat64(usp.selectedCollateralAmount) + ) as liqPrice + FROM user_position up + LEFT JOIN user_collateral_positions ucp ON up.user = ucp.user AND up.pool = ucp.pool + LEFT JOIN user_selected_collateral_position usp ON up.user = usp.user AND up.pool = usp.pool + WHERE COALESCE(usp.selectedCollateralValue, 0) > 0 + AND (up.borrowedAmountUsd - (ucp.totalCollateralValue - COALESCE(usp.selectedCollateralValue, 0))) > 0 + ORDER BY liqPrice DESC) + +SELECT + tokenSymbol, + liqPrice, + count(*) as count +FROM calculations +GROUP BY tokenSymbol, liqPrice +ORDER BY tokenSymbol, liqPrice DESC; \ No newline at end of file diff --git a/liquidations.sql b/liquidations.sql new file mode 100644 index 00000000..4b584799 --- /dev/null +++ b/liquidations.sql @@ -0,0 +1,65 @@ +with user_position as ( + SELECT userAddress, + poolAddress, + borrowedAmountUsd + FROM `BasePositionSnapshot` + WHERE borrowedAmountUsd > 0 +), +user_collateral_positions as ( + SELECT userAddress, + poolAddress, + SUM( + collateralAmountUsd * CollateralPoolSnapshot.liquidationFactor + ) as totalCollateralValue + FROM `CollateralPositionSnapshot` + LEFT JOIN `CollateralPoolSnapshot` ON CollateralPositionSnapshot.underlyingTokenAddress = CollateralPoolSnapshot.underlyingTokenAddress + AND CollateralPositionSnapshot.poolAddress = CollateralPoolSnapshot.poolAddress + GROUP BY userAddress, + poolAddress +), +user_selected_collateral_position as ( + SELECT userAddress, + poolAddress, + SUM(collateralAmountNormalized) as selectedCollateralAmountNormalized, + SUM(collateralAmountUsd) as selectedCollateralAmountUsd, + SUM( + collateralAmountNormalized * CollateralPoolSnapshot.liquidationFactor + ) as selectedCollateralAmount, + SUM( + collateralAmountUsd * CollateralPoolSnapshot.liquidationFactor + ) as selectedCollateralValue + FROM `CollateralPositionSnapshot` + LEFT JOIN `CollateralPoolSnapshot` ON CollateralPositionSnapshot.underlyingTokenAddress = CollateralPoolSnapshot.underlyingTokenAddress + AND CollateralPositionSnapshot.poolAddress = CollateralPoolSnapshot.poolAddress + WHERE underlyingTokenSymbol= 'ETH' + GROUP BY userAddress, + poolAddress +), +calculations as(SELECT borrowedAmountUsd, + totalCollateralValue, + selectedCollateralAmountNormalized, + selectedCollateralAmountUsd, + -- ALREADY MULTIPLIED BY LIQUIDATION FACTOR + selectedCollateralAmount, + -- ALREADY MULTIPLIED BY LIQUIDATION FACTOR + COALESCE(selectedCollateralValue, 0) as selectedCollateralValue, + (totalCollateralValue - selectedCollateralValue) as otherCollateralValue, + (borrowedAmountUsd - otherCollateralValue) as diffDebt, + ROUND( + toFloat64(diffDebt) / toFloat64(selectedCollateralAmount) + ) as liqPrice +FROM user_position + LEFT JOIN user_collateral_positions ON user_position.userAddress = user_collateral_positions.userAddress + AND user_position.poolAddress = user_collateral_positions.poolAddress + LEFT JOIN user_selected_collateral_position ON user_position.userAddress = user_selected_collateral_position.userAddress + AND user_position.poolAddress = user_selected_collateral_position.poolAddress +WHERE selectedCollateralValue > 0 + AND diffDebt > 0 +ORDER BY liqPrice DESC) + +select +liqPrice, count(*) as count +FROM +calculations +GROUP BY liqPrice +ORDER BY liqPrice DESC \ No newline at end of file From 110d8fbba595697acc0c05227eba61375080833d Mon Sep 17 00:00:00 2001 From: martines3000 Date: Wed, 6 Nov 2024 09:09:12 +0100 Subject: [PATCH 5/8] chore: remove sql queries --- liquidations copy 2.sql | 69 -------------------------------------- liquidations copy.sql | 73 ----------------------------------------- liquidations.sql | 65 ------------------------------------ 3 files changed, 207 deletions(-) delete mode 100644 liquidations copy 2.sql delete mode 100644 liquidations copy.sql delete mode 100644 liquidations.sql diff --git a/liquidations copy 2.sql b/liquidations copy 2.sql deleted file mode 100644 index 12f980ed..00000000 --- a/liquidations copy 2.sql +++ /dev/null @@ -1,69 +0,0 @@ -with user_position as ( - SELECT userAddress, - poolAddress, - borrowedAmountUsd - FROM `BasePositionSnapshot` - WHERE borrowedAmountUsd > 0 -), -user_collateral_positions as ( - SELECT userAddress, - poolAddress, - SUM( - collateralAmountUsd * CollateralPoolSnapshot.liquidationFactor - ) as totalCollateralValue - FROM `CollateralPositionSnapshot` - LEFT JOIN `CollateralPoolSnapshot` ON CollateralPositionSnapshot.underlyingTokenAddress = CollateralPoolSnapshot.underlyingTokenAddress - AND CollateralPositionSnapshot.poolAddress = CollateralPoolSnapshot.poolAddress - GROUP BY userAddress, - poolAddress -), -user_selected_collateral_position as ( - SELECT userAddress, - poolAddress, - SUM(collateralAmountNormalized) as selectedCollateralAmountNormalized, - SUM(collateralAmountUsd) as selectedCollateralAmountUsd, - SUM( - collateralAmountNormalized * CollateralPoolSnapshot.liquidationFactor - ) as selectedCollateralAmount, - SUM( - collateralAmountUsd * CollateralPoolSnapshot.liquidationFactor - ) as selectedCollateralValue - FROM `CollateralPositionSnapshot` - LEFT JOIN `CollateralPoolSnapshot` ON CollateralPositionSnapshot.underlyingTokenAddress = CollateralPoolSnapshot.underlyingTokenAddress - AND CollateralPositionSnapshot.poolAddress = CollateralPoolSnapshot.poolAddress - WHERE underlyingTokenSymbol = 'ETH' - GROUP BY userAddress, - poolAddress -), -calculations as( - SELECT - borrowedAmountUsd, - totalCollateralValue, - selectedCollateralAmountNormalized, - selectedCollateralAmountUsd, - -- ALREADY MULTIPLIED BY LIQUIDATION FACTOR - selectedCollateralAmount, - -- ALREADY MULTIPLIED BY LIQUIDATION FACTOR - COALESCE(selectedCollateralValue, 0) as selectedCollateralValue, - (totalCollateralValue - selectedCollateralValue) as otherCollateralValue, - (borrowedAmountUsd - otherCollateralValue) as diffDebt, - ROUND( - toFloat64(diffDebt) / toFloat64(selectedCollateralAmount) / 10 - ) * 10 as liqPrice - FROM user_position - LEFT JOIN user_collateral_positions ON user_position.userAddress = user_collateral_positions.userAddress - AND user_position.poolAddress = user_collateral_positions.poolAddress - LEFT JOIN user_selected_collateral_position ON user_position.userAddress = user_selected_collateral_position.userAddress - AND user_position.poolAddress = user_selected_collateral_position.poolAddress - WHERE selectedCollateralValue > 0 - AND diffDebt > 0 -) - -SELECT - liqPrice, - count(*) as count, - ROUND(SUM(SUM(borrowedAmountUsd)) OVER (ORDER BY liqPrice DESC)) as cumulative_liquidated_amount, - SUM(count(*)) OVER (ORDER BY liqPrice DESC) as cumulative_count -FROM calculations -GROUP BY liqPrice -ORDER BY liqPrice DESC \ No newline at end of file diff --git a/liquidations copy.sql b/liquidations copy.sql deleted file mode 100644 index b43c42de..00000000 --- a/liquidations copy.sql +++ /dev/null @@ -1,73 +0,0 @@ -with tokens as ( - SELECT arrayJoin(['ETH']) as token -), -user_position as ( - SELECT - userAddress as user, - poolAddress as pool, - borrowedAmountUsd - FROM `BasePositionSnapshot` - WHERE borrowedAmountUsd > 0 -), -user_collateral_positions as ( - SELECT - CollateralPositionSnapshot.userAddress as user, - CollateralPositionSnapshot.poolAddress as pool, - SUM( - collateralAmountUsd * CollateralPoolSnapshot.liquidationFactor - ) as totalCollateralValue - FROM `CollateralPositionSnapshot` - LEFT JOIN `CollateralPoolSnapshot` ON CollateralPositionSnapshot.underlyingTokenAddress = CollateralPoolSnapshot.underlyingTokenAddress - AND CollateralPositionSnapshot.poolAddress = CollateralPoolSnapshot.poolAddress - GROUP BY CollateralPositionSnapshot.userAddress, - CollateralPositionSnapshot.poolAddress -), -user_selected_collateral_position as ( - SELECT - tokens.token as tokenSymbol, - CollateralPositionSnapshot.userAddress as user, - CollateralPositionSnapshot.poolAddress as pool, - SUM(CollateralPositionSnapshot.collateralAmountNormalized) as selectedCollateralAmountNormalized, - SUM(CollateralPositionSnapshot.collateralAmountUsd) as selectedCollateralAmountUsd, - SUM( - CollateralPositionSnapshot.collateralAmountNormalized * CollateralPoolSnapshot.liquidationFactor - ) as selectedCollateralAmount, - SUM( - CollateralPositionSnapshot.collateralAmountUsd * CollateralPoolSnapshot.liquidationFactor - ) as selectedCollateralValue - FROM tokens - CROSS JOIN `CollateralPositionSnapshot` - LEFT JOIN `CollateralPoolSnapshot` ON CollateralPositionSnapshot.underlyingTokenAddress = CollateralPoolSnapshot.underlyingTokenAddress - AND CollateralPositionSnapshot.poolAddress = CollateralPoolSnapshot.poolAddress - WHERE CollateralPositionSnapshot.underlyingTokenSymbol = tokens.token - GROUP BY tokens.token, CollateralPositionSnapshot.userAddress, CollateralPositionSnapshot.poolAddress -), -calculations as( - SELECT - usp.tokenSymbol, - up.borrowedAmountUsd, - ucp.totalCollateralValue, - usp.selectedCollateralAmountNormalized, - usp.selectedCollateralAmountUsd, - usp.selectedCollateralAmount, - COALESCE(usp.selectedCollateralValue, 0) as selectedCollateralValue, - (ucp.totalCollateralValue - COALESCE(usp.selectedCollateralValue, 0)) as otherCollateralValue, - (up.borrowedAmountUsd - (ucp.totalCollateralValue - COALESCE(usp.selectedCollateralValue, 0))) as diffDebt, - ROUND( - toFloat64(up.borrowedAmountUsd - (ucp.totalCollateralValue - COALESCE(usp.selectedCollateralValue, 0))) / - toFloat64(usp.selectedCollateralAmount) - ) as liqPrice - FROM user_position up - LEFT JOIN user_collateral_positions ucp ON up.user = ucp.user AND up.pool = ucp.pool - LEFT JOIN user_selected_collateral_position usp ON up.user = usp.user AND up.pool = usp.pool - WHERE COALESCE(usp.selectedCollateralValue, 0) > 0 - AND (up.borrowedAmountUsd - (ucp.totalCollateralValue - COALESCE(usp.selectedCollateralValue, 0))) > 0 - ORDER BY liqPrice DESC) - -SELECT - tokenSymbol, - liqPrice, - count(*) as count -FROM calculations -GROUP BY tokenSymbol, liqPrice -ORDER BY tokenSymbol, liqPrice DESC; \ No newline at end of file diff --git a/liquidations.sql b/liquidations.sql deleted file mode 100644 index 4b584799..00000000 --- a/liquidations.sql +++ /dev/null @@ -1,65 +0,0 @@ -with user_position as ( - SELECT userAddress, - poolAddress, - borrowedAmountUsd - FROM `BasePositionSnapshot` - WHERE borrowedAmountUsd > 0 -), -user_collateral_positions as ( - SELECT userAddress, - poolAddress, - SUM( - collateralAmountUsd * CollateralPoolSnapshot.liquidationFactor - ) as totalCollateralValue - FROM `CollateralPositionSnapshot` - LEFT JOIN `CollateralPoolSnapshot` ON CollateralPositionSnapshot.underlyingTokenAddress = CollateralPoolSnapshot.underlyingTokenAddress - AND CollateralPositionSnapshot.poolAddress = CollateralPoolSnapshot.poolAddress - GROUP BY userAddress, - poolAddress -), -user_selected_collateral_position as ( - SELECT userAddress, - poolAddress, - SUM(collateralAmountNormalized) as selectedCollateralAmountNormalized, - SUM(collateralAmountUsd) as selectedCollateralAmountUsd, - SUM( - collateralAmountNormalized * CollateralPoolSnapshot.liquidationFactor - ) as selectedCollateralAmount, - SUM( - collateralAmountUsd * CollateralPoolSnapshot.liquidationFactor - ) as selectedCollateralValue - FROM `CollateralPositionSnapshot` - LEFT JOIN `CollateralPoolSnapshot` ON CollateralPositionSnapshot.underlyingTokenAddress = CollateralPoolSnapshot.underlyingTokenAddress - AND CollateralPositionSnapshot.poolAddress = CollateralPoolSnapshot.poolAddress - WHERE underlyingTokenSymbol= 'ETH' - GROUP BY userAddress, - poolAddress -), -calculations as(SELECT borrowedAmountUsd, - totalCollateralValue, - selectedCollateralAmountNormalized, - selectedCollateralAmountUsd, - -- ALREADY MULTIPLIED BY LIQUIDATION FACTOR - selectedCollateralAmount, - -- ALREADY MULTIPLIED BY LIQUIDATION FACTOR - COALESCE(selectedCollateralValue, 0) as selectedCollateralValue, - (totalCollateralValue - selectedCollateralValue) as otherCollateralValue, - (borrowedAmountUsd - otherCollateralValue) as diffDebt, - ROUND( - toFloat64(diffDebt) / toFloat64(selectedCollateralAmount) - ) as liqPrice -FROM user_position - LEFT JOIN user_collateral_positions ON user_position.userAddress = user_collateral_positions.userAddress - AND user_position.poolAddress = user_collateral_positions.poolAddress - LEFT JOIN user_selected_collateral_position ON user_position.userAddress = user_selected_collateral_position.userAddress - AND user_position.poolAddress = user_selected_collateral_position.poolAddress -WHERE selectedCollateralValue > 0 - AND diffDebt > 0 -ORDER BY liqPrice DESC) - -select -liqPrice, count(*) as count -FROM -calculations -GROUP BY liqPrice -ORDER BY liqPrice DESC \ No newline at end of file From 09678fba54577e6b4737684576841d1f2189cbff Mon Sep 17 00:00:00 2001 From: martines3000 Date: Wed, 6 Nov 2024 09:12:56 +0100 Subject: [PATCH 6/8] fix: update asserts because we increased the initial eth amount in test wallets from 10 to 1000 --- contracts/market/tests/local_tests/scenarios/liquidation.rs | 4 ++-- .../local_tests/scenarios/multicall_absorb_buy_collateral.rs | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/market/tests/local_tests/scenarios/liquidation.rs b/contracts/market/tests/local_tests/scenarios/liquidation.rs index e687c1de..bb1d90b3 100644 --- a/contracts/market/tests/local_tests/scenarios/liquidation.rs +++ b/contracts/market/tests/local_tests/scenarios/liquidation.rs @@ -283,7 +283,7 @@ async fn absorb_and_liquidate() { // Wait for response let _: CallResponse<((), ())> = submitted_tx.response().await.unwrap(); let alice_balance = alice.get_asset_balance(ð.asset_id).await.unwrap(); - assert!(alice_balance == 10_999_999_997 * AMOUNT_COEFFICIENT); + assert!(alice_balance == 1000_999_999_997 * AMOUNT_COEFFICIENT); // check reserves let reserves = market @@ -569,7 +569,7 @@ async fn all_assets_liquidated() { // Check asset balance let balance = alice.get_asset_balance(ð.asset_id).await.unwrap(); - assert!(balance == 10_999_999_997 * AMOUNT_COEFFICIENT); + assert!(balance == 1000_999_999_997 * AMOUNT_COEFFICIENT); market .print_debug_state(&wallets, &usdc, ð) diff --git a/contracts/market/tests/local_tests/scenarios/multicall_absorb_buy_collateral.rs b/contracts/market/tests/local_tests/scenarios/multicall_absorb_buy_collateral.rs index 6f72ac06..cf141b11 100644 --- a/contracts/market/tests/local_tests/scenarios/multicall_absorb_buy_collateral.rs +++ b/contracts/market/tests/local_tests/scenarios/multicall_absorb_buy_collateral.rs @@ -221,7 +221,7 @@ async fn multicall_absorb_buy_collateral_test() { // Check asset balance let balance = chad.get_asset_balance(ð.asset_id).await.unwrap(); - assert!(balance == 10_998_986_826 - 1); // subtract oracle update fee + assert!(balance == 1000_998_986_826 - 1); // subtract oracle update fee market .print_debug_state(&wallets, &usdc, ð) From 7a692dbd5b003b1e99dcfd86d819534305c584f8 Mon Sep 17 00:00:00 2001 From: Vid Kersic Date: Thu, 7 Nov 2024 09:12:07 +0100 Subject: [PATCH 7/8] eth base: finish test --- .../tests/local_tests/main_test_eth_base.rs | 116 +++++++----------- contracts/market/tests/utils/mod.rs | 2 +- 2 files changed, 42 insertions(+), 76 deletions(-) diff --git a/contracts/market/tests/local_tests/main_test_eth_base.rs b/contracts/market/tests/local_tests/main_test_eth_base.rs index e3a870cb..34cca23f 100644 --- a/contracts/market/tests/local_tests/main_test_eth_base.rs +++ b/contracts/market/tests/local_tests/main_test_eth_base.rs @@ -371,7 +371,13 @@ async fn main_test() { // ==================== Step #8 ==================== // πŸ‘› Wallet: Bob 🀡 // πŸ€™ Call: buy_collateral - // πŸ’° Amount: 1.94 ETH + // πŸ’° Amount: ~2.77 ETH + + // Reset prices back to old values + market + .update_price_feeds_if_necessary(&[&oracle.instance], &price_data_update_old) + .await + .unwrap(); let reserves = market .with_account(&bob) @@ -396,13 +402,6 @@ async fn main_test() { let log_amount = format!("{} ETH", amount as f64 / scale_9); print_case_title(8, "Bob", "buy_collateral", log_amount.as_str()); - // Reset prices back to old values - // This is used to test that multi_call_handler works correctly - market - .update_price_feeds_if_necessary(&[&oracle.instance], &price_data_update_old) - .await - .unwrap(); - // Prepare calls for multi_call_handler let tx_policies = TxPolicies::default().with_script_gas_limit(1_000_000); @@ -414,7 +413,7 @@ async fn main_test() { let update_balance_call = market .instance .methods() - .update_price_feeds_if_necessary(price_data_update.clone()) + .update_price_feeds_if_necessary(price_data_update_old.clone()) .with_contracts(&[&oracle.instance]) .with_tx_policies(tx_policies) .call_params(call_params_update_price) @@ -448,7 +447,7 @@ async fn main_test() { // Check let balance = bob.get_asset_balance(&usdt.asset_id).await.unwrap(); - assert!(balance == parse_units(10000, usdt.decimals) * AMOUNT_COEFFICIENT); + assert!(balance == parse_units(10000, usdt.decimals) * AMOUNT_COEFFICIENT - 2); // -2 because some ETH is spent on tx fees market .print_debug_state(&wallets, ð, &usdt) @@ -548,71 +547,38 @@ async fn main_test() { // // ================================================= // // ==================== Step #11 ==================== - // // πŸ‘› Wallet: Alice πŸ§› - // // πŸ€™ Call: withdraw_base - // // πŸ’° Amount: 17.276598 USDC - - // let (amount, _) = market.get_user_supply_borrow(alice_account).await.unwrap(); - // let log_amount = format!("{} USDC", amount as f64 / scale_6); - // print_case_title(11, "Alice", "withdraw_base", log_amount.as_str()); - - // // Alice calls withdraw_base - // market - // .with_account(&alice) - // .await - // .unwrap() - // .withdraw_base( - // &[&oracle.instance], - // amount.try_into().unwrap(), - // &price_data_update, - // ) - // .await - // .unwrap(); - - // // USDC balance check - // let (supplied, _) = market.get_user_supply_borrow(alice_account).await.unwrap(); - // assert!(supplied == 0); - - // market - // .print_debug_state(&wallets, &usdc, &uni) - // .await - // .unwrap(); - // market.debug_increment_timestamp().await.unwrap(); - - // // ================================================= - // // ==================== Step #12 ==================== // // πŸ‘› Wallet: Chad 🀡 // // πŸ€™ Call: withdraw_collateral - // // πŸ’° Amount: 270 UNI - - // let amount = market - // .get_user_collateral(chad_account, uni.asset_id) - // .await - // .unwrap() - // .value; - // let log_amount = format!("{} UNI", amount as f64 / scale_9); - // print_case_title(12, "Chad", "withdraw_collateral", log_amount.as_str()); - - // // Chad calls withdraw_collateral - // market - // .with_account(&chad) - // .await - // .unwrap() - // .withdraw_collateral( - // &[&oracle.instance], - // uni.asset_id, - // amount.try_into().unwrap(), - // &price_data_update, - // ) - // .await - // .unwrap(); - - // // UNI balance check - // let balance = chad.get_asset_balance(&uni.asset_id).await.unwrap(); - // assert!(balance == amount); - - // market - // .print_debug_state(&wallets, &usdc, &uni) - // .await - // .unwrap(); + // // πŸ’° Amount: 15000 USDT + + let amount = market + .get_user_collateral(chad_account, usdt.asset_id) + .await + .unwrap() + .value; + let log_amount = format!("{} USDT", amount as f64 / scale_6); + print_case_title(12, "Chad", "withdraw_collateral", log_amount.as_str()); + + // Chad calls withdraw_collateral + market + .with_account(&chad) + .await + .unwrap() + .withdraw_collateral( + &[&oracle.instance], + usdt.asset_id, + amount.try_into().unwrap(), + &price_data_update, + ) + .await + .unwrap(); + + // USDT balance check + let balance = chad.get_asset_balance(&usdt.asset_id).await.unwrap(); + assert!(balance == amount); + + market + .print_debug_state(&wallets, ð, &usdt) + .await + .unwrap(); } diff --git a/contracts/market/tests/utils/mod.rs b/contracts/market/tests/utils/mod.rs index 49b9fec5..c95a6756 100644 --- a/contracts/market/tests/utils/mod.rs +++ b/contracts/market/tests/utils/mod.rs @@ -1,7 +1,7 @@ use chrono::Utc; use fuels::accounts::wallet::WalletUnlocked; use fuels::test_helpers::{ - launch_custom_provider_and_get_wallets, ChainConfig, NodeConfig, Trigger, WalletsConfig + launch_custom_provider_and_get_wallets, NodeConfig, Trigger, WalletsConfig }; use fuels::types::{Bits256, ContractId, Identity}; use market_sdk::{get_market_config, Market}; From e92d648a8db262cce2071c6cb144d6805cac964f Mon Sep 17 00:00:00 2001 From: Vid Kersic Date: Thu, 7 Nov 2024 09:20:24 +0100 Subject: [PATCH 8/8] chore: rebase issues --- .../tests/local_tests/scenarios/update_curve_parameters.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/contracts/market/tests/local_tests/scenarios/update_curve_parameters.rs b/contracts/market/tests/local_tests/scenarios/update_curve_parameters.rs index 6462d0b4..82f233cb 100644 --- a/contracts/market/tests/local_tests/scenarios/update_curve_parameters.rs +++ b/contracts/market/tests/local_tests/scenarios/update_curve_parameters.rs @@ -1,6 +1,4 @@ -use std::str::FromStr; - -use crate::utils::{print_case_title, setup, TestData}; +use crate::utils::{print_case_title, setup, TestBaseAsset, TestData}; use chrono::Utc; use fuels::{ prelude::ViewOnlyAccount, @@ -42,7 +40,7 @@ async fn main_test() { publish_time, prices, .. - } = setup(None).await; + } = setup(None, TestBaseAsset::USDC).await; let price_data_update = PriceDataUpdate { update_fee: 1,