From 0529119813c8885ebd30b5a45ea16dccc61eb470 Mon Sep 17 00:00:00 2001 From: esteblock Date: Tue, 12 Nov 2024 09:20:35 -0300 Subject: [PATCH 01/28] add fees and not mock auths todo tests and use checked mul and div@ --- apps/contracts/vault/src/lib.rs | 9 +-- apps/contracts/vault/src/test.rs | 1 + apps/contracts/vault/src/test/fees.rs | 6 ++ apps/contracts/vault/src/test/withdraw.rs | 85 ++++++++++++++++++++++- apps/contracts/vault/src/utils.rs | 8 ++- 5 files changed, 96 insertions(+), 13 deletions(-) create mode 100644 apps/contracts/vault/src/test/fees.rs diff --git a/apps/contracts/vault/src/lib.rs b/apps/contracts/vault/src/lib.rs index ece2aec1..973aad06 100755 --- a/apps/contracts/vault/src/lib.rs +++ b/apps/contracts/vault/src/lib.rs @@ -308,7 +308,7 @@ impl VaultTrait for DeFindexVault { shares_amount: i128, from: Address) -> Result, ContractError> { - extend_instance_ttl(&e); + extend_instance_ttl(&e); check_initialized(&e)?; check_nonnegative_amount(shares_amount)?; from.require_auth(); @@ -319,13 +319,6 @@ impl VaultTrait for DeFindexVault { // Check if the user has enough dfTokens. // TODO, we can move this error into the internal_burn function let df_user_balance = VaultToken::balance(e.clone(), from.clone()); if df_user_balance < shares_amount { - // return vec[df_user_balance, shares amount] - // let mut result: Vec = Vec::new(&e); - // result.push_back(df_user_balance); - // result.push_back(shares_amount); - // return Ok(result); - - return Err(ContractError::InsufficientBalance); } diff --git a/apps/contracts/vault/src/test.rs b/apps/contracts/vault/src/test.rs index f696f7ee..4b4cfd7a 100755 --- a/apps/contracts/vault/src/test.rs +++ b/apps/contracts/vault/src/test.rs @@ -174,3 +174,4 @@ mod invest; mod withdraw; mod emergency_withdraw; mod rebalance; +mod fees; diff --git a/apps/contracts/vault/src/test/fees.rs b/apps/contracts/vault/src/test/fees.rs new file mode 100644 index 00000000..5747834b --- /dev/null +++ b/apps/contracts/vault/src/test/fees.rs @@ -0,0 +1,6 @@ + +// test fees are correctly calculated and harvested (todo) +#[test] +fn test_fees() { + todo!(); +} diff --git a/apps/contracts/vault/src/test/withdraw.rs b/apps/contracts/vault/src/test/withdraw.rs index b5fe4ef8..12b4dee9 100644 --- a/apps/contracts/vault/src/test/withdraw.rs +++ b/apps/contracts/vault/src/test/withdraw.rs @@ -12,8 +12,83 @@ use crate::test::{ DeFindexVaultTest, }; + +#[test] +fn test_withdraw_not_yet_initialized() { + let test = DeFindexVaultTest::setup(); + let users = DeFindexVaultTest::generate_random_users(&test.env, 1); + + let result = test.defindex_contract.try_withdraw(&100i128, &users[0]); + assert_eq!(result, Err(Ok(ContractError::NotInitialized))); +} + +// check that withdraw with negative amount after initialized returns error +#[test] +fn test_withdraw_negative_amount() { + let test = DeFindexVaultTest::setup(); + test.env.mock_all_auths(); + let strategy_params_token0 = create_strategy_params_token0(&test); + let assets: Vec = sorobanvec![ + &test.env, + AssetStrategySet { + address: test.token0.address.clone(), + strategies: strategy_params_token0.clone() + } + ]; + + test.defindex_contract.initialize( + &assets, + &test.manager, + &test.emergency_manager, + &test.vault_fee_receiver, + &2000u32, + &test.defindex_protocol_receiver, + &test.defindex_factory, + &String::from_str(&test.env, "dfToken"), + &String::from_str(&test.env, "DFT"), + ); + + let users = DeFindexVaultTest::generate_random_users(&test.env, 1); + + let result = test.defindex_contract.try_withdraw(&-100i128, &users[0]); + assert_eq!(result, Err(Ok(ContractError::NegativeNotAllowed))); +} + + +// check that withdraw without balance after initialized returns error InsufficientBalance #[test] -fn test_withdraw_from_idle_success() { +fn test_withdraw_insufficient_balance() { + let test = DeFindexVaultTest::setup(); + test.env.mock_all_auths(); + let strategy_params_token0 = create_strategy_params_token0(&test); + let assets: Vec = sorobanvec![ + &test.env, + AssetStrategySet { + address: test.token0.address.clone(), + strategies: strategy_params_token0.clone() + } + ]; + + test.defindex_contract.initialize( + &assets, + &test.manager, + &test.emergency_manager, + &test.vault_fee_receiver, + &2000u32, + &test.defindex_protocol_receiver, + &test.defindex_factory, + &String::from_str(&test.env, "dfToken"), + &String::from_str(&test.env, "DFT"), + ); + + let users = DeFindexVaultTest::generate_random_users(&test.env, 1); + + let result = test.defindex_contract.try_withdraw(&100i128, &users[0]); + assert_eq!(result, Err(Ok(ContractError::InsufficientBalance))); +} + +#[test] +fn test_withdraw_from_idle_success() { let test = DeFindexVaultTest::setup(); test.env.mock_all_auths(); let strategy_params_token0 = create_strategy_params_token0(&test); @@ -198,4 +273,10 @@ fn test_withdraw_from_strategy_success() { let user_balance = test.token0.balance(&users[0]); assert_eq!(user_balance, amount - 1000); } - \ No newline at end of file + + +// test withdraw without mock all auths +#[test] +fn test_withdraw_from_strategy_success_no_mock_all_auths() { + todo!(); +} \ No newline at end of file diff --git a/apps/contracts/vault/src/utils.rs b/apps/contracts/vault/src/utils.rs index db1360ed..84fedc29 100644 --- a/apps/contracts/vault/src/utils.rs +++ b/apps/contracts/vault/src/utils.rs @@ -68,15 +68,17 @@ pub fn calculate_withdrawal_amounts( pub fn calculate_asset_amounts_for_dftokens( env: &Env, - df_token_amount: i128, + shares_amount: i128, ) -> Map { let mut asset_amounts: Map = Map::new(&env); let total_supply = VaultToken::total_supply(env.clone()); let total_managed_funds = fetch_total_managed_funds(&env); - // Iterate over each asset and calculate the corresponding amount based on df_token_amount + // Iterate over each asset and calculate the corresponding amount based on shares_amount for (asset_address, amount) in total_managed_funds.iter() { - let asset_amount = (amount * df_token_amount) / total_supply; + let asset_amount = amount + .checked_mul(shares_amount).unwrap_or_else(|| panic_with_error!(&env, ContractError::ArithmeticError)) + .checked_div(total_supply).unwrap_or_else(|| panic_with_error!(&env, ContractError::ArithmeticError)); asset_amounts.set(asset_address.clone(), asset_amount); } From 82a58e21247a6c1bd47d2cd1b8eec62619f24d4d Mon Sep 17 00:00:00 2001 From: esteblock Date: Tue, 12 Nov 2024 09:31:03 -0300 Subject: [PATCH 02/28] improve name get_asset_amounts_per_shares --- apps/contracts/vault/src/interface.rs | 15 ++++++++--- apps/contracts/vault/src/lib.rs | 22 +++++++++++----- apps/contracts/vault/src/utils.rs | 37 +++++++++++++++++++++------ 3 files changed, 57 insertions(+), 17 deletions(-) diff --git a/apps/contracts/vault/src/interface.rs b/apps/contracts/vault/src/interface.rs index 7dd40f1f..9c388d91 100644 --- a/apps/contracts/vault/src/interface.rs +++ b/apps/contracts/vault/src/interface.rs @@ -195,9 +195,18 @@ pub trait VaultTrait { /// * `Map` - A map of asset addresses to their total idle amounts. fn fetch_current_idle_funds(e: &Env) -> Map; - // TODO: DELETE THIS, USED FOR TESTING - /// Temporary method for testing purposes. - fn get_asset_amounts_for_dftokens(e: Env, df_token: i128) -> Map; + // Calculates the corresponding amounts of each asset per a given number of vault shares. + /// This function extends the contract's time-to-live and calculates how much of each asset corresponds + /// per the provided number of vault shares (`vault_shares`). It provides proportional allocations for each asset + /// in the vault relative to the specified shares. + /// + /// # Arguments + /// * `e` - The current environment reference. + /// * `vault_shares` - The number of vault shares for which the corresponding asset amounts are calculated. + /// + /// # Returns + /// * `Map` - A map containing each asset address and its corresponding proportional amount. + fn get_asset_amounts_per_shares(e: Env, vault_shares: i128) -> Map; } pub trait AdminInterfaceTrait { diff --git a/apps/contracts/vault/src/lib.rs b/apps/contracts/vault/src/lib.rs index 973aad06..513b438c 100755 --- a/apps/contracts/vault/src/lib.rs +++ b/apps/contracts/vault/src/lib.rs @@ -43,7 +43,7 @@ use strategies::{ }; use token::{internal_burn, internal_mint, write_metadata, VaultToken}; use utils::{ - calculate_asset_amounts_for_dftokens, calculate_deposit_amounts_and_shares_to_mint, + calculate_asset_amounts_per_vault_shares, calculate_deposit_amounts_and_shares_to_mint, calculate_withdrawal_amounts, check_initialized, check_nonnegative_amount, }; @@ -323,7 +323,7 @@ impl VaultTrait for DeFindexVault { } // Calculate the withdrawal amounts for each asset based on the dfToken amount - let asset_amounts = calculate_asset_amounts_for_dftokens(&e, shares_amount); + let asset_amounts = calculate_asset_amounts_per_vault_shares(&e, shares_amount); // Burn the dfTokens after calculating the withdrawal amounts (so total supply is correct) internal_burn(e.clone(), from.clone(), shares_amount); @@ -555,12 +555,22 @@ impl VaultTrait for DeFindexVault { fetch_current_idle_funds(e) } - // TODO: DELETE THIS, USED FOR TESTING - /// Temporary method for testing purposes. - fn get_asset_amounts_for_dftokens(e: Env, df_tokens: i128) -> Map { + // Calculates the corresponding amounts of each asset per a given number of vault shares. + /// This function extends the contract's time-to-live and calculates how much of each asset corresponds + /// per the provided number of vault shares (`vault_shares`). It provides proportional allocations for each asset + /// in the vault relative to the specified shares. + /// + /// # Arguments + /// * `e` - The current environment reference. + /// * `vault_shares` - The number of vault shares for which the corresponding asset amounts are calculated. + /// + /// # Returns + /// * `Map` - A map containing each asset address and its corresponding proportional amount. + fn get_asset_amounts_per_shares(e: Env, vault_shares: i128) -> Map { extend_instance_ttl(&e); - calculate_asset_amounts_for_dftokens(&e, df_tokens) + calculate_asset_amounts_per_vault_shares(&e, vault_shares) } + } #[contractimpl] diff --git a/apps/contracts/vault/src/utils.rs b/apps/contracts/vault/src/utils.rs index 84fedc29..d4552cb2 100644 --- a/apps/contracts/vault/src/utils.rs +++ b/apps/contracts/vault/src/utils.rs @@ -66,19 +66,40 @@ pub fn calculate_withdrawal_amounts( withdrawal_amounts } -pub fn calculate_asset_amounts_for_dftokens( +/// Calculates the corresponding amounts of each asset per given number of vault shares. +/// This function takes the number of vault shares (`shares_amount`) and computes how much of each asset in the vault +/// corresponds to those shares, based on the total managed funds and the total supply of vault shares. +/// +/// # Arguments +/// * `env` - Reference to the current environment. +/// * `shares_amount` - The number of vault shares for which the equivalent asset amounts are being calculated. +/// +/// # Returns +/// * `Map` - A map of asset addresses to their respective amounts, proportional to the `shares_amount`. +/// +/// # Errors +/// * Panics with `ContractError::ArithmeticError` if there are any issues with multiplication or division, +/// such as overflow or division by zero. +pub fn calculate_asset_amounts_per_vault_shares( env: &Env, shares_amount: i128, ) -> Map { - let mut asset_amounts: Map = Map::new(&env); - let total_supply = VaultToken::total_supply(env.clone()); - let total_managed_funds = fetch_total_managed_funds(&env); + let mut asset_amounts: Map = Map::new(env); + + // Fetch the total supply of vault shares and the total managed funds for each asset + let total_shares_supply = VaultToken::total_supply(env.clone()); + let total_managed_funds = fetch_total_managed_funds(env); // Iterate over each asset and calculate the corresponding amount based on shares_amount - for (asset_address, amount) in total_managed_funds.iter() { - let asset_amount = amount - .checked_mul(shares_amount).unwrap_or_else(|| panic_with_error!(&env, ContractError::ArithmeticError)) - .checked_div(total_supply).unwrap_or_else(|| panic_with_error!(&env, ContractError::ArithmeticError)); + for (asset_address, total_asset_amount) in total_managed_funds.iter() { + // Calculate the proportional asset amount per the given number of shares + let asset_amount = total_asset_amount + .checked_mul(shares_amount) + .unwrap_or_else(|| panic_with_error!(env, ContractError::ArithmeticError)) + .checked_div(total_shares_supply) + .unwrap_or_else(|| panic_with_error!(env, ContractError::ArithmeticError)); + + // Set the calculated asset amount for the given asset address asset_amounts.set(asset_address.clone(), asset_amount); } From 340c4d0f4ba2e2bbafe44b1756810dc446eeaf8a Mon Sep 17 00:00:00 2001 From: esteblock Date: Tue, 12 Nov 2024 15:22:25 -0300 Subject: [PATCH 03/28] refactor and rename calculate_asset_amounts_per_vault_shares --- apps/contracts/vault/src/error.rs | 1 + apps/contracts/vault/src/funds.rs | 2 +- apps/contracts/vault/src/interface.rs | 3 +- apps/contracts/vault/src/lib.rs | 14 +- apps/contracts/vault/src/test.rs | 1 + apps/contracts/vault/src/test/deposit.rs | 3 +- .../src/test/get_asset_amounts_per_shares.rs | 165 ++++++++++++++++++ apps/contracts/vault/src/utils.rs | 23 ++- 8 files changed, 195 insertions(+), 17 deletions(-) create mode 100644 apps/contracts/vault/src/test/get_asset_amounts_per_shares.rs diff --git a/apps/contracts/vault/src/error.rs b/apps/contracts/vault/src/error.rs index 016d90d1..9406c87a 100644 --- a/apps/contracts/vault/src/error.rs +++ b/apps/contracts/vault/src/error.rs @@ -24,6 +24,7 @@ pub enum ContractError { WrongInvestmentLength = 119, WrongAssetAddress = 122, WrongStrategiesLength = 123, + AmountOverTotalSupply = 124, // Arithmetic Errors (12x) diff --git a/apps/contracts/vault/src/funds.rs b/apps/contracts/vault/src/funds.rs index 8d19cee9..1c394dbf 100644 --- a/apps/contracts/vault/src/funds.rs +++ b/apps/contracts/vault/src/funds.rs @@ -16,7 +16,7 @@ use crate::strategies::get_strategy_client; /// /// # Returns /// * The idle balance (i128) of the asset in the current contract address. -fn fetch_idle_funds_for_asset(e: &Env, asset: &Address) -> i128 { +pub fn fetch_idle_funds_for_asset(e: &Env, asset: &Address) -> i128 { TokenClient::new(e, &asset).balance(&e.current_contract_address()) } diff --git a/apps/contracts/vault/src/interface.rs b/apps/contracts/vault/src/interface.rs index 9c388d91..f546484f 100644 --- a/apps/contracts/vault/src/interface.rs +++ b/apps/contracts/vault/src/interface.rs @@ -206,7 +206,8 @@ pub trait VaultTrait { /// /// # Returns /// * `Map` - A map containing each asset address and its corresponding proportional amount. - fn get_asset_amounts_per_shares(e: Env, vault_shares: i128) -> Map; + fn get_asset_amounts_per_shares(e: Env, vault_shares: i128) -> Result, ContractError>; + } pub trait AdminInterfaceTrait { diff --git a/apps/contracts/vault/src/lib.rs b/apps/contracts/vault/src/lib.rs index 513b438c..99af6687 100755 --- a/apps/contracts/vault/src/lib.rs +++ b/apps/contracts/vault/src/lib.rs @@ -322,10 +322,12 @@ impl VaultTrait for DeFindexVault { return Err(ContractError::InsufficientBalance); } - // Calculate the withdrawal amounts for each asset based on the dfToken amount - let asset_amounts = calculate_asset_amounts_per_vault_shares(&e, shares_amount); + // Calculate the withdrawal amounts for each asset based on the share amounts + // Map + let asset_amounts = calculate_asset_amounts_per_vault_shares(&e, shares_amount)?; - // Burn the dfTokens after calculating the withdrawal amounts (so total supply is correct) + // Burn the shares after calculating the withdrawal amounts (so total supply is correct + // but before withdrawing to avoid reentrancy attacks) internal_burn(e.clone(), from.clone(), shares_amount); // Create a map to store the total amounts to transfer for each asset address @@ -334,7 +336,7 @@ impl VaultTrait for DeFindexVault { // Get idle funds for each asset (Map) let idle_funds = fetch_current_idle_funds(&e); - // Loop through each asset and handle the withdrawal + // Loop through each asset to withdraw and handle the withdrawal for (asset_address, required_amount) in asset_amounts.iter() { // Check idle funds for this asset let idle_balance = idle_funds.get(asset_address.clone()).unwrap_or(0); @@ -566,9 +568,9 @@ impl VaultTrait for DeFindexVault { /// /// # Returns /// * `Map` - A map containing each asset address and its corresponding proportional amount. - fn get_asset_amounts_per_shares(e: Env, vault_shares: i128) -> Map { + fn get_asset_amounts_per_shares(e: Env, vault_shares: i128) -> Result, ContractError> { extend_instance_ttl(&e); - calculate_asset_amounts_per_vault_shares(&e, vault_shares) + Ok(calculate_asset_amounts_per_vault_shares(&e, vault_shares)?) } } diff --git a/apps/contracts/vault/src/test.rs b/apps/contracts/vault/src/test.rs index 4b4cfd7a..9406d45a 100755 --- a/apps/contracts/vault/src/test.rs +++ b/apps/contracts/vault/src/test.rs @@ -175,3 +175,4 @@ mod withdraw; mod emergency_withdraw; mod rebalance; mod fees; +mod get_asset_amounts_per_shares; \ No newline at end of file diff --git a/apps/contracts/vault/src/test/deposit.rs b/apps/contracts/vault/src/test/deposit.rs index 5b9ffd6f..69d2fffd 100644 --- a/apps/contracts/vault/src/test/deposit.rs +++ b/apps/contracts/vault/src/test/deposit.rs @@ -703,5 +703,4 @@ fn deposit_several_assets_min_greater_than_optimal() { assert_eq!(deposit_result, Err(Ok(ContractError::InsufficientAmount))); -} - +} \ No newline at end of file diff --git a/apps/contracts/vault/src/test/get_asset_amounts_per_shares.rs b/apps/contracts/vault/src/test/get_asset_amounts_per_shares.rs new file mode 100644 index 00000000..553858cc --- /dev/null +++ b/apps/contracts/vault/src/test/get_asset_amounts_per_shares.rs @@ -0,0 +1,165 @@ +use soroban_sdk::{vec as sorobanvec, String, Vec, Map}; + +use crate::test::defindex_vault::{AssetStrategySet, ContractError}; +use crate::test::{ + create_strategy_params_token0, create_strategy_params_token1, DeFindexVaultTest, +}; + + + +// test get_asset_amounts_per_shares function after every deposit +// do a bunch of deposits with different ratios and check that shares are calculated correctly +#[test] +fn deposit_several_assets_get_asset_amounts_per_shares() { + let test = DeFindexVaultTest::setup(); + test.env.mock_all_auths(); + let strategy_params_token0 = create_strategy_params_token0(&test); + let strategy_params_token1 = create_strategy_params_token1(&test); + + // initialize with 2 assets + let assets: Vec = sorobanvec![ + &test.env, + AssetStrategySet { + address: test.token0.address.clone(), + strategies: strategy_params_token0.clone() + }, + AssetStrategySet { + address: test.token1.address.clone(), + strategies: strategy_params_token1.clone() + } + ]; + + test.defindex_contract.initialize( + &assets, + &test.manager, + &test.emergency_manager, + &test.vault_fee_receiver, + &2000u32, + &test.defindex_protocol_receiver, + &test.defindex_factory, + &String::from_str(&test.env, "dfToken"), + &String::from_str(&test.env, "DFT"), + ); + + let amount0 = 123456789i128; + let amount1 = 987654321i128; + + let users = DeFindexVaultTest::generate_random_users(&test.env, 2); + + // Balances before deposit + test.token0_admin_client.mint(&users[0], &amount0); + test.token1_admin_client.mint(&users[0], &amount1); + let user_balance0 = test.token0.balance(&users[0]); + assert_eq!(user_balance0, amount0); + let user_balance1 = test.token1.balance(&users[0]); + assert_eq!(user_balance1, amount1); + + let df_balance = test.defindex_contract.balance(&users[0]); + assert_eq!(df_balance, 0i128); + + // deposit + test.defindex_contract.deposit( + &sorobanvec![&test.env, amount0, amount1], + &sorobanvec![&test.env, amount0, amount1], + &users[0], + ); + + // function is fn get_asset_amounts_per_shares(e: Env, vault_shares: i128) -> Map + // get several results of the function using different vault_shares + let result1 = test.defindex_contract.get_asset_amounts_per_shares(&0i128); + let result2 = test.defindex_contract.get_asset_amounts_per_shares(&1000i128); + let result3 = test.defindex_contract.get_asset_amounts_per_shares(&2000i128); + let result4 = test.defindex_contract.get_asset_amounts_per_shares(&3000i128); + let result5 = test.defindex_contract.get_asset_amounts_per_shares(&4000i128); + let result6 = test.defindex_contract.get_asset_amounts_per_shares(&5000i128); + + // calculate result1_should by hand (put aritmentic as a comment) and check that results are ok + // result1_should = {token0: 0, token1: 0} + let mut result1_should = Map::new(&test.env); + result1_should.set(test.token0.address.clone(), 0i128); + result1_should.set(test.token1.address.clone(), 0i128); + assert_eq!(result1, result1_should); + + // next we will consider that total shares are amount0 + amount1 = 123456789 + 987654321 = 1111111110 + // and we will calculate the shares for each asset + // amount should 1 for token0: + // amount0 * shares 0 = 123456789 * 1000 = 123456789000 + // amount 0 * shares 0 / total supply = 123456789000 / 1111111110 = 111.111110211 + // because truncating, amount should be 111 + + // amount should 1 for token1: + // amount1 * shares 0 = 987654321 * 1000 = 987654321000 + // amount 1 * shares 0 / total supply = 987654321000 / 1111111110 = 888.888889789 + // because truncating, amount should be 888 + // result2_should = {token0: 111, token1: 888} + let mut result2_should = Map::new(&test.env); + result2_should.set(test.token0.address.clone(), 111i128); + result2_should.set(test.token1.address.clone(), 888i128); + assert_eq!(result2, result2_should); + + // amount should 2 for token0: + // amount0 * shares 0 = 123456789 * 2000 = 246913578000 + // amount 0 * shares 0 / total supply = 246913578000 / 1111111110 = 222.222220422 + // because truncating, amount should be 222 + + // amount should 2 for token1: + // amount1 * shares 0 = 987654321 * 2000 = 1975308642000 + // amount 1 * shares 0 / total supply = 1975308642000 / 1111111110 = 1777.777779578 + // because truncating, amount should be 1777 + // result3_should = {token0: 222, token1: 1777} + let mut result3_should = Map::new(&test.env); + result3_should.set(test.token0.address.clone(), 222i128); + result3_should.set(test.token1.address.clone(), 1777i128); + assert_eq!(result3, result3_should); + + // amount should 3 for token0: + // amount0 * shares 0 = 123456789 * 3000 = 370370367000 + // amount 0 * shares 0 / total supply = 370370367000 / 1111111110 = 333.333330633 + // because truncating, amount should be 333 + + // amount should 3 for token1: + // amount1 * shares 0 = 987654321 * 3000 = 2962962963000 + // amount 1 * shares 0 / total supply = 2962962963000 / 1111111110 = 2666.666670633 + // because truncating, amount should be 2666 + // result4_should = {token0: 333, token1: 2666} + let mut result4_should = Map::new(&test.env); + result4_should.set(test.token0.address.clone(), 333i128); + result4_should.set(test.token1.address.clone(), 2666i128); + assert_eq!(result4, result4_should); + + // amount should 4 for token0: + // amount0 * shares 0 = 123456789 * 4000 = 493827156000 + // amount 0 * shares 0 / total supply = 493827156000 / 1111111110 = 444.444440844 + // because truncating, amount should be 444 + + // amount should 4 for token1: + // amount1 * shares 0 = 987654321 * 4000 = 3950617284000 + // amount 1 * shares 0 / total supply = 3950617284000 / 1111111110 = 3555.555561844 + // because truncating, amount should be 3555 + // result5_should = {token0: 444, token1: 3555} + let mut result5_should = Map::new(&test.env); + result5_should.set(test.token0.address.clone(), 444i128); + result5_should.set(test.token1.address.clone(), 3555i128); + assert_eq!(result5, result5_should); + + // amount should 5 for token0: + // amount0 * shares 0 = 123456789 * 5000 = 617283945000 + // amount 0 * shares 0 / total supply = 617283945000 / 1111111110 = 555.555550055 + // because truncating, amount should be 555 + + // amount should 5 for token1: + // amount1 * shares 0 = 987654321 * 5000 = 4938271605000 + // amount 1 * shares 0 / total supply = 4938271605000 / 1111111110 = 4444.444450055 + // because truncating, amount should be 4444 + // result6_should = {token0: 555, token1: 4444} + let mut result6_should = Map::new(&test.env); + result6_should.set(test.token0.address.clone(), 555i128); + result6_should.set(test.token1.address.clone(), 4444i128); + assert_eq!(result6, result6_should); + + // ************************************************* + // now we will consider an amount over total supply , we should get error AmountOverTotalSupply + let result7 = test.defindex_contract.try_get_asset_amounts_per_shares(&1111111111i128); + assert_eq!(result7, Err(Ok(ContractError::AmountOverTotalSupply))); + +} \ No newline at end of file diff --git a/apps/contracts/vault/src/utils.rs b/apps/contracts/vault/src/utils.rs index d4552cb2..db541192 100644 --- a/apps/contracts/vault/src/utils.rs +++ b/apps/contracts/vault/src/utils.rs @@ -83,27 +83,36 @@ pub fn calculate_withdrawal_amounts( pub fn calculate_asset_amounts_per_vault_shares( env: &Env, shares_amount: i128, -) -> Map { +) -> Result, ContractError> { let mut asset_amounts: Map = Map::new(env); // Fetch the total supply of vault shares and the total managed funds for each asset let total_shares_supply = VaultToken::total_supply(env.clone()); let total_managed_funds = fetch_total_managed_funds(env); + // if shares amount over total supply, return error AmountOverTotalSupply + if shares_amount > total_shares_supply { + return Err(ContractError::AmountOverTotalSupply); + } + // Iterate over each asset and calculate the corresponding amount based on shares_amount for (asset_address, total_asset_amount) in total_managed_funds.iter() { // Calculate the proportional asset amount per the given number of shares - let asset_amount = total_asset_amount - .checked_mul(shares_amount) - .unwrap_or_else(|| panic_with_error!(env, ContractError::ArithmeticError)) - .checked_div(total_shares_supply) - .unwrap_or_else(|| panic_with_error!(env, ContractError::ArithmeticError)); + let asset_amount = if total_shares_supply != 0 { + total_asset_amount + .checked_mul(shares_amount) + .ok_or(ContractError::ArithmeticError)? + .checked_div(total_shares_supply) + .ok_or(ContractError::ArithmeticError)? + } else { + return Err(ContractError::AmountOverTotalSupply); + }; // Set the calculated asset amount for the given asset address asset_amounts.set(asset_address.clone(), asset_amount); } - asset_amounts + return Ok(asset_amounts); } // pub fn calculate_dftokens_from_asset_amounts( From 9a0fab3290eb58c0a5c64ed9a59389590a6fe858 Mon Sep 17 00:00:00 2001 From: esteblock Date: Tue, 12 Nov 2024 15:23:40 -0300 Subject: [PATCH 04/28] use fetch_idle_funds_for_asset in withdraw instead --- apps/contracts/vault/src/lib.rs | 40 ++++++++++++--------- apps/contracts/vault/src/test/initialize.rs | 8 ----- 2 files changed, 23 insertions(+), 25 deletions(-) diff --git a/apps/contracts/vault/src/lib.rs b/apps/contracts/vault/src/lib.rs index 99af6687..ceb4e3f4 100755 --- a/apps/contracts/vault/src/lib.rs +++ b/apps/contracts/vault/src/lib.rs @@ -25,7 +25,7 @@ mod utils; use access::{AccessControl, AccessControlTrait, RolesDataKey}; use aggregator::{internal_swap_exact_tokens_for_tokens, internal_swap_tokens_for_exact_tokens}; use fee::collect_fees; -use funds::{fetch_current_idle_funds, fetch_current_invested_funds, fetch_total_managed_funds}; //, fetch_idle_funds_for_asset}; +use funds::{fetch_current_idle_funds, fetch_current_invested_funds, fetch_total_managed_funds, fetch_idle_funds_for_asset}; use interface::{AdminInterfaceTrait, VaultManagementTrait, VaultTrait}; use investment::{check_and_execute_investments}; use models::{ @@ -323,7 +323,7 @@ impl VaultTrait for DeFindexVault { } // Calculate the withdrawal amounts for each asset based on the share amounts - // Map + // Map Maps asset address to the amount to withdraw let asset_amounts = calculate_asset_amounts_per_vault_shares(&e, shares_amount)?; // Burn the shares after calculating the withdrawal amounts (so total supply is correct @@ -333,27 +333,33 @@ impl VaultTrait for DeFindexVault { // Create a map to store the total amounts to transfer for each asset address let mut total_amounts_to_transfer: Map = Map::new(&e); - // Get idle funds for each asset (Map) - let idle_funds = fetch_current_idle_funds(&e); - - // Loop through each asset to withdraw and handle the withdrawal + // Loop through each asset in order to handle the withdrawal and if necesary to deallocate invested funds for (asset_address, required_amount) in asset_amounts.iter() { // Check idle funds for this asset - let idle_balance = idle_funds.get(asset_address.clone()).unwrap_or(0); + let idle_balance = fetch_idle_funds_for_asset(&e, &asset_address); + + // let amount_to_deallocate = if idle_balance >= required_amount { + // 0 + // } else { + // required_amount.checked_sub(idle_balance); + // } + + // if amount_to_deallocate>0{ + // // deallocate from strategies + // } + let mut remaining_amount = required_amount; // Withdraw as much as possible from idle funds first - if idle_balance > 0 { - if idle_balance >= required_amount { - // Idle funds cover the full amount - total_amounts_to_transfer.set(asset_address.clone(), required_amount); - continue; // No need to withdraw from the strategy - } else { - // Partial withdrawal from idle funds - total_amounts_to_transfer.set(asset_address.clone(), idle_balance); - remaining_amount = required_amount - idle_balance; // Update remaining amount - } + if idle_balance >= required_amount { + // Idle funds cover the full amount + total_amounts_to_transfer.set(asset_address.clone(), required_amount); + continue; // No need to withdraw from the strategy + } else { + // Partial withdrawal from idle funds + total_amounts_to_transfer.set(asset_address.clone(), idle_balance); + remaining_amount = required_amount - idle_balance; // Update remaining amount } // Find the corresponding asset address for this strategy diff --git a/apps/contracts/vault/src/test/initialize.rs b/apps/contracts/vault/src/test/initialize.rs index c6e774b6..b8c6c644 100644 --- a/apps/contracts/vault/src/test/initialize.rs +++ b/apps/contracts/vault/src/test/initialize.rs @@ -165,14 +165,6 @@ fn test_initialize_twice() { ); } -#[test] -fn test_withdraw_not_yet_initialized() { - let test = DeFindexVaultTest::setup(); - let users = DeFindexVaultTest::generate_random_users(&test.env, 1); - - let result = test.defindex_contract.try_withdraw(&100i128, &users[0]); - assert_eq!(result, Err(Ok(ContractError::NotInitialized))); -} #[test] fn test_emergency_withdraw_not_yet_initialized() { From 67fb08a485723a112e730cd39ed7f85dae438d1e Mon Sep 17 00:00:00 2001 From: esteblock Date: Thu, 14 Nov 2024 09:18:56 -0300 Subject: [PATCH 05/28] work in progress --- apps/contracts/vault/src/funds.rs | 70 ++++++++++----- apps/contracts/vault/src/interface.rs | 4 +- apps/contracts/vault/src/lib.rs | 11 ++- apps/contracts/vault/src/models.rs | 11 +++ apps/contracts/vault/src/test/deposit.rs | 104 +++++++++++++++++++++-- apps/contracts/vault/src/test/invest.rs | 37 +++++++- apps/contracts/vault/src/utils.rs | 17 ++-- 7 files changed, 214 insertions(+), 40 deletions(-) diff --git a/apps/contracts/vault/src/funds.rs b/apps/contracts/vault/src/funds.rs index 1c394dbf..5e2eeed4 100644 --- a/apps/contracts/vault/src/funds.rs +++ b/apps/contracts/vault/src/funds.rs @@ -1,7 +1,7 @@ use soroban_sdk::token::TokenClient; -use soroban_sdk::{Address, Env, Map}; +use soroban_sdk::{Address, Env, Map, Vec}; -use crate::models::AssetStrategySet; +use crate::models::{AssetStrategySet, StrategyInvestment, CurrentAssetInvestmentAllocation}; use crate::storage::get_assets; use crate::strategies::get_strategy_client; @@ -34,21 +34,28 @@ pub fn fetch_invested_funds_for_strategy(e: &Env, strategy_address: &Address) -> strategy_client.balance(&e.current_contract_address()) } -/// Fetches the total funds that are invested for a given asset. -/// It iterates through all the strategies associated with the asset and sums their balances. -/// -/// # Arguments -/// * `e` - The current environment instance. -/// * `asset` - The asset for which invested funds are being fetched. -/// -/// # Returns -/// * The total invested balance (i128) of the asset across all strategies. -pub fn fetch_invested_funds_for_asset(e: &Env, asset: &AssetStrategySet) -> i128 { +// // Investment Allocation in Strategies +// #[contracttype] +// #[derive(Clone, Debug, Eq, PartialEq)] +// pub struct StrategyInvestment { +// pub strategy: Address, +// pub amount: i128, +// } + + +// return total invested funds but also a vec of StrategyInvestment +pub fn fetch_invested_funds_for_asset(e: &Env, asset: &AssetStrategySet) -> (i128, Vec){ let mut invested_funds = 0; + let mut strategy_investments: Vec = Vec::new(e); for strategy in asset.strategies.iter() { - invested_funds += fetch_invested_funds_for_strategy(e, &strategy.address); + let strategy_balance = fetch_invested_funds_for_strategy(e, &strategy.address); + invested_funds += strategy_balance; + strategy_investments.push_back(StrategyInvestment { + strategy: strategy.address.clone(), + amount: strategy_balance, + }); } - invested_funds + (invested_funds, strategy_investments) } // Pub functions @@ -82,9 +89,10 @@ pub fn fetch_current_invested_funds(e: &Env) -> Map { let assets = get_assets(e); let mut map: Map = Map::new(e); for asset in assets { + let (invested_funds, _) = fetch_invested_funds_for_asset(e, &asset); map.set( asset.address.clone(), - fetch_invested_funds_for_asset(e, &asset), + invested_funds ); } map @@ -99,13 +107,35 @@ pub fn fetch_current_invested_funds(e: &Env) -> Map { /// /// # Returns /// * A map where each entry represents an asset's address and its total managed balance. -pub fn fetch_total_managed_funds(e: &Env) -> Map { + + +// // Current Asset Investment Allocation +// #[contracttype] +// #[derive(Clone, Debug, Eq, PartialEq)] +// pub struct CurrentAssetInvestmentAllocation { +// pub asset: Address, +// pub total_amount: i128, +// pub idle_amount: i128, +// pub invested_amount: i128, +// pub strategy_investments: Vec, +// } +pub fn fetch_total_managed_funds(e: &Env) -> Map { let assets = get_assets(e); - let mut map: Map = Map::new(e); + let mut map: Map = Map::new(e); for asset in assets { - let idle_funds = fetch_idle_funds_for_asset(e, &asset.address); - let invested_funds = fetch_invested_funds_for_asset(e, &asset); - map.set(asset.address.clone(), idle_funds + invested_funds); + let idle_amount = fetch_idle_funds_for_asset(e, &asset.address); + let (invested_amount, strategy_investments) = fetch_invested_funds_for_asset(e, &asset); + let total_amount = idle_amount + invested_amount; + map.set( + asset.address.clone(), + CurrentAssetInvestmentAllocation { + asset: asset.address.clone(), + total_amount, + idle_amount, + invested_amount, + strategy_investments, + }, + ); } map } diff --git a/apps/contracts/vault/src/interface.rs b/apps/contracts/vault/src/interface.rs index f546484f..08fde05f 100644 --- a/apps/contracts/vault/src/interface.rs +++ b/apps/contracts/vault/src/interface.rs @@ -1,7 +1,7 @@ use soroban_sdk::{Address, Env, Map, String, Vec}; use crate::{ - models::{AssetStrategySet, Instruction, AssetInvestmentAllocation}, + models::{AssetStrategySet, Instruction, AssetInvestmentAllocation, CurrentAssetInvestmentAllocation}, ContractError, }; @@ -169,7 +169,7 @@ pub trait VaultTrait { /// /// # Returns: /// * `Map` - A map of asset addresses to their total managed amounts. - fn fetch_total_managed_funds(e: &Env) -> Map; + fn fetch_total_managed_funds(e: &Env) -> Map; /// Returns the current invested funds, representing the total assets allocated to strategies. /// diff --git a/apps/contracts/vault/src/lib.rs b/apps/contracts/vault/src/lib.rs index ceb4e3f4..b42454ab 100755 --- a/apps/contracts/vault/src/lib.rs +++ b/apps/contracts/vault/src/lib.rs @@ -30,7 +30,7 @@ use interface::{AdminInterfaceTrait, VaultManagementTrait, VaultTrait}; use investment::{check_and_execute_investments}; use models::{ ActionType, AssetStrategySet, Instruction, AssetInvestmentAllocation, OptionalSwapDetailsExactIn, - OptionalSwapDetailsExactOut, + OptionalSwapDetailsExactOut, CurrentAssetInvestmentAllocation }; use storage::{ get_assets, set_asset, set_defindex_protocol_fee_receiver, set_factory, @@ -235,8 +235,10 @@ impl VaultTrait for DeFindexVault { // if checked mul gives error, return ArithmeticError VaultToken::total_supply(e.clone()).checked_mul(amounts_desired.get(0) .unwrap()).unwrap_or_else(|| panic_with_error!(&e, ContractError::ArithmeticError)) - .checked_div(total_managed_funds.get(assets.get(0).unwrap().address.clone()) - .unwrap()).unwrap_or_else(|| panic_with_error!(&e, ContractError::ArithmeticError)) + .checked_div( + total_managed_funds.get(assets.get(0).unwrap().address.clone()) + .unwrap().total_amount + ).unwrap_or_else(|| panic_with_error!(&e, ContractError::ArithmeticError)) }; // TODO check that min amount is ok (amounts_desired, shares) @@ -324,6 +326,7 @@ impl VaultTrait for DeFindexVault { // Calculate the withdrawal amounts for each asset based on the share amounts // Map Maps asset address to the amount to withdraw + // this already considers the idle funds and all the invested amounts in strategies let asset_amounts = calculate_asset_amounts_per_vault_shares(&e, shares_amount)?; // Burn the shares after calculating the withdrawal amounts (so total supply is correct @@ -528,7 +531,7 @@ impl VaultTrait for DeFindexVault { /// /// # Returns: /// * `Map` - A map of asset addresses to their total managed amounts. - fn fetch_total_managed_funds(e: &Env) -> Map { + fn fetch_total_managed_funds(e: &Env) -> Map { extend_instance_ttl(&e); fetch_total_managed_funds(e) } diff --git a/apps/contracts/vault/src/models.rs b/apps/contracts/vault/src/models.rs index c0eb3db3..d3eddda2 100644 --- a/apps/contracts/vault/src/models.rs +++ b/apps/contracts/vault/src/models.rs @@ -29,7 +29,18 @@ pub struct AssetInvestmentAllocation { pub asset: Address, pub strategy_investments: Vec>, } +// Current Asset Investment Allocation +#[contracttype] +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct CurrentAssetInvestmentAllocation { + pub asset: Address, + pub total_amount: i128, + pub idle_amount: i128, + pub invested_amount: i128, + pub strategy_investments: Vec, +} +// #[contracttype] #[derive(Clone, Debug, Eq, PartialEq)] pub struct Instruction { diff --git a/apps/contracts/vault/src/test/deposit.rs b/apps/contracts/vault/src/test/deposit.rs index 69d2fffd..67ae1a65 100644 --- a/apps/contracts/vault/src/test/deposit.rs +++ b/apps/contracts/vault/src/test/deposit.rs @@ -1,6 +1,6 @@ use soroban_sdk::{vec as sorobanvec, String, Vec, Map}; -use crate::test::defindex_vault::{AssetStrategySet, ContractError}; +use crate::test::defindex_vault::{AssetStrategySet, ContractError, CurrentAssetInvestmentAllocation, StrategyInvestment}; use crate::test::{ create_strategy_params_token0, create_strategy_params_token1, DeFindexVaultTest, }; @@ -299,13 +299,51 @@ fn deposit_one_asset_success() { let mut expected_map = Map::new(&test.env); expected_map.set(test.token0.address.clone(), amount); + // fn fetch_total_managed_funds(e: &Env) -> Map { + // extend_instance_ttl(&e); + // fetch_total_managed_funds(e) + // } + // Current Asset Investment Allocation + // #[contracttype] + // #[derive(Clone, Debug, Eq, PartialEq)] + // pub struct CurrentAssetInvestmentAllocation { + // pub asset: Address, + // pub total_amount: i128, + // pub idle_amount: i128, + // pub invested_amount: i128, + // pub strategy_investments: Vec, + // } + // #[contracttype] + // #[derive(Clone, Debug, Eq, PartialEq)] + // pub struct StrategyInvestment { + // pub strategy: Address, + // pub amount: i128, + // } + + // construct expected total managed funds maa + let mut total_managed_funds_expected = Map::new(&test.env); + let mut strategy_investments_expected = sorobanvec![&test.env, StrategyInvestment { + strategy: test.strategy_client_token0.address.clone(), + amount: amount, + }]; + total_managed_funds_expected.set(test.token0.address.clone(), + CurrentAssetInvestmentAllocation { + asset: test.token0.address.clone(), + total_amount: amount, + idle_amount: amount, + invested_amount: 0i128, + strategy_investments: strategy_investments_expected, + } + ); + + // check that all the assets are in the vault let vault_balance = test.token0.balance(&test.defindex_contract.address); assert_eq!(vault_balance, amount); // check that fetch_total_managed_funds returns correct amount let total_managed_funds = test.defindex_contract.fetch_total_managed_funds(); - assert_eq!(total_managed_funds, expected_map); + assert_eq!(total_managed_funds, total_managed_funds_expected); // check current idle funds, let current_idle_funds = test.defindex_contract.fetch_current_idle_funds(); @@ -348,8 +386,22 @@ fn deposit_one_asset_success() { assert_eq!(vault_balance, amount + amount2); // check that fetch_total_managed_funds returns correct amount + let mut total_managed_funds_expected = Map::new(&test.env); + let mut strategy_investments_expected = sorobanvec![&test.env, StrategyInvestment { + strategy: test.strategy_client_token0.address.clone(), + amount: amount + amount2, + }]; + total_managed_funds_expected.set(test.token0.address.clone(), + CurrentAssetInvestmentAllocation { + asset: test.token0.address.clone(), + total_amount: amount + amount2, + idle_amount: amount + amount2, + invested_amount: 0i128, + strategy_investments: strategy_investments_expected, + } + ); let total_managed_funds = test.defindex_contract.fetch_total_managed_funds(); - assert_eq!(total_managed_funds, expected_map); + assert_eq!(total_managed_funds, total_managed_funds_expected); // check current idle funds let current_idle_funds = test.defindex_contract.fetch_current_idle_funds(); @@ -503,8 +555,29 @@ fn deposit_several_assets_success() { expected_map.set(test.token1.address.clone(), amount1); // check that fetch_total_managed_funds returns correct amount + let total_managed_funds_expected = Map::new(&test.env); + let mut strategy_investments_expected = sorobanvec![&test.env, StrategyInvestment { + strategy: test.strategy_client_token0.address.clone(), + amount: amount0, + }]; + strategy_investments_expected.push_back(StrategyInvestment { + strategy: test.strategy_client_token1.address.clone(), + amount: amount1, + }); + total_managed_funds_expected.set(test.token0.address.clone(), + CurrentAssetInvestmentAllocation { + asset: test.token0.address.clone(), + total_amount: amount0, + idle_amount: amount0, + invested_amount: 0i128, + strategy_investments: sorobanvec![&test.env, StrategyInvestment { + strategy: test.strategy_client_token0.address.clone(), + amount: amount0, + }], + } + ); let total_managed_funds = test.defindex_contract.fetch_total_managed_funds(); - assert_eq!(total_managed_funds, expected_map); + assert_eq!(total_managed_funds, total_managed_funds_expected); // check current idle funds let current_idle_funds = test.defindex_contract.fetch_current_idle_funds(); @@ -572,8 +645,29 @@ fn deposit_several_assets_success() { expected_map.set(test.token1.address.clone(), 3*amount1); // check that fetch_total_managed_funds returns correct amount + let total_managed_funds_expected = Map::new(&test.env); + let mut strategy_investments_expected = sorobanvec![&test.env, StrategyInvestment { + strategy: test.strategy_client_token0.address.clone(), + amount: 3*amount0, + }]; + strategy_investments_expected.push_back(StrategyInvestment { + strategy: test.strategy_client_token1.address.clone(), + amount: 3*amount1, + }); + total_managed_funds_expected.set(test.token0.address.clone(), + CurrentAssetInvestmentAllocation { + asset: test.token0.address.clone(), + total_amount: 3*amount0, + idle_amount: 3*amount0, + invested_amount: 0i128, + strategy_investments: sorobanvec![&test.env, StrategyInvestment { + strategy: test.strategy_client_token0.address.clone(), + amount: 3*amount0, + }], + } + ); let total_managed_funds = test.defindex_contract.fetch_total_managed_funds(); - assert_eq!(total_managed_funds, expected_map); + assert_eq!(total_managed_funds, total_managed_funds_expected); // check current idle funds let current_idle_funds = test.defindex_contract.fetch_current_idle_funds(); diff --git a/apps/contracts/vault/src/test/invest.rs b/apps/contracts/vault/src/test/invest.rs index 338c2c2a..7e78e1a1 100644 --- a/apps/contracts/vault/src/test/invest.rs +++ b/apps/contracts/vault/src/test/invest.rs @@ -459,9 +459,42 @@ fn test_invest_in_strategy() { assert_eq!(vault_balance_0, amount_0); assert_eq!(vault_balance_1, amount_1); - // check that fetch_total_managed_funds returns correct amount + // EXAMPLE + // // check that fetch_total_managed_funds returns correct amount + // let total_managed_funds_expected = Map::new(&test.env); + // let mut strategy_investments_expected = sorobanvec![&test.env, StrategyInvestment { + // strategy: test.strategy_client_token0.address.clone(), + // amount: 3*amount0, + // }]; + // strategy_investments_expected.push_back(StrategyInvestment { + // strategy: test.strategy_client_token1.address.clone(), + // amount: 3*amount1, + // }); + // total_managed_funds_expected.set(test.token0.address.clone(), + // CurrentAssetInvestmentAllocation { + // asset: test.token0.address.clone(), + // total_amount: 3*amount0, + // idle_amount: 3*amount0, + // invested_amount: 0i128, + // strategy_investments: sorobanvec![&test.env, StrategyInvestment { + // strategy: test.strategy_client_token0.address.clone(), + // amount: 3*amount0, + // }], + // } + // ); + // let total_managed_funds = test.defindex_contract.fetch_total_managed_funds(); + // assert_eq!(total_managed_funds, total_managed_funds_expected); + + + let mut total_managed_funds_expected = Map::new(&test.env); + total_managed_funds_expected.set(test.token0.address.clone(), amount_0); + total_managed_funds_expected.set(test.token1.address.clone(), amount_1); + + + + + let total_managed_funds = test.defindex_contract.fetch_total_managed_funds(); - let mut expected_map = Map::new(&test.env); expected_map.set(test.token0.address.clone(), amount_0); expected_map.set(test.token1.address.clone(), amount_1); assert_eq!(total_managed_funds, expected_map); diff --git a/apps/contracts/vault/src/utils.rs b/apps/contracts/vault/src/utils.rs index db541192..a8e8222d 100644 --- a/apps/contracts/vault/src/utils.rs +++ b/apps/contracts/vault/src/utils.rs @@ -1,12 +1,12 @@ use soroban_sdk::{panic_with_error, Address, Env, Map, Vec}; use crate::{ + models::{AssetStrategySet, CurrentAssetInvestmentAllocation}, access::{AccessControl, AccessControlTrait, RolesDataKey}, funds::{ fetch_invested_funds_for_asset, fetch_invested_funds_for_strategy, fetch_total_managed_funds, }, - models::AssetStrategySet, token::VaultToken, ContractError, }; @@ -47,7 +47,7 @@ pub fn calculate_withdrawal_amounts( ) -> Map { let mut withdrawal_amounts = Map::::new(e); - let total_invested_in_strategies: i128 = fetch_invested_funds_for_asset(&e, &asset); + let (total_invested_in_strategies, _) = fetch_invested_funds_for_asset(&e, &asset); for strategy in asset.strategies.iter() { // TODO: if strategy is paused but still holds assets on it shouldnt we withdraw them? @@ -96,10 +96,10 @@ pub fn calculate_asset_amounts_per_vault_shares( } // Iterate over each asset and calculate the corresponding amount based on shares_amount - for (asset_address, total_asset_amount) in total_managed_funds.iter() { + for (asset_address, current_asset_allocation) in total_managed_funds.iter() { // Calculate the proportional asset amount per the given number of shares let asset_amount = if total_shares_supply != 0 { - total_asset_amount + current_asset_allocation.total_amount .checked_mul(shares_amount) .ok_or(ContractError::ArithmeticError)? .checked_div(total_shares_supply) @@ -152,7 +152,7 @@ pub fn calculate_asset_amounts_per_vault_shares( pub fn calculate_optimal_amounts_and_shares_with_enforced_asset( e: &Env, - total_managed_funds: &Map, + total_managed_funds: &Map, assets: &Vec, amounts_desired: &Vec, i: &u32, @@ -162,7 +162,8 @@ pub fn calculate_optimal_amounts_and_shares_with_enforced_asset( // reserve (total manage funds) of the asset we are enforcing let reserve_target = total_managed_funds .get(assets.get(*i).unwrap_or_else(|| panic_with_error!(&e, ContractError::WrongAmountsLength)).address) - .unwrap_or_else(|| panic_with_error!(&e, ContractError::WrongAmountsLength)); + .unwrap_or_else(|| panic_with_error!(&e, ContractError::WrongAmountsLength)) + .total_amount; // If reserve target is zero, we cannot calculate the optimal amounts if reserve_target == 0 { @@ -177,7 +178,9 @@ pub fn calculate_optimal_amounts_and_shares_with_enforced_asset( if j == (*i as usize) { optimal_amounts.push_back(amount_desired_target); } else { - let reserve = total_managed_funds.get(asset.address).unwrap_or_else(|| panic_with_error!(&e, ContractError::WrongAmountsLength)); + let reserve = total_managed_funds + .get(asset.address).unwrap_or_else(|| panic_with_error!(&e, ContractError::WrongAmountsLength)) + .total_amount; let amount = reserve.checked_mul(amount_desired_target) .unwrap_or_else(|| panic_with_error!(&e, ContractError::ArithmeticError)) .checked_div(reserve_target) From d54bb7e29bf6b18978ef2c5a79d2828621a22682 Mon Sep 17 00:00:00 2001 From: coderipper Date: Tue, 26 Nov 2024 18:53:26 -0300 Subject: [PATCH 06/28] update on blend strategy and blend strategy tests --- apps/contracts/package.json | 3 +- apps/contracts/src/strategies/deploy_blend.ts | 3 +- apps/contracts/src/tests/blend/test.ts | 232 ------------------ .../src/tests/blend/test_strategy.ts | 125 ++++++++++ apps/contracts/src/tests/blend/test_vault.ts | 209 ++++++++++++++++ .../strategies/blend/src/blend_pool.rs | 64 ++++- apps/contracts/strategies/blend/src/lib.rs | 24 +- .../contracts/strategies/blend/src/storage.rs | 11 +- apps/contracts/strategies/blend/src/test.rs | 8 +- .../strategies/blend/src/test/deposit.rs | 79 ------ .../strategies/blend/src/test/events.rs | 6 - .../strategies/blend/src/test/initialize.rs | 21 -- .../strategies/blend/src/test/withdraw.rs | 5 - 13 files changed, 419 insertions(+), 371 deletions(-) delete mode 100644 apps/contracts/src/tests/blend/test.ts create mode 100644 apps/contracts/src/tests/blend/test_strategy.ts create mode 100644 apps/contracts/src/tests/blend/test_vault.ts delete mode 100644 apps/contracts/strategies/blend/src/test/deposit.rs delete mode 100644 apps/contracts/strategies/blend/src/test/events.rs delete mode 100644 apps/contracts/strategies/blend/src/test/initialize.rs delete mode 100644 apps/contracts/strategies/blend/src/test/withdraw.rs diff --git a/apps/contracts/package.json b/apps/contracts/package.json index 7f349d64..3b52c8b4 100644 --- a/apps/contracts/package.json +++ b/apps/contracts/package.json @@ -11,7 +11,8 @@ "publish-addresses": "tsc && node dist/publish_addresses.js", "test": "tsc && node dist/test.js", "test-vault": "tsc && node dist/tests/testOnlyVault.js", - "test-blend": "tsc && node dist/tests/blend/test.js", + "test-blend-strategy": "tsc && node dist/tests/blend/test_strategy.js", + "test-blend-vault": "tsc && node dist/tests/blend/test_vault.js", "test-dev": "tsc && node dist/tests/dev.js", "test-two-strat-vault": "tsc && node dist/tests/testTwoStrategiesVault.js" }, diff --git a/apps/contracts/src/strategies/deploy_blend.ts b/apps/contracts/src/strategies/deploy_blend.ts index 7b6db3b5..ba2473ff 100644 --- a/apps/contracts/src/strategies/deploy_blend.ts +++ b/apps/contracts/src/strategies/deploy_blend.ts @@ -1,4 +1,4 @@ -import { Address, Asset, Networks, xdr } from "@stellar/stellar-sdk"; +import { Address, Asset, nativeToScVal, Networks, xdr } from "@stellar/stellar-sdk"; import { AddressBook } from "../utils/address_book.js"; import { airdropAccount, @@ -47,6 +47,7 @@ export async function deployBlendStrategy(addressBook: AddressBook) { const initArgs = xdr.ScVal.scvVec([ new Address("CCEVW3EEW4GRUZTZRTAMJAXD6XIF5IG7YQJMEEMKMVVGFPESTRXY2ZAV").toScVal(), //Blend pool on testnet! + nativeToScVal(0, {type: "u32"}) // ReserveId 0 is XLM ]); const args: xdr.ScVal[] = [ diff --git a/apps/contracts/src/tests/blend/test.ts b/apps/contracts/src/tests/blend/test.ts deleted file mode 100644 index d9a36d77..00000000 --- a/apps/contracts/src/tests/blend/test.ts +++ /dev/null @@ -1,232 +0,0 @@ -import { Address, Keypair, nativeToScVal, scValToNative, xdr } from "@stellar/stellar-sdk"; -import { airdropAccount, invokeCustomContract } from "../../utils/contract.js"; -import { getDfTokenBalance } from "../vault.js"; -import { randomBytes } from "crypto"; -import { TxResponse } from '@soroban-react/contracts'; -const blendStrategyAddress = "CCNFSOPH4XFQ5TNWGTJB4ZVKUUARSNQ67SETXVIQLUIW3B3F7KHA3NKJ" -const factoryAddress = "CB6RQM6ECU775ZC26NMZ6RJNKQLKQGLIJWWN2VZO6AGSE4V4DBQDL23O" -const XLMAddress = "CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC" -const BlendUSDCAddress = "" -const network = process.argv[2]; -const purple = '\x1b[35m%s\x1b[0m'; -const green = '\x1b[32m%s\x1b[0m'; - - -const newVault = { - address: '', - emergencyManager: 'GCH6YKNJ3KPESGSAIGBNHRNCIYXXXSRVU7OC552RDGQFHZ4SYRI26DQE', - feeReceiver: 'GCH6YKNJ3KPESGSAIGBNHRNCIYXXXSRVU7OC552RDGQFHZ4SYRI26DQE', - manager: 'GCH6YKNJ3KPESGSAIGBNHRNCIYXXXSRVU7OC552RDGQFHZ4SYRI26DQE', - name: 'Test', - symbol: 'Test1', - vaultShare: 10, - assets: [ - { - address: 'CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC', - strategies: [ - { - address: 'CCNFSOPH4XFQ5TNWGTJB4ZVKUUARSNQ67SETXVIQLUIW3B3F7KHA3NKJ', - name: 'Blend', - paused: false - } - ], - symbol: 'XLM', - amount: 1000 - } - ], - TVL: 0 -} -export async function createVault(user?: Keypair) { - // Create and fund a new user account if not provided - console.log(purple, '--------------------------------------------------------------------') - console.log(purple, '----------------------- Creating new account -----------------------') - console.log(purple, '--------------------------------------------------------------------') - const newUser = Keypair.random(); - console.log('🚀 ~ depositToVault ~ newUser.publicKey():', newUser.publicKey()); - console.log('🚀 ~ depositToVault ~ newUser.secret():', newUser.secret()); - - console.log(green, '----------------------- New account created -------------------------') - console.log(green, 'Public key: ',newUser.publicKey()) - console.log(green, '---------------------------------------------------------------------') - - if (network !== "mainnet") { - console.log(purple, '-------------------------------------------------------------------') - console.log(purple, '----------------------- Funding new account -----------------------') - console.log(purple, '-------------------------------------------------------------------') - await airdropAccount(newUser); - } - console.log("New user publicKey:", newUser.publicKey()); - - - const indexName = "test"; - const indexSymbol = "TEST"; - const indexShare = 10; - const managerString = newUser.publicKey(); - const vaultName = nativeToScVal(indexName, { type: "string" }) - const vaultSymbol = nativeToScVal(indexSymbol, { type: "string" }) - const vaultShare = nativeToScVal(indexShare, { type: "u32" }) - const emergencyManager = new Address(managerString) - const feeReceiver = new Address(managerString) - const manager = new Address(managerString) - const salt = randomBytes(32) - - const strategyParamsScVal = xdr.ScVal.scvMap([ - new xdr.ScMapEntry({ - key: xdr.ScVal.scvSymbol('address'), - val: new Address(blendStrategyAddress).toScVal(), - }), - new xdr.ScMapEntry({ - key: xdr.ScVal.scvSymbol('name'), - val: nativeToScVal('Blend', { type: "string" }), - }), - new xdr.ScMapEntry({ - key: xdr.ScVal.scvSymbol('paused'), - val: nativeToScVal(false, { type: "bool" }), - }), - ]); - const strategyParamsScValVec = xdr.ScVal.scvVec([strategyParamsScVal]); - const assetsParams = xdr.ScVal.scvMap([ - new xdr.ScMapEntry({ - key: xdr.ScVal.scvSymbol('address'), - val: new Address(newVault.assets[0].address).toScVal(), - }), - new xdr.ScMapEntry({ - key: xdr.ScVal.scvSymbol('strategies'), - val: strategyParamsScValVec, - }), - ]); - const assetParamsScValVec = xdr.ScVal.scvVec([assetsParams]); - const createDefindexParams: xdr.ScVal[] = [ - emergencyManager.toScVal(), - feeReceiver.toScVal(), - vaultShare, - vaultName, - vaultSymbol, - manager.toScVal(), - assetParamsScValVec, - nativeToScVal(salt), - ]; - let result: any; - let blendVaultAddress: string; - try { - console.log(purple, '--------------------------------------------------------------') - console.log(purple, '----------------------- Creating vault -----------------------') - console.log(purple, '--------------------------------------------------------------') - result = await invokeCustomContract( - factoryAddress, - 'create_defindex_vault', - createDefindexParams, - newUser, - false - ); - blendVaultAddress = scValToNative(result.returnValue); - console.log(green, '----------------------- Vault created -------------------------') - console.log(green, 'result', blendVaultAddress) - console.log(green, '---------------------------------------------------------------') - - - // Deposit assets to the vault - - console.log(purple, '---------------------------------------------------------------------------') - console.log(purple, '----------------------- Depositing XLM to the vault -----------------------') - console.log(purple, '---------------------------------------------------------------------------') - const depositParams: xdr.ScVal[] = [ - xdr.ScVal.scvVec([nativeToScVal(987654321, { type: "i128" })]), - xdr.ScVal.scvVec([nativeToScVal(Math.ceil(987654321 * 0.9), { type: "i128" })]), - new Address(newUser.publicKey()).toScVal(), - ] - const depositResult = await invokeCustomContract( - blendVaultAddress, - 'deposit', - depositParams, - newUser, - false - ); - const depositResultValue = scValToNative(depositResult.returnValue); - - console.log(green, '------------ XLM deposited to the vault ------------') - console.log(green, 'depositResult', depositResultValue) - console.log(green, '----------------------------------------------------') - - // Withdraw assets from the vault - - console.log(purple, '------------------------------------------------------------------------------') - console.log(purple, '----------------------- Withdrawing XLM from the vault -----------------------') - console.log(purple, '------------------------------------------------------------------------------') - const withdrawAmount = Math.ceil(100); - const withdrawParams: xdr.ScVal[] = [ - nativeToScVal(withdrawAmount, { type: "i128" }), - new Address(newUser.publicKey()).toScVal(), - ] - const withdrawResult = await invokeCustomContract( - blendVaultAddress, - 'withdraw', - withdrawParams, - newUser, - false - ); - const withdrawResultValue = scValToNative(withdrawResult.returnValue); - console.log(green, '---------------- XLM withdrawn from the vault ----------------') - console.log(green, 'Withdrawed: ', withdrawResultValue, ' from the vault') - console.log(green, '--------------------------------------------------------------') - - // Invest in strategy - - console.log(purple, '---------------------------------------------------------------------------') - console.log(purple, '-------------------------- Investing in strategy --------------------------') - console.log(purple, '---------------------------------------------------------------------------') - - const investment: any = [{ - "asset": "CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC", - "strategy_investments": [ - { - "amount": 24, - "strategy": "CCWUMJGE6LKWRDJ2IYEJBLCWJSMSUC3QCYZNI2MHTOEYPZRWZN56MIVA" - } - ], - }] - - const investmentParams = investment.map((entry:any) => - xdr.ScVal.scvMap([ - new xdr.ScMapEntry({ - key: xdr.ScVal.scvSymbol("asset"), - val: new Address(entry.asset).toScVal()// Convert asset address to ScVal - }), - new xdr.ScMapEntry({ - key: xdr.ScVal.scvSymbol("strategy_investments"), - val: xdr.ScVal.scvVec( - entry.strategy_investments.map((strategy_investment: any) => { - return xdr.ScVal.scvMap([ - new xdr.ScMapEntry({ - key: xdr.ScVal.scvSymbol("amount"), - val: nativeToScVal(BigInt((strategy_investment.amount ?? 0) * 10 ** 7), { type: "i128" }), // Ensure i128 conversion - }), - new xdr.ScMapEntry({ - key: xdr.ScVal.scvSymbol("strategy"), - val: new Address(strategy_investment.strategy).toScVal() // Convert strategy address - }), - ]) - }) - ), - }), - ]) - ) - const investmentParamsScValVec = xdr.ScVal.scvVec(investmentParams); - - const investResult = await invokeCustomContract( - blendVaultAddress, - 'invest', - [investmentParamsScValVec], - newUser, - false - ); - const investResultValue = scValToNative(investResult.returnValue); - console.log(green, '---------------------- Invested in strategy ----------------------') - console.log(green, 'Invested: ', investResultValue, ' in the strategy') - console.log(green, '------------------------------------------------------------------') - - }catch(e){ - console.log('error', e) - } -} -await createVault(); \ No newline at end of file diff --git a/apps/contracts/src/tests/blend/test_strategy.ts b/apps/contracts/src/tests/blend/test_strategy.ts new file mode 100644 index 00000000..443ea4a1 --- /dev/null +++ b/apps/contracts/src/tests/blend/test_strategy.ts @@ -0,0 +1,125 @@ +import { Address, Keypair, nativeToScVal, scValToNative, xdr } from "@stellar/stellar-sdk"; +import { AddressBook } from "../../utils/address_book.js"; +import { airdropAccount, invokeContract } from "../../utils/contract.js"; + +const network = process.argv[2]; +const addressBook = AddressBook.loadFromFile(network); + +const purple = '\x1b[35m%s\x1b[0m'; +const green = '\x1b[32m%s\x1b[0m'; + +export async function testBlendStrategy(user?: Keypair) { + // Create and fund a new user account if not provided + const newUser = Keypair.random(); + console.log(green, '----------------------- New account created -------------------------') + console.log(green, 'Public key: ',newUser.publicKey()) + console.log(green, '---------------------------------------------------------------------') + + if (network !== "mainnet") { + console.log(purple, '-------------------------------------------------------------------') + console.log(purple, '----------------------- Funding new account -----------------------') + console.log(purple, '-------------------------------------------------------------------') + await airdropAccount(newUser); + } + + try { + // Deposit XLM into Blend Strategy + console.log(purple, '---------------------------------------------------------------------------') + console.log(purple, '----------------------- Depositing XLM to the Strategy -----------------------') + console.log(purple, '---------------------------------------------------------------------------') + const depositParams: xdr.ScVal[] = [ + nativeToScVal(1000_0_000_000, { type: "i128" }), + new Address(newUser.publicKey()).toScVal(), + ] + const depositResult = await invokeContract( + 'blend_strategy', + addressBook, + 'deposit', + depositParams, + newUser, + false + ); + console.log('🚀 « depositResult:', depositResult); + const depositResultValue = scValToNative(depositResult.returnValue); + + console.log(green, '------------ XLM deposited to the Strategy ------------') + console.log(green, 'depositResult', depositResultValue) + console.log(green, '----------------------------------------------------') + }catch(e){ + console.log('error', e) + } + + // Wait for 1 minute + console.log(purple, '---------------------------------------------------------------------------') + console.log(purple, '----------------------- Waiting for 1 minute -----------------------') + console.log(purple, '---------------------------------------------------------------------------') + await new Promise(resolve => setTimeout(resolve, 100)); + + try { + // Withdrawing XLM from Blend Strategy + console.log(purple, '---------------------------------------------------------------------------') + console.log(purple, '----------------------- Withdrawing XLM from the Strategy -----------------------') + console.log(purple, '---------------------------------------------------------------------------') + + const balanceScVal = await invokeContract( + 'blend_strategy', + addressBook, + 'balance', + [new Address(newUser.publicKey()).toScVal()], + newUser, + true + ); + console.log('🚀 « balanceScVal:', balanceScVal); + + const balance = scValToNative(balanceScVal.result.retval); + console.log('🚀 « balance:', balance); + + const withdrawParams: xdr.ScVal[] = [ + nativeToScVal(1000_0_000_000, { type: "i128" }), + new Address(newUser.publicKey()).toScVal(), + ] + const withdrawResult = await invokeContract( + 'blend_strategy', + addressBook, + 'withdraw', + withdrawParams, + newUser, + false + ); + const withdrawResultValue = scValToNative(withdrawResult.returnValue); + + console.log(green, '------------ XLM withdrawed from the Strategy ------------') + console.log(green, 'withdrawResult', withdrawResultValue) + console.log(green, '----------------------------------------------------') + }catch(e){ + console.log('error', e) + } + + try { + // Harvest rewards from Blend Strategy + console.log(purple, '---------------------------------------------------------------------------') + console.log(purple, '----------------------- Harvesting from the Strategy -----------------------') + console.log(purple, '---------------------------------------------------------------------------') + + const harvestParams: xdr.ScVal[] = [ + new Address(newUser.publicKey()).toScVal(), + ] + const harvestResult = await invokeContract( + 'blend_strategy', + addressBook, + 'harvest', + harvestParams, + newUser, + false + ); + const harvestResultValue = scValToNative(harvestResult.returnValue); + + console.log(green, '------------ BLND Harvested from the vault ------------') + console.log(green, 'harvestResult', harvestResultValue) + console.log(green, '----------------------------------------------------') + }catch(e){ + console.log('error', e) + } +} + +await testBlendStrategy(); \ No newline at end of file diff --git a/apps/contracts/src/tests/blend/test_vault.ts b/apps/contracts/src/tests/blend/test_vault.ts new file mode 100644 index 00000000..167a121a --- /dev/null +++ b/apps/contracts/src/tests/blend/test_vault.ts @@ -0,0 +1,209 @@ +import { Address, Asset, Keypair, nativeToScVal, Networks, scValToNative, xdr } from "@stellar/stellar-sdk"; +import { randomBytes } from "crypto"; +import { exit } from "process"; +import { AddressBook } from "../../utils/address_book.js"; +import { airdropAccount, invokeContract } from "../../utils/contract.js"; +import { config } from "../../utils/env_config.js"; +import { AssetInvestmentAllocation, depositToVault, investVault } from "../vault.js"; + +const network = process.argv[2]; +const loadedConfig = config(network); +const addressBook = AddressBook.loadFromFile(network); + +const purple = '\x1b[35m%s\x1b[0m'; +const green = '\x1b[32m%s\x1b[0m'; + + + +export async function testBlendVault(user?: Keypair) { + const newUser = Keypair.random(); + console.log(green, '----------------------- New account created -------------------------') + console.log(green, 'Public key: ',newUser.publicKey()) + console.log(green, '---------------------------------------------------------------------') + + if (network !== "mainnet") { + console.log(purple, '-------------------------------------------------------------------') + console.log(purple, '----------------------- Funding new account -----------------------') + console.log(purple, '-------------------------------------------------------------------') + await airdropAccount(newUser); + } + + console.log("Setting Emergengy Manager, Fee Receiver and Manager accounts"); + const emergencyManager = loadedConfig.getUser("DEFINDEX_EMERGENCY_MANAGER_SECRET_KEY"); + if (network !== "mainnet") await airdropAccount(emergencyManager); + + const feeReceiver = loadedConfig.getUser("DEFINDEX_FEE_RECEIVER_SECRET_KEY"); + if (network !== "mainnet") await airdropAccount(feeReceiver); + + const manager = loadedConfig.getUser("DEFINDEX_MANAGER_SECRET_KEY"); + if (network !== "mainnet") await airdropAccount(manager); + + const blendStrategyAddress = addressBook.getContractId("blend_strategy"); + + const xlm = Asset.native(); + let xlmContractId: string; + switch (network) { + case "testnet": + xlmContractId = xlm.contractId(Networks.TESTNET); + break; + case "mainnet": + xlmContractId = xlm.contractId(Networks.PUBLIC); + break; + default: + console.log("Invalid network:", network, "It should be either testnet or mainnet"); + return; + } + + const assets = [ + { + address: new Address(xlmContractId), + strategies: [ + { + name: "Blend Strategy", + address: blendStrategyAddress, + paused: false + }, + ] + } + ]; + + const assetAllocations = assets.map((asset) => { + return xdr.ScVal.scvMap([ + new xdr.ScMapEntry({ + key: xdr.ScVal.scvSymbol("address"), + val: asset.address.toScVal(), + }), + new xdr.ScMapEntry({ + key: xdr.ScVal.scvSymbol("strategies"), + val: xdr.ScVal.scvVec( + asset.strategies.map((strategy) => + xdr.ScVal.scvMap([ + new xdr.ScMapEntry({ + key: xdr.ScVal.scvSymbol("address"), + val: new Address(strategy.address).toScVal(), + }), + new xdr.ScMapEntry({ + key: xdr.ScVal.scvSymbol("name"), + val: nativeToScVal(strategy.name, { type: "string" }), + }), + new xdr.ScMapEntry({ + key: xdr.ScVal.scvSymbol("paused"), + val: nativeToScVal(false, { type: "bool" }), + }), + ]) + ) + ), + }), + ]); + }); + + const createDeFindexParams: xdr.ScVal[] = [ + new Address(emergencyManager.publicKey()).toScVal(), + new Address(feeReceiver.publicKey()).toScVal(), + nativeToScVal(100, { type: "u32" }), + nativeToScVal("BLND Vault", { type: "string" }), + nativeToScVal("BLNVLT", { type: "string" }), + new Address(manager.publicKey()).toScVal(), + xdr.ScVal.scvVec(assetAllocations), + nativeToScVal(randomBytes(32)), + ]; + + const initialAmount = 100_0_000_000; + let blendVaultAddress: string = ""; + + try { + console.log(purple, '--------------------------------------------------------------') + console.log(purple, '----------------------- Creating vault -----------------------') + console.log(purple, '--------------------------------------------------------------') + const createResult = await invokeContract( + 'defindex_factory', + addressBook, + 'create_defindex_vault', + createDeFindexParams, + manager, + false + ); + + blendVaultAddress = scValToNative(createResult.returnValue); + console.log(green, '----------------------- Vault created -------------------------') + console.log(green, 'createResult', blendVaultAddress) + console.log(green, '---------------------------------------------------------------') + } catch(e){ + console.log('❌ Error Creating the vault', e) + exit("Error Creating"); + } + + try { + // Deposit assets to the vault + console.log(purple, '---------------------------------------------------------------------------') + console.log(purple, '----------------------- Depositing XLM to the vault -----------------------') + console.log(purple, '---------------------------------------------------------------------------') + const { user, balanceBefore: depositBalanceBefore, result: depositResult, balanceAfter: depositBalanceAfter } + = await depositToVault(blendVaultAddress, [initialAmount], newUser); + + console.log(green, '------------ XLM deposited to the vault ------------') + console.log(green, 'Deposit balance before: ', depositBalanceBefore) + console.log(green, 'depositResult', depositResult) + console.log(green, 'Deposit balance after: ', depositBalanceAfter) + console.log(green, '----------------------------------------------------') + } catch (error) { + console.log('❌ Error depositing into the vault:', error); + exit("Error Depositing"); + } + + try { + // Invest in strategy + console.log(purple, '---------------------------------------------------------------------------') + console.log(purple, '-------------------------- Investing in strategy --------------------------') + console.log(purple, '---------------------------------------------------------------------------') + + const investParams: AssetInvestmentAllocation[] = [ + { + asset: new Address(xlmContractId), + strategy_investments: [ + { + amount: BigInt(50_0_000_000), + strategy: new Address(blendStrategyAddress) + } + ] + } + ]; + + const investResult = await investVault(blendVaultAddress, investParams, manager) + console.log('🚀 « investResult:', investResult); + + console.log(green, '---------------------- Invested in strategy ----------------------') + console.log(green, 'Invested: ', scValToNative(investResult.returnValue), ' in the strategy') + console.log(green, '------------------------------------------------------------------') + } catch (error) { + console.log('❌ Error Investing the Vault:', error); + exit("Error Investing"); + } + + // try { + // // Withdraw assets from the vault + // console.log(purple, '------------------------------------------------------------------------------') + // console.log(purple, '----------------------- Withdrawing XLM from the vault -----------------------') + // console.log(purple, '------------------------------------------------------------------------------') + // const withdrawAmount = Math.ceil(100); + // const withdrawParams: xdr.ScVal[] = [ + // nativeToScVal(withdrawAmount, { type: "i128" }), + // new Address(newUser.publicKey()).toScVal(), + // ] + // const withdrawResult = await invokeCustomContract( + // blendVaultAddress, + // 'withdraw', + // withdrawParams, + // newUser, + // false + // ); + // const withdrawResultValue = scValToNative(withdrawResult.returnValue); + // console.log(green, '---------------- XLM withdrawn from the vault ----------------') + // console.log(green, 'Withdrawed: ', withdrawResultValue, ' from the vault') + // console.log(green, '--------------------------------------------------------------') + // } catch (error) { + // console.log('🚀 « error:', error); + + // } +} +await testBlendVault(); \ No newline at end of file diff --git a/apps/contracts/strategies/blend/src/blend_pool.rs b/apps/contracts/strategies/blend/src/blend_pool.rs index 69e25274..b1ad4191 100644 --- a/apps/contracts/strategies/blend/src/blend_pool.rs +++ b/apps/contracts/strategies/blend/src/blend_pool.rs @@ -1,6 +1,6 @@ -use soroban_sdk::{vec, Address, Env, Vec}; +use soroban_sdk::{auth::{ContractContext, InvokerContractAuthEntry, SubContractInvocation}, vec, Address, Env, IntoVal, Symbol, Vec}; -use crate::storage::{get_blend_pool, get_underlying_asset}; +use crate::storage::get_blend_pool; soroban_sdk::contractimport!( file = "../external_wasms/blend/blend_pool.wasm" @@ -11,10 +11,10 @@ pub type BlendPoolClient<'a> = Client<'a>; #[derive(Clone, PartialEq)] #[repr(u32)] pub enum RequestType { - // Supply = 0, - // Withdraw = 1, - SupplyCollateral = 2, - WithdrawCollateral = 3, + Supply = 0, + Withdraw = 1, + // SupplyCollateral = 2, + // WithdrawCollateral = 3, // Borrow = 4, // Repay = 5, // FillUserLiquidationAuction = 6, @@ -30,20 +30,57 @@ impl RequestType { } } -pub fn submit(e: &Env, from: &Address, amount: i128, request_type: RequestType) -> Positions { - // Setting up Blend Pool client +pub fn supply(e: &Env, from: &Address, underlying_asset: Address, amount: i128) -> Positions { let blend_pool_address = get_blend_pool(e); let blend_pool_client = BlendPoolClient::new(e, &blend_pool_address); - let underlying_asset = get_underlying_asset(&e); + let requests: Vec = vec![&e, Request { + address: underlying_asset.clone(), + amount, + request_type: RequestType::Supply.to_u32(), + }]; + + e.authorize_as_current_contract(vec![ + &e, + InvokerContractAuthEntry::Contract(SubContractInvocation { + context: ContractContext { + contract: underlying_asset.clone(), + fn_name: Symbol::new(&e, "transfer"), + args: ( + e.current_contract_address(), + blend_pool_address.clone(), + amount.clone()).into_val(e), + }, + sub_invocations: vec![&e], + }), + ]); + + blend_pool_client.submit( + &from, + &e.current_contract_address(), + &from, + &requests + ) +} + +pub fn withdraw(e: &Env, from: &Address, underlying_asset: Address, amount: i128) -> Positions { + let blend_pool_address = get_blend_pool(e); + let blend_pool_client = BlendPoolClient::new(e, &blend_pool_address); let requests: Vec = vec![&e, Request { - address: underlying_asset, - amount: amount, - request_type: request_type.to_u32(), + address: underlying_asset.clone(), + amount, + request_type: RequestType::Withdraw.to_u32(), }]; - blend_pool_client.submit(from, from, from, &requests) + let new_positions = blend_pool_client.submit( + &from, + &from, + &from, + &requests + ); + + new_positions } pub fn claim(e: &Env, from: &Address) -> i128 { @@ -51,6 +88,7 @@ pub fn claim(e: &Env, from: &Address) -> i128 { let blend_pool_address = get_blend_pool(e); let blend_pool_client = BlendPoolClient::new(e, &blend_pool_address); + // TODO: Check reserve_token_ids and how to get the correct one blend_pool_client.claim(from, &vec![&e, 3u32], from) } diff --git a/apps/contracts/strategies/blend/src/lib.rs b/apps/contracts/strategies/blend/src/lib.rs index 1cf33d72..da4c66b6 100644 --- a/apps/contracts/strategies/blend/src/lib.rs +++ b/apps/contracts/strategies/blend/src/lib.rs @@ -1,13 +1,12 @@ #![no_std] -use blend_pool::RequestType; use soroban_sdk::{ - contract, contractimpl, Address, Env, IntoVal, String, Val, Vec}; + contract, contractimpl, token::TokenClient, Address, Env, IntoVal, String, Val, Vec}; mod blend_pool; mod storage; use storage::{ - extend_instance_ttl, get_underlying_asset, is_initialized, set_blend_pool, set_initialized, set_underlying_asset + extend_instance_ttl, get_reserve_id, get_underlying_asset, is_initialized, set_blend_pool, set_initialized, set_reserve_id, set_underlying_asset }; pub use defindex_strategy_core::{ @@ -48,9 +47,11 @@ impl DeFindexStrategyTrait for BlendStrategy { } let blend_pool_address = init_args.get(0).ok_or(StrategyError::InvalidArgument)?.into_val(&e); + let reserve_id = init_args.get(1).ok_or(StrategyError::InvalidArgument)?.into_val(&e); set_initialized(&e); set_blend_pool(&e, blend_pool_address); + set_reserve_id(&e, reserve_id); set_underlying_asset(&e, &asset); event::emit_initialize(&e, String::from_str(&e, STARETEGY_NAME), asset); @@ -75,7 +76,11 @@ impl DeFindexStrategyTrait for BlendStrategy { extend_instance_ttl(&e); from.require_auth(); - blend_pool::submit(&e, &from, amount, RequestType::SupplyCollateral); + // transfer tokens from the vault to the contract + let underlying_asset = get_underlying_asset(&e); + TokenClient::new(&e, &underlying_asset).transfer(&from, &e.current_contract_address(), &amount); + + blend_pool::supply(&e, &from, underlying_asset, amount); event::emit_deposit(&e, String::from_str(&e, STARETEGY_NAME), amount, from); Ok(()) @@ -84,6 +89,7 @@ impl DeFindexStrategyTrait for BlendStrategy { fn harvest(e: Env, from: Address) -> Result<(), StrategyError> { check_initialized(&e)?; extend_instance_ttl(&e); + from.require_auth(); blend_pool::claim(&e, &from); @@ -96,12 +102,13 @@ impl DeFindexStrategyTrait for BlendStrategy { amount: i128, from: Address, ) -> Result { - from.require_auth(); check_initialized(&e)?; check_nonnegative_amount(amount)?; extend_instance_ttl(&e); + from.require_auth(); - blend_pool::submit(&e, &from, amount, RequestType::WithdrawCollateral); + let underlying_asset = get_underlying_asset(&e); + blend_pool::withdraw(&e, &from, underlying_asset, amount); event::emit_withdraw(&e, String::from_str(&e, STARETEGY_NAME), amount, from); @@ -116,9 +123,10 @@ impl DeFindexStrategyTrait for BlendStrategy { extend_instance_ttl(&e); let positions = blend_pool::get_positions(&e, &from); + let reserve_id = get_reserve_id(&e); - let collateral = positions.collateral.get(1u32).unwrap_or(0i128); - Ok(collateral) + let supply = positions.supply.get(reserve_id).unwrap_or(0i128); + Ok(supply) } } diff --git a/apps/contracts/strategies/blend/src/storage.rs b/apps/contracts/strategies/blend/src/storage.rs index dbdc3239..fa6f51b4 100644 --- a/apps/contracts/strategies/blend/src/storage.rs +++ b/apps/contracts/strategies/blend/src/storage.rs @@ -7,7 +7,8 @@ pub enum DataKey { Initialized, UnderlyingAsset, BlendPool, - Balance(Address) + Balance(Address), + ReserveId } const DAY_IN_LEDGERS: u32 = 17280; @@ -44,4 +45,12 @@ pub fn set_blend_pool(e: &Env, address: Address) { pub fn get_blend_pool(e: &Env) -> Address { e.storage().instance().get(&DataKey::BlendPool).unwrap() +} + +pub fn set_reserve_id(e: &Env, id: u32) { + e.storage().instance().set(&DataKey::ReserveId, &id); +} + +pub fn get_reserve_id(e: &Env) -> u32 { + e.storage().instance().get(&DataKey::ReserveId).unwrap() } \ No newline at end of file diff --git a/apps/contracts/strategies/blend/src/test.rs b/apps/contracts/strategies/blend/src/test.rs index ba5282eb..4e4ba291 100644 --- a/apps/contracts/strategies/blend/src/test.rs +++ b/apps/contracts/strategies/blend/src/test.rs @@ -73,7 +73,7 @@ impl<'a> HodlStrategyTest<'a> { // } } -mod initialize; -mod deposit; -mod events; -mod withdraw; \ No newline at end of file +// mod initialize; +// mod deposit; +// mod events; +// mod withdraw; \ No newline at end of file diff --git a/apps/contracts/strategies/blend/src/test/deposit.rs b/apps/contracts/strategies/blend/src/test/deposit.rs deleted file mode 100644 index 3267f974..00000000 --- a/apps/contracts/strategies/blend/src/test/deposit.rs +++ /dev/null @@ -1,79 +0,0 @@ -use crate::test::HodlStrategyTest; -use crate::test::StrategyError; -use soroban_sdk::{IntoVal, Vec, Val}; - -// test deposit with negative amount -#[test] -fn deposit_with_negative_amount() { - let test = HodlStrategyTest::setup(); - let init_fn_args: Vec = (0,).into_val(&test.env); - test.strategy.initialize(&test.token.address, &init_fn_args); - - let amount = -123456; - - let result = test.strategy.try_deposit(&amount, &test.user); - assert_eq!(result, Err(Ok(StrategyError::NegativeNotAllowed))); -} - -// check auth -#[test] -fn deposit_mock_auths() { - todo!() -} - -#[test] -fn deposit_and_withdrawal_flow() { - let test = HodlStrategyTest::setup(); - // let users = HodlStrategyTest::generate_random_users(&test.env, 1); - - // try deposit should return NotInitialized error before being initialize - - let result = test.strategy.try_deposit(&10_000_000, &test.user); - assert_eq!(result, Err(Ok(StrategyError::NotInitialized))); - - // initialize - let init_fn_args: Vec = (0,).into_val(&test.env); - test.strategy.initialize(&test.token.address, &init_fn_args); - - // Initial user token balance - let balance = test.token.balance(&test.user); - - let amount = 123456; - - // Deposit amount of token from the user to the strategy - test.strategy.deposit(&amount, &test.user); - - let balance_after_deposit = test.token.balance(&test.user); - assert_eq!(balance_after_deposit, balance - amount); - - // Reading strategy balance - let strategy_balance_after_deposit = test.token.balance(&test.strategy.address); - assert_eq!(strategy_balance_after_deposit, amount); - - // Reading user balance on strategy contract - let user_balance_on_strategy = test.strategy.balance(&test.user); - assert_eq!(user_balance_on_strategy, amount); - - - let amount_to_withdraw = 100_000; - // Withdrawing token from the strategy to user - test.strategy.withdraw(&amount_to_withdraw, &test.user); - - // Reading user balance in token - let balance = test.token.balance(&test.user); - assert_eq!(balance, balance_after_deposit + amount_to_withdraw); - - // Reading strategy balance in token - let balance = test.token.balance(&test.strategy.address); - assert_eq!(balance, amount - amount_to_withdraw); - - // Reading user balance on strategy contract - let user_balance = test.strategy.balance(&test.user); - assert_eq!(user_balance, amount - amount_to_withdraw); - - // now we will want to withdraw more of the remaining balance - let amount_to_withdraw = 200_000; - let result = test.strategy.try_withdraw(&amount_to_withdraw, &test.user); - assert_eq!(result, Err(Ok(StrategyError::InsufficientBalance))); - -} \ No newline at end of file diff --git a/apps/contracts/strategies/blend/src/test/events.rs b/apps/contracts/strategies/blend/src/test/events.rs deleted file mode 100644 index 239a9bd1..00000000 --- a/apps/contracts/strategies/blend/src/test/events.rs +++ /dev/null @@ -1,6 +0,0 @@ -// TODO: Write tests for events - -#[test] -fn test_events() { - todo!() -} \ No newline at end of file diff --git a/apps/contracts/strategies/blend/src/test/initialize.rs b/apps/contracts/strategies/blend/src/test/initialize.rs deleted file mode 100644 index 41037473..00000000 --- a/apps/contracts/strategies/blend/src/test/initialize.rs +++ /dev/null @@ -1,21 +0,0 @@ -// Cannot Initialize twice -extern crate std; -use soroban_sdk::{IntoVal, Vec, Val}; -use crate::test::HodlStrategyTest; -use crate::test::StrategyError; - -#[test] -fn cannot_initialize_twice() { - let test = HodlStrategyTest::setup(); - - let init_fn_args: Vec = (0,).into_val(&test.env); - - test.strategy.initialize(&test.token.address, &init_fn_args); - let result = test.strategy.try_initialize(&test.token.address , &init_fn_args); - assert_eq!(result, Err(Ok(StrategyError::AlreadyInitialized))); - - // get asset should return underlying asset - - let underlying_asset = test.strategy.asset(); - assert_eq!(underlying_asset, test.token.address); -} \ No newline at end of file diff --git a/apps/contracts/strategies/blend/src/test/withdraw.rs b/apps/contracts/strategies/blend/src/test/withdraw.rs deleted file mode 100644 index dd8aa9d5..00000000 --- a/apps/contracts/strategies/blend/src/test/withdraw.rs +++ /dev/null @@ -1,5 +0,0 @@ - -#[test] -fn withdraw() { - todo!() -} \ No newline at end of file From 655ce8536eb56dd253f357a563cc0a59cb27883f Mon Sep 17 00:00:00 2001 From: coderipper Date: Thu, 28 Nov 2024 20:25:20 -0300 Subject: [PATCH 07/28] blend strategy tracking positions --- apps/contracts/Cargo.lock | 10 ++ apps/contracts/strategies/blend/Cargo.toml | 1 + .../strategies/blend/src/blend_pool.rs | 88 ++++++++++------- .../strategies/blend/src/constants.rs | 6 ++ apps/contracts/strategies/blend/src/lib.rs | 98 ++++++++++++++----- .../strategies/blend/src/positions.rs | 23 +++++ .../strategies/blend/src/reserves.rs | 39 ++++++++ .../contracts/strategies/blend/src/storage.rs | 66 +++++++++---- 8 files changed, 252 insertions(+), 79 deletions(-) create mode 100644 apps/contracts/strategies/blend/src/constants.rs create mode 100644 apps/contracts/strategies/blend/src/positions.rs create mode 100644 apps/contracts/strategies/blend/src/reserves.rs diff --git a/apps/contracts/Cargo.lock b/apps/contracts/Cargo.lock index 234d602b..69666ccb 100644 --- a/apps/contracts/Cargo.lock +++ b/apps/contracts/Cargo.lock @@ -97,6 +97,7 @@ name = "blend_strategy" version = "0.1.0" dependencies = [ "defindex-strategy-core", + "soroban-fixed-point-math", "soroban-sdk", ] @@ -1093,6 +1094,15 @@ dependencies = [ "syn", ] +[[package]] +name = "soroban-fixed-point-math" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9d386a1ca0a148121b21331f9da68f33bf3dfb6de69646f719935d2dec3d49c" +dependencies = [ + "soroban-sdk", +] + [[package]] name = "soroban-ledger-snapshot" version = "21.7.6" diff --git a/apps/contracts/strategies/blend/Cargo.toml b/apps/contracts/strategies/blend/Cargo.toml index cf1a7b29..15acfa03 100644 --- a/apps/contracts/strategies/blend/Cargo.toml +++ b/apps/contracts/strategies/blend/Cargo.toml @@ -13,6 +13,7 @@ crate-type = ["cdylib"] [dependencies] soroban-sdk = { workspace = true } defindex-strategy-core = { workspace = true } +soroban-fixed-point-math = "1.2.0" [dev-dependencies] soroban-sdk = { workspace = true, features = ["testutils"] } diff --git a/apps/contracts/strategies/blend/src/blend_pool.rs b/apps/contracts/strategies/blend/src/blend_pool.rs index b1ad4191..90b527e1 100644 --- a/apps/contracts/strategies/blend/src/blend_pool.rs +++ b/apps/contracts/strategies/blend/src/blend_pool.rs @@ -1,10 +1,11 @@ -use soroban_sdk::{auth::{ContractContext, InvokerContractAuthEntry, SubContractInvocation}, vec, Address, Env, IntoVal, Symbol, Vec}; +use defindex_strategy_core::StrategyError; +use soroban_sdk::{auth::{ContractContext, InvokerContractAuthEntry, SubContractInvocation}, panic_with_error, token::TokenClient, vec, Address, Env, IntoVal, Symbol, Vec}; -use crate::storage::get_blend_pool; +use crate::storage::Config; soroban_sdk::contractimport!( - file = "../external_wasms/blend/blend_pool.wasm" -); + file = "../external_wasms/blend/blend_pool.wasm" + ); pub type BlendPoolClient<'a> = Client<'a>; // Define the RequestType enum with explicit u32 values @@ -30,13 +31,19 @@ impl RequestType { } } -pub fn supply(e: &Env, from: &Address, underlying_asset: Address, amount: i128) -> Positions { - let blend_pool_address = get_blend_pool(e); - let blend_pool_client = BlendPoolClient::new(e, &blend_pool_address); +pub fn supply(e: &Env, from: &Address, amount: &i128, config: &Config) -> i128 { + let pool_client = BlendPoolClient::new(e, &config.pool); + + // Get deposit amount pre-supply + let pre_supply = pool_client + .get_positions(&e.current_contract_address()) + .supply + .get(config.reserve_id) + .unwrap_or(0); let requests: Vec = vec![&e, Request { - address: underlying_asset.clone(), - amount, + address: config.asset.clone(), + amount: amount.clone(), request_type: RequestType::Supply.to_u32(), }]; @@ -44,58 +51,67 @@ pub fn supply(e: &Env, from: &Address, underlying_asset: Address, amount: i128) &e, InvokerContractAuthEntry::Contract(SubContractInvocation { context: ContractContext { - contract: underlying_asset.clone(), + contract: config.asset.clone(), fn_name: Symbol::new(&e, "transfer"), args: ( e.current_contract_address(), - blend_pool_address.clone(), + config.pool.clone(), amount.clone()).into_val(e), }, sub_invocations: vec![&e], }), ]); - blend_pool_client.submit( - &from, + let new_positions = pool_client.submit( + &e.current_contract_address(), &e.current_contract_address(), &from, &requests - ) + ); + + // Calculate the amount of bTokens received + let b_tokens_amount = new_positions.supply.get_unchecked(config.reserve_id) - pre_supply; + b_tokens_amount } -pub fn withdraw(e: &Env, from: &Address, underlying_asset: Address, amount: i128) -> Positions { - let blend_pool_address = get_blend_pool(e); - let blend_pool_client = BlendPoolClient::new(e, &blend_pool_address); +pub fn withdraw(e: &Env, from: &Address, amount: &i128, config: &Config) -> (i128, i128) { + let pool_client = BlendPoolClient::new(e, &config.pool); + + let pre_supply = pool_client + .get_positions(&e.current_contract_address()) + .supply + .get(config.reserve_id) + .unwrap_or_else(|| panic_with_error!(e, StrategyError::InsufficientBalance)); + + // Get balance pre-withdraw, as the pool can modify the withdrawal amount + let pre_withdrawal_balance = TokenClient::new(&e, &config.asset).balance(&from); let requests: Vec = vec![&e, Request { - address: underlying_asset.clone(), - amount, + address: config.asset.clone(), + amount: amount.clone(), request_type: RequestType::Withdraw.to_u32(), }]; - let new_positions = blend_pool_client.submit( - &from, - &from, + // Execute the withdrawal - the tokens are transferred from the pool to the vault + let new_positions = pool_client.submit( + &e.current_contract_address(), + &e.current_contract_address(), &from, &requests ); - new_positions + // Calculate the amount of tokens withdrawn and bTokens burnt + let post_withdrawal_balance = TokenClient::new(&e, &config.asset).balance(&from); + let real_amount = post_withdrawal_balance - pre_withdrawal_balance; + + // position entry is deleted if the position is cleared + let b_tokens_amount = pre_supply - new_positions.supply.get(config.reserve_id).unwrap_or(0); + (real_amount, b_tokens_amount) } -pub fn claim(e: &Env, from: &Address) -> i128 { - // Setting up Blend Pool client - let blend_pool_address = get_blend_pool(e); - let blend_pool_client = BlendPoolClient::new(e, &blend_pool_address); +pub fn claim(e: &Env, from: &Address, config: &Config) -> i128 { + let pool_client = BlendPoolClient::new(e, &config.pool); // TODO: Check reserve_token_ids and how to get the correct one - blend_pool_client.claim(from, &vec![&e, 3u32], from) -} - -pub fn get_positions(e: &Env, from: &Address) -> Positions { - // Setting up Blend Pool client - let blend_pool_address = get_blend_pool(e); - let blend_pool_client = BlendPoolClient::new(e, &blend_pool_address); - - blend_pool_client.get_positions(from) + pool_client.claim(from, &vec![&e, 3u32], from) } \ No newline at end of file diff --git a/apps/contracts/strategies/blend/src/constants.rs b/apps/contracts/strategies/blend/src/constants.rs new file mode 100644 index 00000000..903615cf --- /dev/null +++ b/apps/contracts/strategies/blend/src/constants.rs @@ -0,0 +1,6 @@ +/// 1 with 7 decimal places +pub const SCALAR_7: i128 = 1_0000000; +/// 1 with 9 decimal places +pub const SCALAR_9: i128 = 1_000_000_000; +/// The minimum amount of tokens than can be deposited or withdrawn from the vault +pub const MIN_DUST: i128 = 0_0010000; diff --git a/apps/contracts/strategies/blend/src/lib.rs b/apps/contracts/strategies/blend/src/lib.rs index da4c66b6..881e51a1 100644 --- a/apps/contracts/strategies/blend/src/lib.rs +++ b/apps/contracts/strategies/blend/src/lib.rs @@ -1,13 +1,15 @@ #![no_std] +use constants::MIN_DUST; use soroban_sdk::{ - contract, contractimpl, token::TokenClient, Address, Env, IntoVal, String, Val, Vec}; + contract, contractimpl, panic_with_error, token::TokenClient, Address, Env, IntoVal, String, Val, Vec}; mod blend_pool; +mod constants; +mod positions; +mod reserves; mod storage; -use storage::{ - extend_instance_ttl, get_reserve_id, get_underlying_asset, is_initialized, set_blend_pool, set_initialized, set_reserve_id, set_underlying_asset -}; +use storage::{extend_instance_ttl, is_initialized, set_initialized, Config}; pub use defindex_strategy_core::{ DeFindexStrategyTrait, @@ -46,14 +48,19 @@ impl DeFindexStrategyTrait for BlendStrategy { return Err(StrategyError::AlreadyInitialized); } - let blend_pool_address = init_args.get(0).ok_or(StrategyError::InvalidArgument)?.into_val(&e); - let reserve_id = init_args.get(1).ok_or(StrategyError::InvalidArgument)?.into_val(&e); + let blend_pool_address: Address = init_args.get(0).ok_or(StrategyError::InvalidArgument)?.into_val(&e); + let reserve_id: u32 = init_args.get(1).ok_or(StrategyError::InvalidArgument)?.into_val(&e); set_initialized(&e); - set_blend_pool(&e, blend_pool_address); - set_reserve_id(&e, reserve_id); - set_underlying_asset(&e, &asset); + let config = Config { + asset: asset.clone(), + pool: blend_pool_address.clone(), + reserve_id: reserve_id.clone(), + }; + + storage::set_config(&e, config); + event::emit_initialize(&e, String::from_str(&e, STARETEGY_NAME), asset); extend_instance_ttl(&e); Ok(()) @@ -63,7 +70,7 @@ impl DeFindexStrategyTrait for BlendStrategy { check_initialized(&e)?; extend_instance_ttl(&e); - Ok(get_underlying_asset(&e)) + Ok(storage::get_config(&e).asset) } fn deposit( @@ -76,11 +83,29 @@ impl DeFindexStrategyTrait for BlendStrategy { extend_instance_ttl(&e); from.require_auth(); - // transfer tokens from the vault to the contract - let underlying_asset = get_underlying_asset(&e); - TokenClient::new(&e, &underlying_asset).transfer(&from, &e.current_contract_address(), &amount); + // protect against rouding of reserve_vault::update_rate, as small amounts + // can cause incorrect b_rate calculations due to the pool rounding + if amount < MIN_DUST { + return Err(StrategyError::InvalidArgument); //TODO: create a new error type for this + } + + let mut reserves = storage::get_strategy_reserves(&e); + + let config = storage::get_config(&e); + // transfer tokens from the vault to the strategy contract + TokenClient::new(&e, &config.asset).transfer(&from, &e.current_contract_address(), &amount); - blend_pool::supply(&e, &from, underlying_asset, amount); + let b_tokens_minted = blend_pool::supply(&e, &from, &amount, &config); + + // Keeping track of the total deposited amount and the total bTokens owned by the strategy depositors + reserves.add(amount, b_tokens_minted); + + // Keeping track of the total amount deposited by the user and the total amount of bTokens owned by the user + let mut vault_position = storage::get_vault_position(&e, &from); + vault_position.add(amount, b_tokens_minted); + + storage::set_strategy_reserves(&e, reserves); + storage::set_vault_position(&e, &from, vault_position); event::emit_deposit(&e, String::from_str(&e, STARETEGY_NAME), amount, from); Ok(()) @@ -89,9 +114,10 @@ impl DeFindexStrategyTrait for BlendStrategy { fn harvest(e: Env, from: Address) -> Result<(), StrategyError> { check_initialized(&e)?; extend_instance_ttl(&e); - from.require_auth(); + from.require_auth(); - blend_pool::claim(&e, &from); + let config = storage::get_config(&e); + blend_pool::claim(&e, &from, &config); event::emit_harvest(&e, String::from_str(&e, STARETEGY_NAME), 0i128, from); Ok(()) @@ -106,13 +132,39 @@ impl DeFindexStrategyTrait for BlendStrategy { check_nonnegative_amount(amount)?; extend_instance_ttl(&e); from.require_auth(); + + // protect against rouding of reserve_vault::update_rate, as small amounts + // can cause incorrect b_rate calculations due to the pool rounding + if amount < MIN_DUST { + return Err(StrategyError::InvalidArgument) //TODO: create a new error type for this + } + + let mut reserves = storage::get_strategy_reserves(&e); + + let config = storage::get_config(&e); + + + let (tokens_withdrawn, b_tokens_burnt) = blend_pool::withdraw(&e, &from, &amount, &config); + + + if tokens_withdrawn <= 0 { + panic_with_error!(e, StrategyError::InvalidArgument); + } + if b_tokens_burnt <= 0 { + panic_with_error!(e, StrategyError::InvalidArgument); + } + + reserves.remove(tokens_withdrawn, b_tokens_burnt); + + let mut vault_position = storage::get_vault_position(&e, &from); + vault_position.remove(amount, b_tokens_burnt); - let underlying_asset = get_underlying_asset(&e); - blend_pool::withdraw(&e, &from, underlying_asset, amount); + storage::set_strategy_reserves(&e, reserves); + storage::set_vault_position(&e, &from, vault_position); event::emit_withdraw(&e, String::from_str(&e, STARETEGY_NAME), amount, from); - Ok(amount) + Ok(tokens_withdrawn) } fn balance( @@ -122,12 +174,10 @@ impl DeFindexStrategyTrait for BlendStrategy { check_initialized(&e)?; extend_instance_ttl(&e); - let positions = blend_pool::get_positions(&e, &from); - let reserve_id = get_reserve_id(&e); + let vault_position = storage::get_vault_position(&e, &from); - let supply = positions.supply.get(reserve_id).unwrap_or(0i128); - Ok(supply) + Ok(vault_position.b_tokens) } } -mod test; \ No newline at end of file +// mod test; \ No newline at end of file diff --git a/apps/contracts/strategies/blend/src/positions.rs b/apps/contracts/strategies/blend/src/positions.rs new file mode 100644 index 00000000..efe7470c --- /dev/null +++ b/apps/contracts/strategies/blend/src/positions.rs @@ -0,0 +1,23 @@ +use soroban_sdk::contracttype; + +#[contracttype] +pub struct VaultPosition { + /// Total amount deposited by the user + pub deposited: i128, + /// Total amount withdrawn by the user + pub withdrawn: i128, + /// Total amount of bTokens owned by the user + pub b_tokens: i128, +} + +impl VaultPosition { + pub fn add(&mut self, amount: i128, b_tokens: i128) { + self.deposited += amount; + self.b_tokens += b_tokens; + } + + pub fn remove(&mut self, amount: i128, b_tokens: i128) { + self.withdrawn += amount; + self.b_tokens -= b_tokens; + } +} \ No newline at end of file diff --git a/apps/contracts/strategies/blend/src/reserves.rs b/apps/contracts/strategies/blend/src/reserves.rs new file mode 100644 index 00000000..b4598271 --- /dev/null +++ b/apps/contracts/strategies/blend/src/reserves.rs @@ -0,0 +1,39 @@ +use soroban_fixed_point_math::{i128, FixedPoint}; +use soroban_sdk::contracttype; + +use crate::constants::SCALAR_9; + +#[contracttype] +pub struct StrategyReserves { + /// The total deposited amount of the underlying asset + pub total_deposited: i128, + /// The total bToken deposits owned by the strategy depositors. + pub total_b_tokens: i128, + /// The reserve's last bRate + pub b_rate: i128, +} + +impl StrategyReserves { + pub fn add(&mut self, amount: i128, b_tokens: i128) { + // Calculate the new bRate - 9 decimal places of precision + // Update the reserve's bRate + self.b_rate = new_rate(amount, b_tokens); + + self.total_b_tokens += b_tokens; + self.total_deposited += amount; + } + + pub fn remove(&mut self, amount: i128, b_tokens: i128) { + // Calculate the new bRate - 9 decimal places of precision + // Update the reserve's bRate + self.b_rate = new_rate(amount, b_tokens); + + self.total_b_tokens -= b_tokens; + } +} + +fn new_rate(amount: i128, b_tokens: i128) -> i128 { + amount + .fixed_div_floor(b_tokens, SCALAR_9) + .unwrap() +} \ No newline at end of file diff --git a/apps/contracts/strategies/blend/src/storage.rs b/apps/contracts/strategies/blend/src/storage.rs index fa6f51b4..5485879f 100644 --- a/apps/contracts/strategies/blend/src/storage.rs +++ b/apps/contracts/strategies/blend/src/storage.rs @@ -1,19 +1,29 @@ use soroban_sdk::{contracttype, Address, Env}; +use crate::{positions::VaultPosition, reserves::StrategyReserves}; + +#[contracttype] +pub struct Config { + pub asset: Address, + pub pool: Address, + pub reserve_id: u32, +} + #[derive(Clone)] #[contracttype] pub enum DataKey { Initialized, - UnderlyingAsset, - BlendPool, - Balance(Address), - ReserveId + Config, + Reserves, + VaultPos(Address) // Vaults Positions } const DAY_IN_LEDGERS: u32 = 17280; pub const INSTANCE_BUMP_AMOUNT: u32 = 30 * DAY_IN_LEDGERS; pub const INSTANCE_LIFETIME_THRESHOLD: u32 = INSTANCE_BUMP_AMOUNT - DAY_IN_LEDGERS; +const LEDGER_BUMP: u32 = 120 * DAY_IN_LEDGERS; +const LEDGER_THRESHOLD: u32 = LEDGER_BUMP - 20 * DAY_IN_LEDGERS; pub fn extend_instance_ttl(e: &Env) { e.storage() @@ -29,28 +39,46 @@ pub fn is_initialized(e: &Env) -> bool { e.storage().instance().has(&DataKey::Initialized) } -// Underlying asset -pub fn set_underlying_asset(e: &Env, address: &Address) { - e.storage().instance().set(&DataKey::UnderlyingAsset, &address); +// Config +pub fn set_config(e: &Env, config: Config) { + e.storage().instance().set(&DataKey::Config, &config); } -pub fn get_underlying_asset(e: &Env) -> Address { - e.storage().instance().get(&DataKey::UnderlyingAsset).unwrap() +pub fn get_config(e: &Env) -> Config { + e.storage().instance().get(&DataKey::Config).unwrap() +} + +// Vault Position +pub fn set_vault_position(e: &Env, address: &Address, vault_position: VaultPosition) { + let key = DataKey::VaultPos(address.clone()); + e.storage().persistent().set(&key, &vault_position); + e.storage() + .persistent() + .extend_ttl(&key, LEDGER_THRESHOLD, LEDGER_BUMP); } -// Blend Pool Address -pub fn set_blend_pool(e: &Env, address: Address) { - e.storage().instance().set(&DataKey::BlendPool, &address); +pub fn get_vault_position(e: &Env, address: &Address) -> VaultPosition { + e.storage().persistent().get(&DataKey::VaultPos(address.clone())).unwrap_or( + VaultPosition { + deposited: 0, + withdrawn: 0, + b_tokens: 0, + } + ) } -pub fn get_blend_pool(e: &Env) -> Address { - e.storage().instance().get(&DataKey::BlendPool).unwrap() +// Strategy Reserves +pub fn set_strategy_reserves(e: &Env, new_reserves: StrategyReserves) { + e.storage().instance().set(&DataKey::Reserves, &new_reserves); } -pub fn set_reserve_id(e: &Env, id: u32) { - e.storage().instance().set(&DataKey::ReserveId, &id); +pub fn get_strategy_reserves(e: &Env) -> StrategyReserves { + e.storage().instance().get(&DataKey::Reserves).unwrap_or( + StrategyReserves { + total_deposited: 0, + total_b_tokens: 0, + b_rate: 0, + } + ) } -pub fn get_reserve_id(e: &Env) -> u32 { - e.storage().instance().get(&DataKey::ReserveId).unwrap() -} \ No newline at end of file From 0e66d5e2b37a050ee995af1235a3c2c028a794c6 Mon Sep 17 00:00:00 2001 From: coderipper Date: Fri, 29 Nov 2024 11:38:31 -0300 Subject: [PATCH 08/28] Keeping track of shares --- .../strategies/blend/src/blend_pool.rs | 2 +- apps/contracts/strategies/blend/src/lib.rs | 48 +++---- .../strategies/blend/src/positions.rs | 23 ---- .../strategies/blend/src/reserves.rs | 123 +++++++++++++++--- .../contracts/strategies/blend/src/storage.rs | 27 ++-- 5 files changed, 140 insertions(+), 83 deletions(-) delete mode 100644 apps/contracts/strategies/blend/src/positions.rs diff --git a/apps/contracts/strategies/blend/src/blend_pool.rs b/apps/contracts/strategies/blend/src/blend_pool.rs index 90b527e1..1f8c324f 100644 --- a/apps/contracts/strategies/blend/src/blend_pool.rs +++ b/apps/contracts/strategies/blend/src/blend_pool.rs @@ -113,5 +113,5 @@ pub fn claim(e: &Env, from: &Address, config: &Config) -> i128 { let pool_client = BlendPoolClient::new(e, &config.pool); // TODO: Check reserve_token_ids and how to get the correct one - pool_client.claim(from, &vec![&e, 3u32], from) + pool_client.claim(from, &vec![&e, config.reserve_id], from) } \ No newline at end of file diff --git a/apps/contracts/strategies/blend/src/lib.rs b/apps/contracts/strategies/blend/src/lib.rs index 881e51a1..fd113551 100644 --- a/apps/contracts/strategies/blend/src/lib.rs +++ b/apps/contracts/strategies/blend/src/lib.rs @@ -5,7 +5,6 @@ use soroban_sdk::{ mod blend_pool; mod constants; -mod positions; mod reserves; mod storage; @@ -89,7 +88,13 @@ impl DeFindexStrategyTrait for BlendStrategy { return Err(StrategyError::InvalidArgument); //TODO: create a new error type for this } - let mut reserves = storage::get_strategy_reserves(&e); + // Harvest if rewards exceed threshold + // let rewards = blend_pool::claim_rewards(&e); + // if rewards > REWARD_THRESHOLD { + // blend_pool::reinvest_rewards(&e, rewards); + // } + + let reserves = storage::get_strategy_reserves(&e); let config = storage::get_config(&e); // transfer tokens from the vault to the strategy contract @@ -98,14 +103,7 @@ impl DeFindexStrategyTrait for BlendStrategy { let b_tokens_minted = blend_pool::supply(&e, &from, &amount, &config); // Keeping track of the total deposited amount and the total bTokens owned by the strategy depositors - reserves.add(amount, b_tokens_minted); - - // Keeping track of the total amount deposited by the user and the total amount of bTokens owned by the user - let mut vault_position = storage::get_vault_position(&e, &from); - vault_position.add(amount, b_tokens_minted); - - storage::set_strategy_reserves(&e, reserves); - storage::set_vault_position(&e, &from, vault_position); + reserves::deposit(&e, reserves, &from, amount, b_tokens_minted); event::emit_deposit(&e, String::from_str(&e, STARETEGY_NAME), amount, from); Ok(()) @@ -117,7 +115,12 @@ impl DeFindexStrategyTrait for BlendStrategy { from.require_auth(); let config = storage::get_config(&e); - blend_pool::claim(&e, &from, &config); + let _harvested_blend = blend_pool::claim(&e, &from, &config); + + // should swap to usdc + // should supply to the pool + + // etcetc event::emit_harvest(&e, String::from_str(&e, STARETEGY_NAME), 0i128, from); Ok(()) @@ -139,28 +142,13 @@ impl DeFindexStrategyTrait for BlendStrategy { return Err(StrategyError::InvalidArgument) //TODO: create a new error type for this } - let mut reserves = storage::get_strategy_reserves(&e); + let reserves = storage::get_strategy_reserves(&e); let config = storage::get_config(&e); - let (tokens_withdrawn, b_tokens_burnt) = blend_pool::withdraw(&e, &from, &amount, &config); - - if tokens_withdrawn <= 0 { - panic_with_error!(e, StrategyError::InvalidArgument); - } - if b_tokens_burnt <= 0 { - panic_with_error!(e, StrategyError::InvalidArgument); - } - - reserves.remove(tokens_withdrawn, b_tokens_burnt); - - let mut vault_position = storage::get_vault_position(&e, &from); - vault_position.remove(amount, b_tokens_burnt); - - storage::set_strategy_reserves(&e, reserves); - storage::set_vault_position(&e, &from, vault_position); + let _burnt_shares = reserves::withdraw(&e, reserves, &from, tokens_withdrawn, b_tokens_burnt); event::emit_withdraw(&e, String::from_str(&e, STARETEGY_NAME), amount, from); @@ -174,9 +162,9 @@ impl DeFindexStrategyTrait for BlendStrategy { check_initialized(&e)?; extend_instance_ttl(&e); - let vault_position = storage::get_vault_position(&e, &from); + let vault_shares = storage::get_vault_shares(&e, &from); - Ok(vault_position.b_tokens) + Ok(vault_shares) } } diff --git a/apps/contracts/strategies/blend/src/positions.rs b/apps/contracts/strategies/blend/src/positions.rs deleted file mode 100644 index efe7470c..00000000 --- a/apps/contracts/strategies/blend/src/positions.rs +++ /dev/null @@ -1,23 +0,0 @@ -use soroban_sdk::contracttype; - -#[contracttype] -pub struct VaultPosition { - /// Total amount deposited by the user - pub deposited: i128, - /// Total amount withdrawn by the user - pub withdrawn: i128, - /// Total amount of bTokens owned by the user - pub b_tokens: i128, -} - -impl VaultPosition { - pub fn add(&mut self, amount: i128, b_tokens: i128) { - self.deposited += amount; - self.b_tokens += b_tokens; - } - - pub fn remove(&mut self, amount: i128, b_tokens: i128) { - self.withdrawn += amount; - self.b_tokens -= b_tokens; - } -} \ No newline at end of file diff --git a/apps/contracts/strategies/blend/src/reserves.rs b/apps/contracts/strategies/blend/src/reserves.rs index b4598271..de2dcdeb 100644 --- a/apps/contracts/strategies/blend/src/reserves.rs +++ b/apps/contracts/strategies/blend/src/reserves.rs @@ -1,12 +1,13 @@ +use defindex_strategy_core::StrategyError; use soroban_fixed_point_math::{i128, FixedPoint}; -use soroban_sdk::contracttype; +use soroban_sdk::{contracttype, panic_with_error, Address, Env}; -use crate::constants::SCALAR_9; +use crate::{constants::SCALAR_9, storage}; #[contracttype] pub struct StrategyReserves { /// The total deposited amount of the underlying asset - pub total_deposited: i128, + pub total_shares: i128, /// The total bToken deposits owned by the strategy depositors. pub total_b_tokens: i128, /// The reserve's last bRate @@ -14,26 +15,112 @@ pub struct StrategyReserves { } impl StrategyReserves { - pub fn add(&mut self, amount: i128, b_tokens: i128) { - // Calculate the new bRate - 9 decimal places of precision - // Update the reserve's bRate - self.b_rate = new_rate(amount, b_tokens); - - self.total_b_tokens += b_tokens; - self.total_deposited += amount; + /// Converts a b_token amount to shares rounding down + pub fn b_tokens_to_shares_down(&self, amount: i128) -> i128 { + if self.total_shares == 0 || self.total_b_tokens == 0 { + return amount; + } + amount + .fixed_mul_floor(self.total_shares, self.total_b_tokens) + .unwrap() + } + + /// Converts a b_token amount to shares rounding up + pub fn b_tokens_to_shares_up(&self, amount: i128) -> i128 { + if self.total_shares == 0 || self.total_b_tokens == 0 { + return amount; + } + amount + .fixed_mul_ceil(self.total_shares, self.total_b_tokens) + .unwrap() } - pub fn remove(&mut self, amount: i128, b_tokens: i128) { + /// Coverts a share amount to a b_token amount rounding down + pub fn shares_to_b_tokens_down(&self, amount: i128) -> i128 { + amount + .fixed_div_floor(self.total_shares, self.total_b_tokens) + .unwrap() + } + + pub fn update_rate(&mut self, amount: i128, b_tokens: i128) { // Calculate the new bRate - 9 decimal places of precision // Update the reserve's bRate - self.b_rate = new_rate(amount, b_tokens); - - self.total_b_tokens -= b_tokens; + let new_rate = amount + .fixed_div_floor(b_tokens, SCALAR_9) + .unwrap(); + + self.b_rate = new_rate; } + } -fn new_rate(amount: i128, b_tokens: i128) -> i128 { - amount - .fixed_div_floor(b_tokens, SCALAR_9) - .unwrap() +/// Deposit into the reserve vault. This function expects the deposit to have already been made +/// into the pool, and accounts for the deposit in the reserve vault. +pub fn deposit( + e: &Env, + mut reserves: StrategyReserves, + from: &Address, + underlying_amount: i128, + b_tokens_amount: i128, +) -> i128 { + if underlying_amount <= 0 { + panic_with_error!(e, StrategyError::InvalidArgument); //TODO: create a new error type for this + } + + if b_tokens_amount <= 0 { + panic_with_error!(e, StrategyError::InvalidArgument); //TODO: create a new error type for this + } + + reserves.update_rate(underlying_amount, b_tokens_amount); + + let mut vault_shares = storage::get_vault_shares(&e, &from); + let share_amount: i128 = reserves.b_tokens_to_shares_down(b_tokens_amount); + + reserves.total_shares += share_amount; + reserves.total_b_tokens += b_tokens_amount; + + vault_shares += share_amount; + + storage::set_strategy_reserves(&e, reserves); + storage::set_vault_shares(&e, &from, vault_shares); + share_amount +} + +/// Withdraw from the reserve vault. This function expects the withdraw to have already been made +/// from the pool, and only accounts for the withdraw from the reserve vault. +pub fn withdraw( + e: &Env, + mut reserves: StrategyReserves, + from: &Address, + underlying_amount: i128, + b_tokens_amount: i128, +) -> i128 { + if underlying_amount <= 0 { + panic_with_error!(e, StrategyError::InvalidArgument); + } + if b_tokens_amount <= 0 { + panic_with_error!(e, StrategyError::InvalidArgument); + } + + reserves.update_rate(underlying_amount, b_tokens_amount); + + let mut vault_shares = storage::get_vault_shares(&e, &from); + let share_amount = reserves.b_tokens_to_shares_up(b_tokens_amount); + + if reserves.total_shares < share_amount || reserves.total_b_tokens < b_tokens_amount { + panic_with_error!(e, StrategyError::InvalidArgument); + } + + reserves.total_shares -= share_amount; + reserves.total_b_tokens -= b_tokens_amount; + + if share_amount > vault_shares { + panic_with_error!(e, StrategyError::InvalidArgument); + } + + vault_shares -= share_amount; + storage::set_strategy_reserves(&e, reserves); + storage::set_vault_shares(&e, &from, vault_shares); + + share_amount } \ No newline at end of file diff --git a/apps/contracts/strategies/blend/src/storage.rs b/apps/contracts/strategies/blend/src/storage.rs index 5485879f..42fd9635 100644 --- a/apps/contracts/strategies/blend/src/storage.rs +++ b/apps/contracts/strategies/blend/src/storage.rs @@ -1,6 +1,6 @@ use soroban_sdk::{contracttype, Address, Env}; -use crate::{positions::VaultPosition, reserves::StrategyReserves}; +use crate::reserves::StrategyReserves; #[contracttype] pub struct Config { @@ -49,22 +49,27 @@ pub fn get_config(e: &Env) -> Config { } // Vault Position -pub fn set_vault_position(e: &Env, address: &Address, vault_position: VaultPosition) { +/// Set the number of shares shares a user owns. Shares are stored with 7 decimal places of precision. +pub fn set_vault_shares(e: &Env, address: &Address, shares: i128) { let key = DataKey::VaultPos(address.clone()); - e.storage().persistent().set(&key, &vault_position); + e.storage().persistent().set::(&key, &shares); e.storage() .persistent() .extend_ttl(&key, LEDGER_THRESHOLD, LEDGER_BUMP); } -pub fn get_vault_position(e: &Env, address: &Address) -> VaultPosition { - e.storage().persistent().get(&DataKey::VaultPos(address.clone())).unwrap_or( - VaultPosition { - deposited: 0, - withdrawn: 0, - b_tokens: 0, +/// Get the number of strategy shares a user owns. Shares are stored with 7 decimal places of precision. +pub fn get_vault_shares(e: &Env, address: &Address) -> i128 { + let result = e.storage().persistent().get::(&DataKey::VaultPos(address.clone())); + match result { + Some(shares) => { + e.storage() + .persistent() + .extend_ttl(&DataKey::VaultPos(address.clone()), LEDGER_THRESHOLD, LEDGER_BUMP); + shares } - ) + None => 0, + } } // Strategy Reserves @@ -75,7 +80,7 @@ pub fn set_strategy_reserves(e: &Env, new_reserves: StrategyReserves) { pub fn get_strategy_reserves(e: &Env) -> StrategyReserves { e.storage().instance().get(&DataKey::Reserves).unwrap_or( StrategyReserves { - total_deposited: 0, + total_shares: 0, total_b_tokens: 0, b_rate: 0, } From 30f39b94e212b820ced3ebe7ad6ef8ba5ac19ef6 Mon Sep 17 00:00:00 2001 From: Matias Poblete <86752543+MattPoblete@users.noreply.github.com> Date: Mon, 2 Dec 2024 10:19:16 -0300 Subject: [PATCH 09/28] =?UTF-8?q?=F0=9F=A9=B9=20Fix=20deposit=20function?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- apps/contracts/src/tests/blend/test_vault.ts | 2 +- apps/contracts/src/tests/vault.ts | 6 ++++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/apps/contracts/src/tests/blend/test_vault.ts b/apps/contracts/src/tests/blend/test_vault.ts index 167a121a..4be22505 100644 --- a/apps/contracts/src/tests/blend/test_vault.ts +++ b/apps/contracts/src/tests/blend/test_vault.ts @@ -173,7 +173,7 @@ export async function testBlendVault(user?: Keypair) { console.log('🚀 « investResult:', investResult); console.log(green, '---------------------- Invested in strategy ----------------------') - console.log(green, 'Invested: ', scValToNative(investResult.returnValue), ' in the strategy') + console.log(green, 'Invested: ', investResult, ' in the strategy') console.log(green, '------------------------------------------------------------------') } catch (error) { console.log('❌ Error Investing the Vault:', error); diff --git a/apps/contracts/src/tests/vault.ts b/apps/contracts/src/tests/vault.ts index 4260782b..3b99bada 100644 --- a/apps/contracts/src/tests/vault.ts +++ b/apps/contracts/src/tests/vault.ts @@ -21,9 +21,10 @@ import { airdropAccount, invokeCustomContract } from "../utils/contract.js"; const network = process.argv[2]; -export async function depositToVault(deployedVault: string, amount: number[], user?: Keypair, ) { +export async function depositToVault(deployedVault: string, amount: number[], user?: Keypair, invest?: boolean) { // Create and fund a new user account if not provided const newUser = user ? user : Keypair.random(); + const investDeposit = invest ? invest : false; console.log('🚀 ~ depositToVault ~ newUser.publicKey():', newUser.publicKey()); console.log('🚀 ~ depositToVault ~ newUser.secret():', newUser.secret()); @@ -41,7 +42,8 @@ export async function depositToVault(deployedVault: string, amount: number[], us const depositParams: xdr.ScVal[] = [ xdr.ScVal.scvVec(amountsDesired.map((amount) => nativeToScVal(amount, { type: "i128" }))), xdr.ScVal.scvVec(amountsMin.map((min) => nativeToScVal(min, { type: "i128" }))), - (new Address(newUser.publicKey())).toScVal() + (new Address(newUser.publicKey())).toScVal(), + xdr.ScVal.scvBool(investDeposit) ]; try { From 7a65c7f37c02ebe1a2ca6b82e4e3ff401296161d Mon Sep 17 00:00:00 2001 From: coderipper Date: Tue, 3 Dec 2024 15:08:21 -0300 Subject: [PATCH 10/28] blend strategy, rust tests --- apps/contracts/Cargo.lock | 20 + apps/contracts/strategies/blend/Cargo.toml | 2 + .../strategies/blend/src/blend_pool.rs | 42 +- .../strategies/blend/src/constants.rs | 2 + apps/contracts/strategies/blend/src/lib.rs | 59 ++- .../strategies/blend/src/reserves.rs | 21 + .../strategies/blend/src/soroswap.rs | 27 ++ .../contracts/strategies/blend/src/storage.rs | 4 +- apps/contracts/strategies/blend/src/test.rs | 386 +++++++++++++++--- .../strategies/blend/src/test/success.rs | 228 +++++++++++ .../external_wasms/blend/backstop.wasm | Bin 0 -> 27518 bytes .../external_wasms/blend/comet.wasm | Bin 0 -> 29046 bytes .../external_wasms/blend/emitter.wasm | Bin 0 -> 10448 bytes .../external_wasms/blend/pool_factory.wasm | Bin 0 -> 2898 bytes 14 files changed, 712 insertions(+), 79 deletions(-) create mode 100644 apps/contracts/strategies/blend/src/soroswap.rs create mode 100644 apps/contracts/strategies/blend/src/test/success.rs create mode 100644 apps/contracts/strategies/external_wasms/blend/backstop.wasm create mode 100644 apps/contracts/strategies/external_wasms/blend/comet.wasm create mode 100644 apps/contracts/strategies/external_wasms/blend/emitter.wasm create mode 100644 apps/contracts/strategies/external_wasms/blend/pool_factory.wasm diff --git a/apps/contracts/Cargo.lock b/apps/contracts/Cargo.lock index 4226274a..39fb2feb 100644 --- a/apps/contracts/Cargo.lock +++ b/apps/contracts/Cargo.lock @@ -97,6 +97,8 @@ name = "blend_strategy" version = "0.1.0" dependencies = [ "defindex-strategy-core", + "sep-40-oracle", + "sep-41-token", "soroban-fixed-point-math", "soroban-sdk", ] @@ -928,6 +930,24 @@ version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61697e0a1c7e512e84a621326239844a24d8207b4669b41bc18b32ea5cbf988b" +[[package]] +name = "sep-40-oracle" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "019c355be5fa5dac942350fff686cfd97fb6cd5302cefb69fae3ac7ec15ac72d" +dependencies = [ + "soroban-sdk", +] + +[[package]] +name = "sep-41-token" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c181783c38f2ffd99cd97c66b5e2a8f7f2e8ebfb15441d58f74485d1e1cfa20" +dependencies = [ + "soroban-sdk", +] + [[package]] name = "serde" version = "1.0.192" diff --git a/apps/contracts/strategies/blend/Cargo.toml b/apps/contracts/strategies/blend/Cargo.toml index 15acfa03..61a40a63 100644 --- a/apps/contracts/strategies/blend/Cargo.toml +++ b/apps/contracts/strategies/blend/Cargo.toml @@ -17,3 +17,5 @@ soroban-fixed-point-math = "1.2.0" [dev-dependencies] soroban-sdk = { workspace = true, features = ["testutils"] } +sep-40-oracle = { version = "1.0.0", features = ["testutils"] } +sep-41-token = { version = " 1.0.0", features = ["testutils"] } diff --git a/apps/contracts/strategies/blend/src/blend_pool.rs b/apps/contracts/strategies/blend/src/blend_pool.rs index 1f8c324f..f99f4a6f 100644 --- a/apps/contracts/strategies/blend/src/blend_pool.rs +++ b/apps/contracts/strategies/blend/src/blend_pool.rs @@ -1,7 +1,7 @@ use defindex_strategy_core::StrategyError; use soroban_sdk::{auth::{ContractContext, InvokerContractAuthEntry, SubContractInvocation}, panic_with_error, token::TokenClient, vec, Address, Env, IntoVal, Symbol, Vec}; -use crate::storage::Config; +use crate::{constants::REWARD_THRESHOLD, reserves, soroswap::internal_swap_exact_tokens_for_tokens, storage::{self, Config}}; soroban_sdk::contractimport!( file = "../external_wasms/blend/blend_pool.wasm" @@ -114,4 +114,44 @@ pub fn claim(e: &Env, from: &Address, config: &Config) -> i128 { // TODO: Check reserve_token_ids and how to get the correct one pool_client.claim(from, &vec![&e, config.reserve_id], from) +} + +pub fn perform_reinvest(e: &Env, config: &Config) -> Result{ + // Check the current BLND balance + let blnd_balance = TokenClient::new(e, &config.blend_token).balance(&e.current_contract_address()); + + // If balance does not exceed threshold, skip harvest + if blnd_balance < REWARD_THRESHOLD { + return Ok(false); + } + + // Swap BLND to the underlying asset + let mut swap_path: Vec
= vec![&e]; + swap_path.push_back(config.blend_token.clone()); + swap_path.push_back(config.asset.clone()); + + let deadline = e.ledger().timestamp() + 600; + + // Swapping BLND tokens to Underlying Asset + let swapped_amounts = internal_swap_exact_tokens_for_tokens( + e, + &blnd_balance, + &0i128, + swap_path, + &e.current_contract_address(), + &deadline, + config, + )?; + let amount_out: i128 = swapped_amounts + .get(1) + .ok_or(StrategyError::InvalidArgument)? + .into_val(e); + + // Supplying underlying asset into blend pool + let b_tokens_minted = supply(&e, &e.current_contract_address(), &amount_out, &config); + + let reserves = storage::get_strategy_reserves(&e); + reserves::harvest(&e, reserves, amount_out, b_tokens_minted); + + Ok(true) } \ No newline at end of file diff --git a/apps/contracts/strategies/blend/src/constants.rs b/apps/contracts/strategies/blend/src/constants.rs index 903615cf..b2417fec 100644 --- a/apps/contracts/strategies/blend/src/constants.rs +++ b/apps/contracts/strategies/blend/src/constants.rs @@ -4,3 +4,5 @@ pub const SCALAR_7: i128 = 1_0000000; pub const SCALAR_9: i128 = 1_000_000_000; /// The minimum amount of tokens than can be deposited or withdrawn from the vault pub const MIN_DUST: i128 = 0_0010000; + +pub const REWARD_THRESHOLD: i128 = 500_0000000; \ No newline at end of file diff --git a/apps/contracts/strategies/blend/src/lib.rs b/apps/contracts/strategies/blend/src/lib.rs index fd113551..3edb42fe 100644 --- a/apps/contracts/strategies/blend/src/lib.rs +++ b/apps/contracts/strategies/blend/src/lib.rs @@ -1,13 +1,16 @@ #![no_std] -use constants::MIN_DUST; +use blend_pool::perform_reinvest; +use constants::{MIN_DUST, SCALAR_9}; use soroban_sdk::{ - contract, contractimpl, panic_with_error, token::TokenClient, Address, Env, IntoVal, String, Val, Vec}; + contract, contractimpl, token::TokenClient, vec, Address, Env, IntoVal, String, Val, Vec}; mod blend_pool; mod constants; mod reserves; +mod soroswap; mod storage; +use soroswap::internal_swap_exact_tokens_for_tokens; use storage::{extend_instance_ttl, is_initialized, set_initialized, Config}; pub use defindex_strategy_core::{ @@ -49,13 +52,17 @@ impl DeFindexStrategyTrait for BlendStrategy { let blend_pool_address: Address = init_args.get(0).ok_or(StrategyError::InvalidArgument)?.into_val(&e); let reserve_id: u32 = init_args.get(1).ok_or(StrategyError::InvalidArgument)?.into_val(&e); + let blend_token: Address = init_args.get(2).ok_or(StrategyError::InvalidArgument)?.into_val(&e); + let soroswap_router: Address = init_args.get(3).ok_or(StrategyError::InvalidArgument)?.into_val(&e); set_initialized(&e); let config = Config { asset: asset.clone(), - pool: blend_pool_address.clone(), - reserve_id: reserve_id.clone(), + pool: blend_pool_address, + reserve_id, + blend_token, + router: soroswap_router, }; storage::set_config(&e, config); @@ -88,15 +95,11 @@ impl DeFindexStrategyTrait for BlendStrategy { return Err(StrategyError::InvalidArgument); //TODO: create a new error type for this } - // Harvest if rewards exceed threshold - // let rewards = blend_pool::claim_rewards(&e); - // if rewards > REWARD_THRESHOLD { - // blend_pool::reinvest_rewards(&e, rewards); - // } + let config = storage::get_config(&e); + perform_reinvest(&e, &config)?; let reserves = storage::get_strategy_reserves(&e); - let config = storage::get_config(&e); // transfer tokens from the vault to the strategy contract TokenClient::new(&e, &config.asset).transfer(&from, &e.current_contract_address(), &amount); @@ -112,17 +115,13 @@ impl DeFindexStrategyTrait for BlendStrategy { fn harvest(e: Env, from: Address) -> Result<(), StrategyError> { check_initialized(&e)?; extend_instance_ttl(&e); - from.require_auth(); let config = storage::get_config(&e); - let _harvested_blend = blend_pool::claim(&e, &from, &config); + let harvested_blend = blend_pool::claim(&e, &e.current_contract_address(), &config); - // should swap to usdc - // should supply to the pool + perform_reinvest(&e, &config)?; - // etcetc - - event::emit_harvest(&e, String::from_str(&e, STARETEGY_NAME), 0i128, from); + event::emit_harvest(&e, String::from_str(&e, STARETEGY_NAME), harvested_blend, from); Ok(()) } @@ -161,11 +160,29 @@ impl DeFindexStrategyTrait for BlendStrategy { ) -> Result { check_initialized(&e)?; extend_instance_ttl(&e); - + + // Get the vault's shares let vault_shares = storage::get_vault_shares(&e, &from); - - Ok(vault_shares) + + // Get the strategy's total shares and bTokens + let reserves = storage::get_strategy_reserves(&e); + let total_shares = reserves.total_shares; + let total_b_tokens = reserves.total_b_tokens; + + if total_shares == 0 || total_b_tokens == 0 { + // No shares or bTokens in the strategy + return Ok(0); + } + + // Calculate the bTokens corresponding to the vault's shares + let vault_b_tokens = (vault_shares * total_b_tokens) / total_shares; + + // Use the b_rate to convert bTokens to underlying assets + let underlying_balance = (vault_b_tokens * reserves.b_rate) / SCALAR_9; + + Ok(underlying_balance) } } -// mod test; \ No newline at end of file +#[cfg(any(test, feature = "testutils"))] +mod test; \ No newline at end of file diff --git a/apps/contracts/strategies/blend/src/reserves.rs b/apps/contracts/strategies/blend/src/reserves.rs index de2dcdeb..3369377e 100644 --- a/apps/contracts/strategies/blend/src/reserves.rs +++ b/apps/contracts/strategies/blend/src/reserves.rs @@ -123,4 +123,25 @@ pub fn withdraw( storage::set_vault_shares(&e, &from, vault_shares); share_amount +} + +pub fn harvest( + e: &Env, + mut reserves: StrategyReserves, + underlying_amount: i128, + b_tokens_amount: i128, +) { + if underlying_amount <= 0 { + panic_with_error!(e, StrategyError::InvalidArgument); //TODO: create a new error type for this + } + + if b_tokens_amount <= 0 { + panic_with_error!(e, StrategyError::InvalidArgument); //TODO: create a new error type for this + } + + reserves.update_rate(underlying_amount, b_tokens_amount); + + reserves.total_b_tokens += b_tokens_amount; + + storage::set_strategy_reserves(&e, reserves); } \ No newline at end of file diff --git a/apps/contracts/strategies/blend/src/soroswap.rs b/apps/contracts/strategies/blend/src/soroswap.rs new file mode 100644 index 00000000..7a9318ee --- /dev/null +++ b/apps/contracts/strategies/blend/src/soroswap.rs @@ -0,0 +1,27 @@ +use defindex_strategy_core::StrategyError; +use soroban_sdk::{vec, Address, Env, IntoVal, Symbol, Val, Vec}; + +use crate::storage::Config; + +pub fn internal_swap_exact_tokens_for_tokens( + e: &Env, + amount_in: &i128, + amount_out_min: &i128, + path: Vec
, + to: &Address, + deadline: &u64, + config: &Config, +) -> Result, StrategyError> { + let mut swap_args: Vec = vec![&e]; + swap_args.push_back(amount_in.into_val(e)); + swap_args.push_back(amount_out_min.into_val(e)); + swap_args.push_back(path.into_val(e)); + swap_args.push_back(to.to_val()); + swap_args.push_back(deadline.into_val(e)); + + e.invoke_contract( + &config.router, + &Symbol::new(&e, "swap_exact_tokens_for_tokens"), + swap_args, + ) +} \ No newline at end of file diff --git a/apps/contracts/strategies/blend/src/storage.rs b/apps/contracts/strategies/blend/src/storage.rs index 42fd9635..2cfe07d3 100644 --- a/apps/contracts/strategies/blend/src/storage.rs +++ b/apps/contracts/strategies/blend/src/storage.rs @@ -7,6 +7,8 @@ pub struct Config { pub asset: Address, pub pool: Address, pub reserve_id: u32, + pub blend_token: Address, + pub router: Address, } #[derive(Clone)] @@ -19,7 +21,7 @@ pub enum DataKey { VaultPos(Address) // Vaults Positions } -const DAY_IN_LEDGERS: u32 = 17280; +pub const DAY_IN_LEDGERS: u32 = 17280; pub const INSTANCE_BUMP_AMOUNT: u32 = 30 * DAY_IN_LEDGERS; pub const INSTANCE_LIFETIME_THRESHOLD: u32 = INSTANCE_BUMP_AMOUNT - DAY_IN_LEDGERS; const LEDGER_BUMP: u32 = 120 * DAY_IN_LEDGERS; diff --git a/apps/contracts/strategies/blend/src/test.rs b/apps/contracts/strategies/blend/src/test.rs index 4e4ba291..041fedaf 100644 --- a/apps/contracts/strategies/blend/src/test.rs +++ b/apps/contracts/strategies/blend/src/test.rs @@ -1,79 +1,353 @@ #![cfg(test)] -use crate::{BlendStrategy, BlendStrategyClient, StrategyError}; - -use soroban_sdk::token::{TokenClient, StellarAssetClient}; +extern crate std; +use crate::{ + blend_pool::{self, BlendPoolClient, Request, ReserveConfig, ReserveEmissionMetadata}, constants::SCALAR_7, storage::DAY_IN_LEDGERS, BlendStrategy, BlendStrategyClient +}; +use sep_41_token::testutils::MockTokenClient; +use soroban_fixed_point_math::FixedPoint; use soroban_sdk::{ - Env, - Address, - testutils::Address as _, + testutils::{Address as _, BytesN as _, Ledger as _, LedgerInfo}, token::StellarAssetClient, vec, Address, BytesN, Env, IntoVal, String, Symbol, Val, Vec }; -// mod blend_pool_module { -// soroban_sdk::contractimport!(file = "../external_wasms/blend/blend_pool.wasm"); -// pub type BlendPoolContractClient<'a> = Client<'a>; -// } +mod blend_factory_pool { + soroban_sdk::contractimport!(file = "../external_wasms/blend/pool_factory.wasm"); +} + +mod blend_emitter { + soroban_sdk::contractimport!(file = "../external_wasms/blend/emitter.wasm"); +} + +mod blend_backstop { + soroban_sdk::contractimport!(file = "../external_wasms/blend/backstop.wasm"); +} + +mod blend_comet { + soroban_sdk::contractimport!(file = "../external_wasms/blend/comet.wasm"); +} + +pub(crate) fn register_blend_strategy(e: &Env) -> Address { + e.register_contract(None, BlendStrategy {}) +} -// use blend_pool_module::BlendPoolContractClient; +pub struct BlendFixture<'a> { + pub backstop: blend_backstop::Client<'a>, + pub emitter: blend_emitter::Client<'a>, + pub backstop_token: blend_comet::Client<'a>, + pub pool_factory: blend_factory_pool::Client<'a>, +} -// // fn initialize(admin: address, name: string, oracle: address, bstop_rate: u32, max_postions: u32, backstop_id: address, blnd_id: address) +pub(crate) fn create_blend_pool( + e: &Env, + blend_fixture: &BlendFixture, + admin: &Address, + usdc: &MockTokenClient, + xlm: &MockTokenClient, +) -> Address { + // Mint usdc to admin + usdc.mint(&admin, &200_000_0000000); + // Mint xlm to admin + xlm.mint(&admin, &200_000_0000000); -// fn create_blend_pool_contract<'a>(e: &Env, asset: &Address, init_args: &Vec) -> BlendPoolContractClient<'a> { -// let address = &e.register_contract_wasm(None, hodl_strategy::WASM); -// let strategy = BlendPoolContractClient::new(e, address); -// strategy.initialize(asset, init_args); -// strategy -// } + // set up oracle + let (oracle, oracle_client) = create_mock_oracle(e); + oracle_client.set_data( + &admin, + &Asset::Other(Symbol::new(&e, "USD")), + &vec![ + e, + Asset::Stellar(usdc.address.clone()), + Asset::Stellar(xlm.address.clone()), + ], + &7, + &300, + ); + oracle_client.set_price_stable(&vec![e, 1_000_0000, 100_0000]); + let salt = BytesN::<32>::random(&e); + let pool = blend_fixture.pool_factory.deploy( + &admin, + &String::from_str(e, "TEST"), + &salt, + &oracle, + &0, + &4, + ); + let pool_client = BlendPoolClient::new(e, &pool); + blend_fixture + .backstop + .deposit(&admin, &pool, &20_0000_0000000); + let reserve_config = ReserveConfig { + c_factor: 900_0000, + decimals: 7, + index: 0, + l_factor: 900_0000, + max_util: 900_0000, + reactivity: 0, + r_base: 100_0000, + r_one: 0, + r_two: 0, + r_three: 0, + util: 0, + }; + pool_client.queue_set_reserve(&usdc.address, &reserve_config); + pool_client.set_reserve(&usdc.address); + pool_client.queue_set_reserve(&xlm.address, &reserve_config); + pool_client.set_reserve(&xlm.address); + let emission_config = vec![ + e, + ReserveEmissionMetadata { + res_index: 0, + res_type: 0, + share: 250_0000, + }, + ReserveEmissionMetadata { + res_index: 0, + res_type: 1, + share: 250_0000, + }, + ReserveEmissionMetadata { + res_index: 1, + res_type: 0, + share: 250_0000, + }, + ReserveEmissionMetadata { + res_index: 1, + res_type: 1, + share: 250_0000, + }, + ]; + pool_client.set_emissions_config(&emission_config); + pool_client.set_status(&0); + blend_fixture.backstop.add_reward(&pool, &pool); -// Blend Strategy Contract -fn create_blend_strategy<'a>(e: &Env) -> BlendStrategyClient<'a> { - BlendStrategyClient::new(e, &e.register_contract(None, BlendStrategy {})) + // wait a week and start emissions + e.jump(DAY_IN_LEDGERS * 7); + blend_fixture.emitter.distribute(); + blend_fixture.backstop.gulp_emissions(); + pool_client.gulp_emissions(); + + // admin joins pool + let requests = vec![ + e, + Request { + address: usdc.address.clone(), + amount: 200_000_0000000, + request_type: 2, + }, + Request { + address: usdc.address.clone(), + amount: 100_000_0000000, + request_type: 4, + }, + Request { + address: xlm.address.clone(), + amount: 200_000_0000000, + request_type: 2, + }, + Request { + address: xlm.address.clone(), + amount: 100_000_0000000, + request_type: 4, + }, + ]; + pool_client + .mock_all_auths() + .submit(&admin, &admin, &admin, &requests); + return pool; } -// Create Test Token -pub(crate) fn create_token_contract<'a>(e: &Env, admin: &Address) -> TokenClient<'a> { - TokenClient::new(e, &e.register_stellar_asset_contract_v2(admin.clone()).address()) +/// Create a Blend Strategy +pub(crate) fn create_blend_strategy(e: &Env, underlying_asset: &Address, blend_pool: &Address, reserve_id: &u32, blend_token: &Address, soroswap_router: &Address) -> Address { + let address = register_blend_strategy(e); + let client = BlendStrategyClient::new(e, &address); + + let init_args: Vec = vec![e, + blend_pool.into_val(e), + reserve_id.into_val(e), + blend_token.into_val(e), + soroswap_router.into_val(e), + ]; + + client.initialize(&underlying_asset, &init_args); + address } -pub struct HodlStrategyTest<'a> { - env: Env, - strategy: BlendStrategyClient<'a>, - token: TokenClient<'a>, - user: Address, +pub trait EnvTestUtils { + /// Jump the env by the given amount of ledgers. Assumes 5 seconds per ledger. + fn jump(&self, ledgers: u32); + + /// Jump the env by the given amount of seconds. Incremends the sequence by 1. + fn jump_time(&self, seconds: u64); + + /// Set the ledger to the default LedgerInfo + /// + /// Time -> 1441065600 (Sept 1st, 2015 12:00:00 AM UTC) + /// Sequence -> 100 + fn set_default_info(&self); } -impl<'a> HodlStrategyTest<'a> { - fn setup() -> Self { +impl EnvTestUtils for Env { + fn jump(&self, ledgers: u32) { + self.ledger().set(LedgerInfo { + timestamp: self.ledger().timestamp().saturating_add(ledgers as u64 * 5), + protocol_version: 21, + sequence_number: self.ledger().sequence().saturating_add(ledgers), + network_id: Default::default(), + base_reserve: 10, + min_temp_entry_ttl: 30 * DAY_IN_LEDGERS, + min_persistent_entry_ttl: 30 * DAY_IN_LEDGERS, + max_entry_ttl: 365 * DAY_IN_LEDGERS, + }); + } + + fn jump_time(&self, seconds: u64) { + self.ledger().set(LedgerInfo { + timestamp: self.ledger().timestamp().saturating_add(seconds), + protocol_version: 21, + sequence_number: self.ledger().sequence().saturating_add(1), + network_id: Default::default(), + base_reserve: 10, + min_temp_entry_ttl: 30 * DAY_IN_LEDGERS, + min_persistent_entry_ttl: 30 * DAY_IN_LEDGERS, + max_entry_ttl: 365 * DAY_IN_LEDGERS, + }); + } + + fn set_default_info(&self) { + self.ledger().set(LedgerInfo { + timestamp: 1441065600, // Sept 1st, 2015 12:00:00 AM UTC + protocol_version: 21, + sequence_number: 100, + network_id: Default::default(), + base_reserve: 10, + min_temp_entry_ttl: 30 * DAY_IN_LEDGERS, + min_persistent_entry_ttl: 30 * DAY_IN_LEDGERS, + max_entry_ttl: 365 * DAY_IN_LEDGERS, + }); + } +} + +pub fn assert_approx_eq_abs(a: i128, b: i128, delta: i128) { + assert!( + a > b - delta && a < b + delta, + "assertion failed: `(left != right)` \ + (left: `{:?}`, right: `{:?}`, epsilon: `{:?}`)", + a, + b, + delta + ); +} + +/// Asset that `b` is within `percentage` of `a` where `percentage` +/// is a percentage in decimal form as a fixed-point number with 7 decimal +/// places +pub fn assert_approx_eq_rel(a: i128, b: i128, percentage: i128) { + let rel_delta = b.fixed_mul_floor(percentage, SCALAR_7).unwrap(); + + assert!( + a > b - rel_delta && a < b + rel_delta, + "assertion failed: `(left != right)` \ + (left: `{:?}`, right: `{:?}`, epsilon: `{:?}`)", + a, + b, + rel_delta + ); +} + +/// Oracle +use sep_40_oracle::testutils::{Asset, MockPriceOracleClient, MockPriceOracleWASM}; + +pub fn create_mock_oracle<'a>(e: &Env) -> (Address, MockPriceOracleClient<'a>) { + let contract_id = Address::generate(e); + e.register_contract_wasm(&contract_id, MockPriceOracleWASM); + ( + contract_id.clone(), + MockPriceOracleClient::new(e, &contract_id), + ) +} + +impl<'a> BlendFixture<'a> { + /// Deploy a new set of Blend Protocol contracts. Mints 200k backstop + /// tokens to the deployer that can be used in the future to create up to 4 + /// reward zone pools (50k tokens each). + /// + /// This function also resets the env budget via `reset_unlimited`. + /// + /// ### Arguments + /// * `env` - The environment to deploy the contracts in + /// * `deployer` - The address of the deployer + /// * `blnd` - The address of the BLND token + /// * `usdc` - The address of the USDC token + pub fn deploy( + env: &Env, + deployer: &Address, + blnd: &Address, + usdc: &Address, + ) -> BlendFixture<'a> { + env.budget().reset_unlimited(); + let backstop = env.register_contract_wasm(None, blend_backstop::WASM); + let emitter = env.register_contract_wasm(None, blend_emitter::WASM); + let comet = env.register_contract_wasm(None, blend_comet::WASM); + let pool_factory = env.register_contract_wasm(None, blend_factory_pool::WASM); + let blnd_client = StellarAssetClient::new(env, &blnd); + let usdc_client = StellarAssetClient::new(env, &usdc); + blnd_client + .mock_all_auths() + .mint(deployer, &(1_000_0000000 * 2001)); + usdc_client + .mock_all_auths() + .mint(deployer, &(25_0000000 * 2001)); + + let comet_client: blend_comet::Client<'a> = blend_comet::Client::new(env, &comet); + comet_client.mock_all_auths().init( + &deployer, + &vec![env, blnd.clone(), usdc.clone()], + &vec![env, 0_8000000, 0_2000000], + &vec![env, 1_000_0000000, 25_0000000], + &0_0030000, + ); + + comet_client.mock_all_auths().join_pool( + &199_900_0000000, // finalize mints 100 + &vec![env, 1_000_0000000 * 2000, 25_0000000 * 2000], + deployer, + ); + + blnd_client.mock_all_auths().set_admin(&emitter); + let emitter_client: blend_emitter::Client<'a> = blend_emitter::Client::new(env, &emitter); + emitter_client + .mock_all_auths() + .initialize(&blnd, &backstop, &comet); - let env = Env::default(); - env.mock_all_auths(); + let backstop_client: blend_backstop::Client<'a> = blend_backstop::Client::new(env, &backstop); + backstop_client.mock_all_auths().initialize( + &comet, + &emitter, + &usdc, + &blnd, + &pool_factory, + &Vec::new(env), + ); - let strategy = create_blend_strategy(&env); - let admin = Address::generate(&env); - let token = create_token_contract(&env, &admin); - let user = Address::generate(&env); + let pool_hash = env.deployer().upload_contract_wasm(blend_pool::WASM); - // Mint 1,000,000,000 to user - StellarAssetClient::new(&env, &token.address).mint(&user, &1_000_000_000); + let pool_factory_client = blend_factory_pool::Client::new(env, &pool_factory); + pool_factory_client + .mock_all_auths() + .initialize(&blend_factory_pool::PoolInitMeta { + backstop, + blnd_id: blnd.clone(), + pool_hash, + }); + backstop_client.update_tkn_val(); - HodlStrategyTest { - env, - strategy, - token, - user + BlendFixture { + backstop: backstop_client, + emitter: emitter_client, + backstop_token: comet_client, + pool_factory: pool_factory_client, } } - - // pub(crate) fn generate_random_users(e: &Env, users_count: u32) -> vec::Vec
{ - // let mut users = vec![]; - // for _c in 0..users_count { - // users.push(Address::generate(e)); - // } - // users - // } } -// mod initialize; -// mod deposit; -// mod events; -// mod withdraw; \ No newline at end of file +mod success; \ No newline at end of file diff --git a/apps/contracts/strategies/blend/src/test/success.rs b/apps/contracts/strategies/blend/src/test/success.rs new file mode 100644 index 00000000..46511ff2 --- /dev/null +++ b/apps/contracts/strategies/blend/src/test/success.rs @@ -0,0 +1,228 @@ +#![cfg(test)] +use crate::blend_pool::{BlendPoolClient, Request}; +use crate::constants::{MIN_DUST, SCALAR_7}; +use crate::storage::DAY_IN_LEDGERS; +use crate::test::{create_blend_pool, create_blend_strategy, BlendFixture, EnvTestUtils}; +use crate::BlendStrategyClient; +use defindex_strategy_core::StrategyError; +use sep_41_token::testutils::MockTokenClient; +use soroban_fixed_point_math::FixedPoint; +use soroban_sdk::testutils::{Address as _, AuthorizedFunction, AuthorizedInvocation}; +use soroban_sdk::{vec, Address, Env, Error, IntoVal, Symbol}; +use crate::test::std; + +#[test] +fn success() { + let e = Env::default(); + e.budget().reset_unlimited(); + e.mock_all_auths(); + e.set_default_info(); + + let admin = Address::generate(&e); + let user_2 = Address::generate(&e); + let user_3 = Address::generate(&e); + let user_4 = Address::generate(&e); + let user_5 = Address::generate(&e); + + let blnd = e.register_stellar_asset_contract_v2(admin.clone()); + let usdc = e.register_stellar_asset_contract_v2(admin.clone()); + let xlm = e.register_stellar_asset_contract_v2(admin.clone()); + let blnd_client = MockTokenClient::new(&e, &blnd.address()); + let usdc_client = MockTokenClient::new(&e, &usdc.address()); + let xlm_client = MockTokenClient::new(&e, &xlm.address()); + + let blend_fixture = BlendFixture::deploy(&e, &admin, &blnd.address(), &usdc.address()); + + // usdc (0) and xlm (1) charge a fixed 10% borrow rate with 0% backstop take rate + // admin deposits 200m tokens and borrows 100m tokens for a 50% util rate + // emits to each reserve token evently, and starts emissions + let pool = create_blend_pool(&e, &blend_fixture, &admin, &usdc_client, &xlm_client); + let pool_client = BlendPoolClient::new(&e, &pool); + let strategy = create_blend_strategy(&e, &usdc.address(), &pool, &0u32, &blnd.address(), &Address::generate(&e)); + let strategy_client = BlendStrategyClient::new(&e, &strategy); + + /* + * Deposit into pool + * -> deposit 100 into blend strategy for each user_3 and user_4 + * -> deposit 200 into pool for user_5 + * -> admin borrow from pool to return to 50% util rate + * -> verify a deposit into an uninitialized vault fails + */ + let pool_usdc_balace_start = usdc_client.balance(&pool); + let starting_balance = 100_0000000; + usdc_client.mint(&user_3, &starting_balance); + usdc_client.mint(&user_4, &starting_balance); + + let user_3_balance = usdc_client.balance(&user_3); + assert_eq!(user_3_balance, starting_balance); + + + strategy_client.deposit(&starting_balance, &user_3); + // -> verify deposit auth + + assert_eq!( + e.auths()[0], + ( + user_3.clone(), + AuthorizedInvocation { + function: AuthorizedFunction::Contract(( + strategy.clone(), + Symbol::new(&e, "deposit"), + vec![ + &e, + starting_balance.into_val(&e), + user_3.to_val(), + ] + )), + sub_invocations: std::vec![AuthorizedInvocation { + function: AuthorizedFunction::Contract(( + usdc.address().clone(), + Symbol::new(&e, "transfer"), + vec![ + &e, + user_3.to_val(), + strategy.to_val(), + starting_balance.into_val(&e) + ] + )), + sub_invocations: std::vec![] + }] + } + ) + ); + + strategy_client.deposit(&starting_balance, &user_4); + + // verify deposit (pool b_rate still 1 as no time has passed) + assert_eq!(usdc_client.balance(&user_3), 0); + assert_eq!(usdc_client.balance(&user_4), 0); + assert_eq!(strategy_client.balance(&user_3), starting_balance); + assert_eq!(strategy_client.balance(&user_4), starting_balance); + assert_eq!( + usdc_client.balance(&pool), + pool_usdc_balace_start + starting_balance * 2 + ); + let vault_positions = pool_client.get_positions(&strategy); + assert_eq!(vault_positions.supply.get(0).unwrap(), starting_balance * 2); + + // user_5 deposit directly into pool + let merry_starting_balance = 200_0000000; + usdc_client.mint(&user_5, &merry_starting_balance); + pool_client.submit( + &user_5, + &user_5, + &user_5, + &vec![ + &e, + Request { + request_type: 0, + address: usdc.address().clone(), + amount: merry_starting_balance, + }, + ], + ); + + // admin borrow back to 50% util rate + let borrow_amount = (merry_starting_balance + starting_balance * 2) / 2; + pool_client.submit( + &admin, + &admin, + &admin, + &vec![ + &e, + Request { + request_type: 4, + address: usdc.address().clone(), + amount: borrow_amount, + }, + ], + ); + + /* + * Allow 1 week to pass + */ + e.jump(DAY_IN_LEDGERS * 7); + + /* + * Withdraw from pool + * -> withdraw all funds from pool for user_5 + * -> withdraw (excluding dust) from blend strategy for user_3 and user_4 + * -> verify a withdraw from an uninitialized vault fails + * -> verify a withdraw from an empty vault fails + * -> verify an over withdraw fails + */ + + // withdraw all funds from pool for user_5 + pool_client.submit( + &user_5, + &user_5, + &user_5, + &vec![ + &e, + Request { + request_type: 1, + address: usdc.address().clone(), + amount: merry_starting_balance * 2, + }, + ], + ); + let user_5_final_balance = usdc_client.balance(&user_5); + let user_5_profit = user_5_final_balance - merry_starting_balance; + + // withdraw from blend strategy for user_3 and user_4 + // they are expected to receive half of the profit of user_5 + let expected_user_4_profit = user_5_profit / 2; + let withdraw_amount = starting_balance + expected_user_4_profit; + // withdraw_amount = 100_0958904 + + // -> verify over withdraw fails + let result = strategy_client.try_withdraw(&(withdraw_amount + 100_000_000_0000000), &user_4); + assert_eq!(result, Err(Ok(StrategyError::InvalidArgument))); // TODO: Check which is the one failing + + strategy_client.withdraw(&withdraw_amount, &user_3); + // -> verify withdraw auth + assert_eq!( + e.auths()[0], + ( + user_3.clone(), + AuthorizedInvocation { + function: AuthorizedFunction::Contract(( + strategy.clone(), + Symbol::new(&e, "withdraw"), + vec![ + &e, + withdraw_amount.into_val(&e), + user_3.to_val(), + ] + )), + sub_invocations: std::vec![] + } + ) + ); + + strategy_client.withdraw(&withdraw_amount, &user_4); + + // -> verify withdraw + assert_eq!(usdc_client.balance(&user_3), withdraw_amount); + assert_eq!(usdc_client.balance(&user_4), withdraw_amount); + assert_eq!(strategy_client.balance(&user_3), 0); + assert_eq!(strategy_client.balance(&user_4), 0); + + // -> verify withdraw from empty vault fails + let result = strategy_client.try_withdraw(&MIN_DUST, &user_4); + assert_eq!(result, Err(Ok(StrategyError::InsufficientBalance))); + + // TODO: Finish harvest testings, pending soroswap router setup with a blend token pair with the underlying asset + /* + * Harvest + * -> claim emissions for the strategy + * -> Swaps them into the underlying asset + * -> Re invest this claimed usdc into the blend pool + */ + + // harvest + // strategy_client.harvest(&usdc, &user_2, &expected_fees); + + // -> verify harvest + +} diff --git a/apps/contracts/strategies/external_wasms/blend/backstop.wasm b/apps/contracts/strategies/external_wasms/blend/backstop.wasm new file mode 100644 index 0000000000000000000000000000000000000000..acf4b9e0478cdfd22339382b908c8cd3c7ef6a6b GIT binary patch literal 27518 zcmb`QdvILWec$hEUswRVlxT@2<>>C3u|Qjr0TM6Dc7(eUWm1wQQlw~Easq-$8y)`eR;|-yvvolJdYm>!09vIy>J@o3sA7{f^l0u(cfL z_bhEf|2ZIp{**y`&fuK&N3C{`wHM^G{-jzCT>{)0LI0UUk_^uYbAgSh^T& zDV}PcT4+5Vcs(=oGwqqFlQW-ddd<>wb8%s5rtLiwpFYz()0}*ErhQ_%HTCS&NpJ3^ z>E;cEC(C&Y?^N%ZrDkjL*wo3X`QuG*zOuNmaB^~bsy*c`^dFl#KDX3fSe$Gx%r)n| z#r|i`oLro2o|;)&npv1%@=o_mO;1m@n$J$ProGn9R%`dKHd!hhKRGpX%6m4NZY?Z& z&vTf1*85y>dSQO5-SmF6|I8wtH7DD1^OI-6_Z+Of==V$-3X{$G>CmrEPM&B^ErR1x zGYl%R@1=gVbm8;<3;stx{?Qlxo^s4ts+68HmL&L9yjTc{8Sy}OWgKFY8%9ne6j4AUlbJZPnintdkFV=_~$R-QPiH!NmH1i8l~1fVuu+$@7CS zD$q$fIGcX^;#Ds#$3uy?Gc3ou5`Skn-dk4X#9aFSZmitbTT>Q{7hMAp;O^bbtKX-oBvf36o?t{r#+c*9ZrU#t!yY2ik`Gia)!?(K)-?IeV*fcCB-E{qMY* zq`CU@AdMb~P-*3%K8R5Z6R#G96G<3N1k0(PM0a@}%JF;N1AX2$v}15i>XP<6YP#|( zp1a)UF8^0{`TmFc3bg&$oRlX>N9M%XAiaC8`nsr}6dJ{sF4hW3h~(2_l=`!^h&EMf zP}6=>(_E)=<%(~w4*UKx`V`OA!yV{g0@KPIV4)Znra?Sn+-!I%2@zi8=40ROru0pT zVPN-;-+1qXK>&SRmuN83CdiGT2IjQ@G6hBkMiC@lEwmx{G7e=ZTAoe)c!U!};}%f7 zVMyDnU-YpOfx39hGb=&+0n?rYnHezc8=?>;TlEu;ElJKx?qf8@)0jhu-5U$HrdNfl z_!G~<-f>P6Lv`c3xv6G?5r2rA0Ry|@^o@;S>~k;%=jsuxjp%{l3yElFxD_xF!-QZQ zfs$~b9GnJdiv2>?I2jZ&w{hD*uqFL64m#ZgIk(PY)dzy!%>}ReKMO&$ToQw?;RXVF z3ewBiS3mwC8Hgm19jzA+P>h{}r&uWOP~sohjvGQxo$7d_!A1D!Z12wSt2%$fnm1Nn z|KCwVP%rwk@ntFoXxiuF+5o*+FN>2w`i^I?OAYVwq;z2WUX$Cw*`%D5k|N05OPh%~ zx~~BNXHzTbFz9;!CKf+$Xc#{sQ_dZ48`N4wZI9M^7-WZ^dHa_ThYW1`rZ-!c)|>1~ zNf05YsbVVdkV8?R*jT;I+c69H;SzJEs8h&Hg7k3AvQ*{|)c4J`cTsdc%egJ0`;@9oh#MDC zgd{G=2)@Y;p!N+vZs_>|TYjx)we{6b>jQWsM-;5$&X8ukG()wy zcokXT;))Z6a?-=N9f#xlRKJzMswcAyj_`?kfmr3FH>s{^>}8G3iPx;NGJSbT3ANx* z)QG*LcPt#_&?70A^~en>!cMG%l}ONV8p<$LbQU1XFl-Yp?2mjul1-NNGNasZ95ufh zNWjB*Cn60W5V_Exix=^ahyq(71(wsaI=+OYblkhe0$xh5b7^?G9?fF@qG$rPQFxCh zY@ju$?C-;GgVA6Tp~&gE)AhnE%3Dai2d#OKqB}x4nyu57YaR)vY&R7^{ti&9;A56i z16}U8k%B_G21qB-#RGUnPSKg%R<5ipU%DuHrTWFj@?$OdwM~L9Ym!9q7kqFt1;A<- zq#04euhx7}iHzPE^<|C}WzyRG$Ik`W5pxu{zwZMDr<+C8tSE%f8_wRLdTBeCGWylLAkDXN#%B1%HnqTa)Kd3%gr7vZK;?E)=|c$a$MAQ;~22D&)7K5#X> zqS^191PI2xFT)lG^TotJ2LkH2y!}P=UgSAfk4)PM$lnW@%18$0Y^Zv=6XFLGt3m#+ zXF-1T0Wn`R76vBW@@AZs6|;C*@Xuw#%>d%tV3!|%K#c0JhMs6qZFtg;>Td;3M6RI< zCFop|1t5J-PapCo>&PfL3WB_^erZ1wR;jRc9s;etd?TN-}`K#RFp6XIiIa zwo7Iys4FDJ*kEkM{^<&7gngN52z74)Nbwfa*wnQXM+jf0+fU{_>>&ny<9qtM zbOA^Stm7ZtR(+}yh`@3%K_o!(05MX5K`SVO+KyZ(|9xV4S?m%Qr8`EF*x6S{lah5H z3cNSik}CTA2g3fm;?5`wZ7nKMcnJ2+Hd(BQuU0HWaUI!5nz%H-6Mqug2Cij2y2J%Y zoM)ssD6bw#E{Y}>QZkC8^G?Hz=K;)i9R4yKCbuQ3(M=uM@aQtQB=0YSsc^Pl#Lp+i z!>=P%g>&cX!75yIFD801x1GhqG>zY) z5Q2^VxxR_w57!aaj0oU%NN60~js$|7CmVUVjzi5zQB0ykaHE(vNHCT(=%azrjljhk zl&k@eG)|zNPpXj2hIYvOAss_97t6Z=0`-!GM9{gH#uody#vqZ=SJp^2<`QI~tMf@; z-tsejGGivo%o5|hHuVKLZcGe2^Ewi`2NXHx1A=r$PT21T9Elq+SnA&)r*YZbKAr>= z1m<naL!FtwgO@mbg+!(qgz6;(X&rlG2l;00in4ja{&? zcZV4R+~5ap_&Q!vU+>}~smP90lE~Q+=qUgYAA@W699iWk zw1ag>v^mH4o|s50W;`85_p0BLu`};JL71|`gCIgf3WVY&AXAGyG--q1AYEB z2`8C0hGdb?`>;xQzi6V9ACde%*qOaax+G4ZD>h<^;)9Zg_<)8YC*y>}2+r8y1+F=M zOdPQJ+vhrr-h`NzH#xY=GoTTq^GROoyhnE;=|zt z;sYHuk*rrFL47J+to2itwLIG0(%NitZF)uOiMe#;m;ac7zWMiFJdpIDk{)xCDA{zW zt{HzXdZ%D0DedhmZ6g&#KqF`GC;fQIzFI+gt3t^!w-OOiMl2DV)@?d37}C_LH1!bo zaeW@^T#X;4dvrluTr)*t00T^sf`qX+y&#^E_vuR*7W#3H$yh(uu8{O$?Od$WN2o`0 zMJ&KW+E%Ar+@d6>PjzBimRY5u1xH>LHfx?#L0~JIR+;Onh|7aa^WgFT^U4l?V+ql7IF{py#bQgzXOtW*8 zN9@#?Ope`LB#THutxN?8Vbu7qIz~#Pu%Mwq{5F8nX$WSLWOTYFe7=b#nb(7+M%`v@ zVr~PohNf$ZE~&)lr0*z{Q=-9!Ba6TeX*oQu^b}q~b66?&7CcFN*2cvWss^@huMyik9V(`7`Tr3qe#gTfmXy6}c9qrw{% zbU7XTUfipt4|r#caAU}fL1?s6@H(-M%?L50lpWTDQdU%Vi~VqhKH&QvXKFKs{yfXP z%LTc0vdeimx7EVA4UC>h7EE+Z-$9G!vLt;#hJMxVc`lSw+6-BM0503exvU_eXJ#ME ztL;Ef<{b;DCdw^36B_4Dq`yE?Bg^?FHHAz#BMy1shfOg8SPC$kvL~}jBO=rS=)~Kc zB4zT*Sy=cz14N6!CVUGIndm#OBAJ4)Mr~R4Is!#ZHtL8BPdi2|a2oV*zKTL}%p<~_ zNPiL8RXVtndxXof$k;_q-DDRzmJty@{xIl*J1QNB{kMCay9q=;WSw?OXgtaki5~ug zdI;!&p;~rR$FNIA=^_4b!rEQjE3iMBK@LOQ zTjjcV1+#O{*P(_4J9B8puE2s!_5H9TFg=_4s^@HZBtb=(d`A#ivx@{-!p0yoF+CGJ zL|w!VUC{bRJ_LrrZXs3cMA=!3G3A9}e%5LcBITt8J41n6Euz%;iS)9FSd3G*Q0v<) zZP0QpW_?rz74J@Emt0bZi?8Gt0T+292qnBb{Uz1Fb?GSBcdi@6ot@zGBWCgpnjhZ{ z|NG*n2oh@p8O_7FK4MiF->N`-`@?YZ^VB`WujbjZw`XL^o5(GMjA$^fZjGBJQas2Ah=IY+;J8h=(!-`R&c zTE3`D1h39QzzKIgI2JxfQ;UX~F3|d#VM340^Wy{YQ|i<3n4vNcoQc)Aa_LU1e88m6 z@Nh{dLj7nW{j*YxKxlp`jL8NwAaxe+r$93goj(KuQ9LP(1qIBsRK{R*^<4bJ=?j_2 zVBA9475WwjCpa)FoG57JfIk**+D5tHnkI0Ii-0#(S?d=zXjBDCLcZF8>XmNqNL-Nq z?8{CFv8NCf&|@6&mRmVUYB;!vAfbPf=;WeP<}>a>PNE>!R%B!%R#C%{q18OIRy4^X znzBYXhmrU!r}FYZb@#cItkve#A6K%^{5J-`$IL+{n=r)g3i{hoIwoGC?2A z1l{G7P0qo~BmR_$GO2b;O-_J`4&a5!`5-MUM37({sEf7Ck0tdLCpue|vqSh* zREQ4*6Yig)*dquZqK7+H4p7O3lFMhMTON`>R)h=_lmLoW=b-@+X`!+5d*5a$qnBI~ zaj%wKgQS;Ckg_by=q$diP+HdFX4yj93ZZTJl1*g^^=uYzUY6U(!UJMg(vuWP9TGMF zum;D-(SQOdk?C5A4>MgiRitP$X*0%q6auQysRr4rFrPnAiq@oWeICh;F>sldNIj6) zai=As9eogW$x(>j&Qa7f)h;L)J>l9Pr3E$s=Qtu&s!(|kMK+7<>}^4(BbSk6KMEHi zO6C52v113XGtV^f2oS-J6It~)X2#H!Oh6O^dUWJsKogL`8wG^+GJ9r;pkij>oXLT- zATMIXvTztPohKTZiO&GH4N5jtywAkPSuo6&%v~uyKno-aQBkbr#Sasoi&PJZyEjVE zdZ8&fj)S{Qql>UKQ7V$D-3JcVahHu1+cNeO4PpY*YvSQe=A_KhiFxo4<|*i9_ktL> z%Du7~JBh>&HnwEku^h2+<84K$N`+io5qs0t%m+#1G`engv+8Wtx|-bT z2Q1h;44pI{92jS27>qNHeBzTjV!1*LC0m0*l46%!W-0x4Zq2DN-$KI0?szaKH4?qn zlTZPbT3(@Cj*wj{zMSxijehD2@1dZU{>Ff$`Lc)Q*gUv`$M&*LChyrktg(C2Fdg~#W>4r ze*Gq{-gf&kZf;!tS6^eko433#VY|*{tuBkZ9XPbHEU1?~y<(l|<#<3j-ic9bwuW2%@Evt3Jce#Mxq z%deWBL1TA@R|B~LHUtIr-uN)BT%=-%j@LG;YG3>a`9J_|R;nugG(SnWEp9BgfW&BlFLvkoGnrL&Zr(nMDf76de0HILUmGc1tP?t+S^CA4?$z`%eqhi z^4B}E_(NR~#t}TIkTze?4yzZw^b|`Ojpal7VMR=Iuqen;NqIU?+1_txI)lPq6%`Pf zcqan-A;K7vYzhJ1Q9X|4I`%Hl-@>|}D=F3Q0+e&C9c*g&=W3f2J@!_r>EC?*s+ab& zg=-ktgczs{rh{R|a#CKp5@t?Hae`YC%tbmxq>G5On_&Ky<&OCFGTip!RZ|tH(!_=`VE)5hPM9bq?uZC&)Q0yyR5F9wm0en$${$d;$tjl^wdhZ(#DT8R=)Lr-zYw*{A-;R23^Q-WvAyG zw_a}aoU5_v8?lXVR(@T+VMY3gO%J3i(zYu;=jbaV&P5+?=Q*G^bP8S8*OI$ENevcX zFcuN&&IZB=3K0dTe`>o}IH4^osYrTbS&g4iUjAe~+}_zS`mRT{)3GGnPRQf{{7x5u zkJEyvjHTR5+7DEgkOPYm4FrdQ1?}_A{O@{HW&Wlc+{fMCN1?L?SDS;1GEl5h3S(N_{Zm;|I8P!HjdEJ)=OZ|&;H@hmLCVQ zjt94^t1X%ym_S@HS40Z^0+LrW11x{To{;!vZVevGvLn%Br&-db08Vz@SgyuL5dmWQ ze~srtI(2gXFs8t^k%E$D5Hgn(;2|uu<@zoE2!ysBiL|Mg9+zYvWKStQBSd@_Uu;Ad zk(Mpki>?kck?N_|ik%D>CPBHN&NW*sFDn(oCL2`MQX!Y=KXd7UIq)p@M-t`3JCUXH z%#mrxI+b}lWG&Qo$}0Wg@90(-h>}N+np}eRajEfO9c^~uemz?)T%(2YleKc(M~>!8 zFN1Eyf@0rI|IsC;|B|sZb`$WxUATEJ0?XDwfD&RudkBZOKAr|YQBsi0RJ@kg_PY72?iz~7iOVcL{pt7B) znwG2?1XuL4m02OPbvKHndq~N98EPYTI&;flLjP{C&Pr1zos4Enh8n@^ z-$qkEpJmHJzpuuoZ`15rOz5R)^&p#wIlM|VX0vdPMT^CHl33o}Cz!g4oJ5ZqluZZw z*szoPhQ6}q9H?^1W~ms)65W1Q)bKRLP&Py3c?GC?kb^4B(ab3Q`oRX&TK}-&p zZw0ojUaK~2Ylh`T0H~^O;-hIvpj2iq#fCqm$UvLpuh#onl$QbR#kp2l07r@ zmNurgPt|(jGwGEdE6%gi_w@!R7chhHx-URYMC5DGsE??FiIi6M7)_}C$#3acdaa`^ zZ|j<&y^Y{p3s8{=MUT={Dx>7$uBxtL+xEk*P5`+7!9eF(vGH92+^zQ zS1+TuJhVkzV~DJ%V?w2O;E!hV*V&`yDNpQ{3jX~HJ3YmV~^d!olh}0gbLrbtr zxt6e&-O-XB)DWSHw>EsYBUCD*g7>?$_;sJi6%yMNVlz=5eTx(6iVNLEru$TQg4qY^ zkf*{-Vi%2?K*W}pO${}PAXBddMfz3dL`o*ODX~PvxN~4EypqY<(XsFi@lTr^ZctF< zLJDf>q6csZq>a>Sf_Y4y#jp2Udix4uDBXI9u9e=_q8Kgd#q^fbH-hfu_RS!|{Q6B{ z;bQbKxmhuLN9wa=vy*zu>E^;t-gld5dxm53 zc6jk;YEdxJS(T~>I9NTOh?ntLI&{9qo=-{tK*NqKVxbyLv!~8{jF*qG^0n6FCp?NK zqbhqY@2K!xQztVJXE~MAQ}E?gf4O^^0y>~Ro#}|lztTBQb=Wz##_!oUky!deXT#t zm%={ZAZgfl@%ObrRzRyC1zVQK2s^-y^)WIzU28oCkr8%Q z%RtvfB=P;(>Xv}a*zjQ`!{3hyQ#STh4VgtuCXgm@2?q@ARt_w&vvm!sixOEbJ=XC|2p$k6y zy@WiMw=JCLm6hQ=13WW}IayixH9cmMGJat^5X74!kA1Bejy^y2s(J_=s7PG)jNnfc z{HnIcvN~r5D&2u9>ZzqL4e#;p(9-g>&g=&h%35+0)vy@}{W#7GaZ7~MosqI>}} zj`D*(cBqJqfCgMbJYlSsZ>xV*464rLB9|o;>yBE0gz5Hr_&TkYm%dJzFF|}{I~yHe z`EBnoZ0f7^0|!wmr4>2FIwCbk#834~y}xn&7je0L=UyX-e)rw*bovM0d>!p~5_rFGWzwbQ+9sw{& z{s{|0>NWj&-vx42L(HFV?}C72tijPqv@&~H7qXN*m{?8kNCKWP!V*B3eINq!ZmW6e zU9~VBph`skh}j6M0bgD}QP_?h#Cgt=cF7567W@P4^!799tI+0jtpaM21iTa?W0qx0 z-BS@e<0LroGVGSN;;NjoTDAha#${A5lVSLW-H2qJb|Z*URx&S=cmFOgsr5QQseg}` z2zmz*!ubpl7A@x_pa>1p5TIH0K(+`%B|Xk468cE`15!{1&*4s`9-XEsI%n{cDjlP& zdS(mBF3#1wTx~(7F4+B{=X-1tp%D#jstaY$%KLzX&X8;xYMCT62ap=fW6YlhQ1jQ} z>8q!8cuGqIK(4}u>2WT4)6j7CgeAlEk|0aLXy;1a?^=jPlf>I!qlF%vBQ_1H?^ON1 zWrW9U1Fjav<$2-6uUDjeW`E0duN6%M^rZNa6qC$&#Thq^5@FJ&OB(n!rAwfGq?TBL z2m0`siFc>xVKTi(#9+PDL7td9MPlzR&rk0?Edr&ttHMtwKSjGREw+bswkc&52L02Ga`- z5=R&wc#(H4(&}0A< zJ5Z<=oSG#Oh}zYP;TJW0vMAuW+9d*2OnuQD4Y||v4Gk*{I)y=2SmoZ}ECN7dSQjEI zh#+7iauSF`k;9|g;WeXIek*9#dg(Vz{}$_~Csv?_z3YI-x~RmhsUV4J9-w^ZbowDt zS~^R9q>V5d6t)Uz!%7IWX&d51mIfgF37LE;T{glcA? zqpVG|+D4I7IfdX^Bf_{1MvB3c5pi@3^jKC&l=dNUDUHxbs2T887E7m+VQP@d$aXIR zyd!5a0$mqfawc8QYk(nj1x$!5u7@UWww5h7W^C&MYON7FlRlFBv<6|}jEfN|Z^JBX zL`exJ+x%ry&^cT_*n64nuiWJ&viyPP11P}9GBTO3z|6f4X85fa>s*i3AS`efHH~2; zhb@*5WYEm8w17`oWNv|wR!k%+3N3uq)Rx4Qv-1(}#^DtMpt2kaK@W3JgwGhPpLH-) zJO^6)4UqaYSQ$1BVzv6adKN6-WpDeSHGg8IQn5?=mk`5D7lG8x zGS2MOK##8c>Cn10>PWL|qj#~}UqY#O+iBJ5E5J^*{gg23cO6iH-f z#E&UG-p1iNc}<0;f$q|J58+uGdH&WH=)oFm$<0eIsvoQ8~&Q$GRwMy!<|gY5K4M$8*Ylef{{pf9`Hb1d+fVLg6i1 zKOOibB9GL|Uh9FaWQvYVy4g8#%3YeWS-g_XQ)Pog_tp;PC76J^nJt+ZOar{b)nV#@ zfj&NL%naLgcGb$y1ZLr6rU-Ntj#7#dhm!6kS15b=tOSv#))N94DTU^77znJIR^{x4 zA+jk39Ys-4OZX|R)3>uTCYL>^fWE0^p|4)%;KuD)^+%2CKe=IRQ&cSJwz3E{VfNEaLTzQl5s zfB7QePlY4ESs}j6))VDHoOOmdY_O5J0SIvs2W>(^eUflR56)jW&jcrQOGZy(ciGj+ zXVZ%^a4&I{T)qebps>Oei`JB?0OPEph}(gtrjhXF?6NSgH1t%cUWVt|5o@TWd*+)P zR@i_LsHDN9+m)^zBQb}D7uxXf`drjXhNTwGSC(r5Jw)LI<70z(hkER`(Q25;CcK0c zvUPwFlh0U3vOu(g^p0ev#*P6Pc=l9LEVizJpW zWNQ#-TBl=OC$&Y~dB1ppBAysA0jQJv$WOKAmxv3=<$C!7i!Q3;ymEm(PcWbDPYxal zAl4=kUS7PR*F{J$dT7?>t9}E1>KCJ`C2Zy z7Z+v7vI2rzP>^N!h<%RVCRFOG!(kr|OJ<8sW_c2nXTb0hBxa1SmSyD{V_T1~U-+AF zPFGk-B@CjM-24WJ&LBey_b4JNqQR4?E>{Qh2Q^qPav`A4f&}S(+kK>WGid7Ro*ACCZq zYwCD=U8D4x0RLETSIbjpPPS(jPd>l4W%kb5{Y(3K6YbtpGxXd#z`J7~0A}OiNA5p7 zH~;vd`|sn>IIOqFK0LM5zJF$^{n(TD^CH-XIeYj3l}Dyd9y>WdeR}xW$;IPsd(Z6B znWgFDzrjmeHM;-8vBdGeb1ZWFR#wgpODCpU%_Yh_KlVZnAxE{z+fJQYI5XdFKDS8O zj;!v(S=;sZtba%Djc?7(Uzxl19k{J$CqK6^-#o6D-0Ib~?!C4%OOtvJE;Q1sbLS_g zPPHdz<|m(NwkLUku8Ni>7tXYG-Ck%pmKRZ57S;M^ySlsM76*pA`ua_G7x$o&`?07#f3w~S$IypXd@?>*5Ir`|L5WeT0 zGxN{3rWOZw9!(bJld0tBBM|Fo!kd22GzSLPv@UD?vqr1j-jqlpCdvN#A?p?cg?;hSgvU_y* z*zWP&dxi&xhlY0z?;ai=9vL1T9vdDX-ZL^dGBmPlWcSGM$jHd($k@pE$ez)`(V@{@ zqq|3kM@L3SN5@9TNB4{kjt!0N8rwZKJT@{mIyN>oKDK9kaC~Td*ZA)7;qj62(ebhI z@$o%-KyeS|DTx_9j#~k_4uKA^>o2|5k7T&*bYHDVFznIlP zD5udHXfQLqe}3^y`%`+K^87QX!kOmY=V1Nn#qnlyx;g#u4EmMbkscRe_aoP>`Kgn8 zTdjrGCefass=IYfU-VS}=!n~>Zr+It%kyE;AKG#0fUT94{(|q*UEO*`4 zdVaCJu=i|pzP;2qGmQ)yBI%j-34=axXR_1tnvv73IgSDHa*Cs@&Yj5zJ9U>SlOE=E z?)DFQU!hz&y#C(2eEoe@+Unbzefv0efBU)C_uq!G_wV>#<@=j_zsdIx`Thmpclq|x z?>4?=+R82n2Yq$k{gvgE4h+zCknbqpPw>5;?}K~~@IAu!vwWxc>eFQ(r)SR2OgEEb z&nKU2wic{*qxv<*I9HR$noC&M^=dMo9EEn7nmF79Hn;M^U1QQ$$duf%lpLFKFAGoX<>6HFiJc8`6*3Q$Qtl-06zIH=D%(j@bLN&Cc9 zJDFKZ%z;cNPcO90PiC)Q7jQn|!QoHqD9zEQ=vSje_E7Ea9JVqA{wkoQ9m*r}IX9u4Iw)iJopPoZ^_{=K3N` zB8XV(DqqhV@uD04jqlk1C+Xt`-q5YL(aZZ){*N7#VC0|GzXkA*hr6CuYyY^ws!T@W zGYI6oK&P9n>>3zGi}muHeCG~hq00UajiF&Wz`8@j+d_2|Iq`Lt^aiY z9R$_ox`+LmM8d3j4zog8i$CLV7OSjJUhb~A-ssOLP??W&Be_*ww~S_gbiqJ=Ct2w? zUCZR(#nIBM4n9HK`7+_R9=`iy4hDYBkNfKmt8%mvuDW5pj;XA>KV9da{7*&b`a6x~ zAJR__cl}?U$jcdP$F_*3`pRehj5*ij_`-B^$;^Bk-`8<^xqG}jxo_drDPrBGBD1B0 zDN1&WIf_$L?c*nsGmCC6Wf0EHoNV7UGvAX#SaP=}E&ixSOQGQ1Nh5cya=tT9&m7O8 zFSVyy?F0ujL@<4KJ_4ep{0_s}l`CS>r*BQ{=*n{0x-~u7YEDf*uQ{Fj>mt(~2s!OH zKR!Q2Y`D-Ox?HVY_3Jl3(tL&};%qau=~w4|MIHL|W^;{ZC`7!&`Bu_Hu*h?5Jk7B;VT5aAx zzjWqlh&e;#`+#C{D-Qp}4j3U|D{Rm`f0~u$a1Uwf`Kg)twi}~rO=fhmE$jQRX1$-z z{t`=9yKk!zpUsCC7CtpK|2(0AkehKT=!JhyUCs}+yQRZRrdSH{?pv6Ddgd8bb?i*Y zG*Q=z4E5<*GiP+=-7w#`9;VIR+`YN&D%jN0mF2dj(lygmjrtSZ-HO3v!xMr4L(-za zj+)?No2|2`OG0=wO?pCqPA2=rid!^&)Y!5ZF~^~lPhV-9b^f2TUp zWuv-$0=_|Ar86m~a-;grT)k7j!5DsEb8e5C^Jh;r+fx?v>y9mU+d^kTu%@!mT0)B* z;NsBTV`F#kau@uTTT4sRbFTWMy9VzbxqI+~dz!nB?;hN>>lpL+kz>1d4Nr|tjSmes Whjt&E8W|cJ9cng@4GkYV=KX*Cr_BNY literal 0 HcmV?d00001 diff --git a/apps/contracts/strategies/external_wasms/blend/comet.wasm b/apps/contracts/strategies/external_wasms/blend/comet.wasm new file mode 100644 index 0000000000000000000000000000000000000000..de1b1fa4293e35ee5f6e10affe2755d38f7de2df GIT binary patch literal 29046 zcmcJY36Nb^THo*X-s|q$%WdtJyxjNf8B5G2ukv`txZm?KHnwqFlGiwqTIy%3wRFqf zEnAwjqz1J;3NS`thQyVEph^ntR3YLdBup>?O$b#cGZd-{HB4n7C_qgaC{n6qfFUGI ze*f>B``&%+mh8dg*}C`KvwY_}-+q>RJD8X|6b3;M{%Lsq?&!pc@Wk#=mwu!?Z2+jKbihAygWW-}yDA{Ai<2i# z0!rQtQOkp<}9$S)rn;R+P`(!|)lvwF04Ab~ddXzd*I1z3Q!tllL7Osb=ACXq+q3~9&FIvu|!Pyf| zS^idF9`X=Wa}RA*^LegQ;T^!40V;NDwu7qQ{g^?GiBFfmh)MzN5k95IjZ{c>L@Ul#ri0icf~k#l`bMdNOF9eWi4-{hOpw zJ=8ulGkYuwlBwyb`QZ8F`6CAp2UGp~XQrli9iEvv7#!$tADx4R(LUYa<(t9^80 z@BFTbLo-LF=XXs_2Zz?aJA3BHd@z$wwh!-`pE)p1W!2pEe0zS^L6d2f|v>=c%x7ewOObF{Gt%s7N!gnM1+LVY27Q>~!!- z*sr_G{9M>K+1@(^j&s53Fqxh>)DC_qtj--fv(K{JkGMA2bKDTLwx0kQ=_-S@)9&U;I z^01lhzadChF~Amj^GkmeG#B6g>md7{)W-agJj|nWt^Ac%vXsX@p)vn{XUrD^8+3Wd zd9XPOG|t4vnOZN+UltyWEf458yG{LX0B;KO{moxfVWp>V^I)vPt^1q*`Q3$gFft0q z4m5w$7rGHWpi%x?W%Xyb)FaS`EBm*^!M6A*J<#>Gc$`$!yr^2#XkG~RH>2!!hf<%w zUJOK(kCxb)z*a;cPt-K~Se}S@aTadO6Gy>&D9?e`y8Cl4w}R~?Br5#Ij<>$!f58*8 z$q7};)>Wv`_ev{WO1A+hXn~*O0)?MwhWkxYq6gFMVRSM&Nrmr(r&>dg(aI%WxGx!_ z!!Y}BgT~t#Y0$d+^y`eCMBnEc6zLXPNgnP<>v8iWUB{c!wO|TCME`)kB$9NrKu1V$ zexMOCRKN+ZsP*d4{gXeff?Iq7vSjxsCz?S$jK}ow88C<#d>-h$N(61h%w*Zb5i0Y}5ocnjpd{mn4Dxyxy? zOzm#%G>9R3oI@9+DyJO;p?hdoY81Oho1sG>PEBG= zcsJC^kvvG2#q6A$gnC7&5q>*#kfiD1w>xSt9dQ&%RZ^xt*^V98}>^Tlye8Q#tujvsjxZPpz?th|MLFU z;XdsV4fyYI zH!g&}!mujvNs{bfYG|Ji$=u*URkp;L^eiU%N>fkyn@Q80)E%dnmX;)7vRlB#W)*N{zC2vB zWF5Gel@8pn1UKx!1(bseeX<`3>p}CEUdGb?EEjqRc5EUOTbgI}LJiu>2qrePJ|CHQ zek!{w``&0Qaztu`ALvqB20EHAI`wY|8FQe=CaO6NQ;{5;F{{S)&oQl9t5= zQFe9q55s6IuY4>R7Hccb_4^yuEkS@GscZ>G>IqqDTrF#WQdH;@8ey8dB{>ExWG~=Cv%!?y2_!Uxo>~ z4WbWbbV+QeV|JD`!{fZ(AYgl86HYHN|4w8ipULe7^+We}(U3YX)&p5s;up)S$SpFO z{uW_K_9+)nV82_7|M9m!VIx2_mvxtb-2m7TC!nhhoO&y)S8?in<9W4p%gz_*co2`# z*VFC`bV#QROSBeM7%*eW;w;8fB-vf=A0xi25oQUb>jPZ4(5Q}|Tc{K2DtwV)Igv%6 zj~{`gXg=sOfPw5YQrBom_Su>?0VUAbU^(g6lQ2$aBRwiCdACi?NS+vfqVXaz;L)aRKF5gY7UiY@S{^ zub5bs2>`y2#OD2ZjMQWg>9%=XyeE; z9n`SoBnY;krUf)^IB@^=D5Kff0q5>g2mxKMZH14eA5p8shdFr>)^sKzooPvS)yDJ% zi`4T#lMrNCAz&kF{#sz>y_w$6_??#~I`@u&=om~C00ym7XRx70+0dpH*&2i=%+}T= z@z6f*I+L^&5V4Dy*)rau1M7C*p~3rWTb{#7(FVoHM$ zFhi*(W7)%vYMwllC}ylMBv_K2hvnh z3VE;N96g$rsmBcr$AV#LKqG>r0pel=(&N{;Hj z87d=O@tP8 zYw`~@xpoGu&M+rQc60XkKqKK_rTGn^G6X94SY%E%shU^l$91g!Q99p0v!y$_-TqB* zpqCB~BrnQZjWDZp*gL1zL7JJ}6^fv`_r$lPH@cA1Ynao)ArsHGAL>z z-JPCgE!r*k;h{15&Ho~5^g)dpN=3K}HL%oX*2M~7I1*IdgV-SRo>z(X z#nx)UhN{?5^=tq%l~7OEKvFIfsIHwOK(~6jyU>Qhcw|p^%mtX4O#)MAq7)+KiP@wI zHYq7=5}DaE7>GTRdhU;vtkWPAG0P<>{xAjssbKx0Qx^~D+n}kInoJ*d)ZXfSizuT7 zHM6%#>(&49$3Ond|L(v2FCI78Y%cpjqB}DQCSIDY(uenyaO_xI<(Cw>{UKdRcw3@)cJEr(Yy^jZTZ{p2Uv|jz@ zFZ^GWErXA^M90*`J&38XbSlA3nXVR0EyZ4{VCyW7Lgr!mG)CuJV332bJZMYb>Stjr zleIe=`miG!gCWlRYVlF2uLRp?v8O(Xw=6PenfO$ii>%uvSXyF-#Sl}gyfdK@aGf$w zhxJj!zP2&jCo3-d=7M0w<%^5?&SDA_GI7yrY$jXvdb6L2gPWqe0x*kQQBeg-6-iiY ztuzIW)92{>{6=50P zZ;GhkJ<|H}8$X@w%&Q%WocASbT7M8ck!Na|jd$9~>#N;x^Br%jvcYT!3QH&mY|4?6%R1wbo| zYpLYd9Pw88)!UD^KXFi;-Pl?}3(ow|VxJ|D$Kg5wm&^STpL;&YhPTCM$d|P{ zU6fzK$SsDgS6}<7Z~p3EetB#2^egxe)`z5%fWDm`i86!iNwUs{__|i)qvb_0IZ<@Q z4BE{2K)xy;$yY5jRy}b}nON|&uw}!*sOD?(EZYqvT#SNp*5>(uSr?L1(q3*+UA$EucVbN4Ip7JWdyZM>jUy#KJ2`N zVv`Qi^?@T;&o=?Hub@dV(*Rx(bLpl+*= z7l{s>7YGZrpVHE*cR&VgPr*5`H%1 zLQ{3c+(hP?j_)Al)~`RN$IVbu`)b5Mii^nEpy(A+*Yv2!732$BLu|x@>rHhDmNcUa z3YrQ9N7C$Zz@jrHaX5oG7*T&$#H)&Uge3Swdcb+O`7b<;{ls6hnR+a)bSz}C03b6N z7MlI?^)YU4ZUKNq)?EN#oz~6!88#(b@wr7SEgSe&1P9b=DCDRUF{&Pu zLk~SK>VbpRU`bjv`k_2QB@2qS+5u7ExVEE6fmh9?V1iqZmptQ-RSNYXsZv-1twwxr z6v)0XjUijxjy}Z-j!)TAfR(a_4G1 zUiUX}z_``8Fm%JJxv#zoXCkkf{T*4ORa!0>mbD%(S!Oyz%!Z&{PTMCtb za463f8k;c1WMYbkWQupFBZ=-N+=xYacZdSA9vYA3Y=$%zC|;FsP)tmq;i8lg?vhuKQ zDs@@wlqYk_gD^{Z*6D`wtk>Owb?*D>XnuK50Bc~%GmI4&#rxlh$OWvGEB$G;9BUX! z6}_&kJXpv=dB7P*Dfhl-kf7Ce=_<^5DU8(^mMW!B>SD`Q zrXIuE$VHuw17es-S)nUJ09_HvURSWBGV$xMT#{>IEa}SnvaYa9)T=8)SJaia-}*?E#htqgF>~2 z%}+*r#q}PvCV&O#O3|^Lmeua}wXb2JN!sUv2Isffpw~nbMGU+4(i9OlJJKr@2ATsr~7}ZA!^H#wHrb60Ya5PYc;yjP+kfQeUt{twW`6ZXUisYLv zxtin~F1d!JCzKYF-i|EhyUq_T#f(L+vxriWPZ^i#jOFyAvrQy@XDDdV**cQGGd8h` z&R7XE1`Uz*4ioQ`(-70jdnaUPj=^k+FNOKQGZcT@=HLw?#-|l5cD3h>w8sedbq4`e zUX8UHlpdINu==+p{(9KBHor!6z33pJR!>T!x{xjwka}%JgUIv(M>dF5<%RCV@eBH< zd?V>P?k4p44NWic5u@GX8CN?$=gv-y9?!2Xo7k&C<~%qHU+L^8h3EOs$ln%|FBr1r zR@ZA05lu|;Mt(ISeOJaN-?sScaEba~hfmiNli$lUMSOb`_;tY{-?*5y)XRkkW2X^( zT2F6=YPlqvz$Rx2Y z&@ha&UJUDMthv3QYvq@S;!UxIdF>mzV~}6do#0)}QLDq-;$10k+ZU#mF{%%vC6I!arJCQ#+;r-E?RZy{9^-B-|_nd_tVU*Z%!iI1Ip9DP{nl z$7=XZ6H?68>YBllaI+*aiy4*tr)E3mTiN^j<}hoD*IBq0uk4DXS>6?0Siu!B5XCC2 z4Pk>KVtc2H-W92Zxgx4LR|GGuA{&UNwB8jN=y$s!mWHhMwLPvV8gtGlzN|Bf&NjZggTvA%(sWw3JbZmYJBW5EV0d~nRxz0L%X?bTdvA(lwNczs?jC^PE_`Zh* z$v0#s)elCfz@m{kpY%qAPhue0OX5PmtQNNbk;!{Rq#hd+J$tnfV9jfU61Nwpn>fC&aK^}{*HkR7H2=hpC~Ge{-9no-s zKvDMv;qXp)9}CQb`7q1WLfeG`Zti?3tlvnS$lhs<6D2hqy6fb}*kzZLsy=Z+gHfQjrbgo6apX0M2^5-wHaHnmCYGCI z%*v$;!rZsXwA}Y!)A$c3Cl`?o|ciMI?a3`>|jlnD?GGW@tU00$oEeK)^ zG@D9n`aakUvU_n1lr!HT-|U>DY@&I0*6M=%vi_(?pZMLc{Y=P&P>1bBa)XT1Fvu90 z0#?q%CoI;LE5*99EFF!k;j^UKQ_CiRg-uq{@MehPI`j(tSKw%RwH8F)kwxXdzN~5b6{_^CP-WMXtJvkW%j&77 zrUsn&RtRd+&ruwL71Yb@l1xpwRDNebCML=U75B01!KJH!7CM>*(y9Z4b|&m8Ghs%Z z-D(D&PKEo_zNEl~1uH8sP7D>cl_M!|ZMgz#M;L@xQee4`k^-~YX==9mZ%u)*!QZ_C z(})R5KXIO{+dv|8c|5N!Q%-hxaJXfk8m6f0h;yCVA9o!p!@Ewy&P2j# zqtx|+ONtO)G37chx?J`@3)d;lWl-{>W|KhD+az=0Z@3~;*R$$EdMtHyQNL5yGb^d9 z)+<@J&F+-CUP8o))Jh6@Wpy3aLUOr!p{|7VkQ#UQZIHpkqF)_#z00dBrIJxu7Osc^ zS9r;c&#HBMP|H5|=1E{5pqs#0`-k5F__>+0rtIY&0cP5DglEWFr1L_@1>c_4ZPgo4@jw^+1)Yv!vF+7wfAg*X`WtWkWnfNDW&q+j72RzfRc^PW zH>_NnYsGUC*m@0>K5vW9hs~uQJg-wRMg#9i*~cG3HHX48&G57+cNbypZUahvg{Ylff3*EtVrYo*mG*;2sTT zouqR>-@Dzfd@!vAH`7A}Du~2;Xst=T>A2Tg6!tQaFj{L1286?p=Y8)|X%u*LxdJO= zxdN}OpBJ1GD&Y0HEDgs`No&`TL>b+{8tAZB=SJ!r$7@<~w{f4vB}lxTPOlLB7UF5n z*wp`w>w^GXo4d3{uuc8ZEp?80(I)WP*7B&B1qG-5%sr||xmf}>i>0$=#cnXY#W<7? ziYVO2@42X$1CBa2*>U8J5q#~iOhAUORcy?0Cj7IR17{3IwCqC&XLi#3{+ld1!dO99g5xFWGqOtC*0`@jvTh4^wTU+G{Zb_FENDv zC5F&mVhEej{iPOsW`Q%2)Hr8n7HNEoy%phB2?ACLv;cwNl2C9ExT!v)80 zik@URd@n z2MwKt!*4Av9_Hxzk`BO{QNtl^1uKrb^6d%ts)yck(b?x9eO2SKkL*A&3W zrC8rU%aw;E51K(;pDe-J@XoJ2jOjt=Vf8*)j^PJ_hNu-r-reC zHom%h1*2Ory{EGeD`Yy{Gt;<_RtSq;1PskE85E};-Wr+NTPTLarVhKg5jYlhp_f%U zwhQ6x=#}1zBWQH`27_#aSG$lU24Na_+eN-YZ|#UyN=^E$UPn;AQs4DVI; zp@cMND>}3k6Gcni3-&%IO1=zP(JY-SscK`YgFY(h(2vbP6zFd+u|AOCbzVi#TRtdB zP|m1i{~$EQ;@ufEQHrFEYVO85`#4nk4ZRa*b_a1P4xpRDnbEr30d!BQuLkb;xqlJD zj-SUmehvw`C(Vt?nSW>H*X`7#1fk(h3;eplz^>WxhT_0DwD-rq!55`ud+ED6{%wl- z;0L1@gYd*kAO2vFoNN@p*1!Y*=4We3_B6^?rN61b!wjW=rIf7_w!fd{rg&GH#|{in zzr%#$i=pWlThGth8$J<6kXL!wfAawc#1AwTXH({ZM$9KY*r9oP*6(#gTSWwV4b`@< z`EZXtv703bg^<%WXEH)nGx|bwk-e>PHPnYeJTy#P0gb&a8ubwu*$zmgsa?dzG}}UG zvEF?}eHz$SHynw)du#Droi7PWMytqs2b}idT?l}FD8jL`4ScgeN4F6OxZ^)aAPKP@ zbGFI@?@|5RqEYeM=nZKUr2ne(3TWp2H>PA`;nZx1(PIf;+>#s;51BYdV=?~6SIc%n ztT5Yz`nzwz;K;fVlBMkGy3X;qPt@cwc;Rn99mw=^G~eFgV4TQ*Ks`QpW`RN9HY#B6 z`OsrCs5Ha$PM#x1MUeexm8f#UzAJ%-4oK^b_c5+N88;q8YOy0OuSBSt9x;(at0}mB(q}sas71$o0UP5Mg#ptxoOz2h}4B)K8Is&?# zqehr_a=MgESIw^BXyZ{N}HiMOZTVp*BrU94A*955%tjUVjCXuIuE>6 zVd7$1QAbepeKW>~jCQEU+J>knvI#FC#j+FTILE6kBUvO`L3&3ry~1s%S|d^3hO3Wq zFcRKf7!Yflcjxi3*Bgiv*TDlQ3)9v?URh6jxXd9ve3T^4xXjB`9c;_I?!^|imatvU z;EK>>sP6~cDAfvJ#E9v(U%JbTm?@?9wvc)R(5yQdOyc{%)ok~4SS1jI)J^~zL;*#T z*Xy-L62sj_-w9rVRvGF36AK7z{>nmwciyB=HBH|oyeGt#owB(Sq|-|a3sBU)=@*|^ zSfJPRXXC;T7UmbAd4#ot&P(I7$w?Fw`^zCvGPH5dmryTMiqjbZi$Y-#ZxT-Xeq?Hd;*?d^H>L{(P}n+eqJ zv(1*Y@@Bq6HWxlKC)GzRqMfr2))+pc(=#(C4W`qvOh@_IW{D1>xd#W3S7u58a{;XO z4#0^WM$PpZr0#@(5wPY7m`9!>=*cGSMZXMr^U7>`dn6{BPyn z4VC358Z4vCI7ZgXC3l*^BTE!zrx}8VwGsOqzfGtpLoquTS4yWE^eHTT$tG@|56m#f zZk0Qhv27&SuO)N%+I$E9iGqUXYxZw4$e>Uso4Cbsrh|5pJ$zY zj!(7*%{Nu?3rVTw+>t$epLH)^t1Z{OXXa3QJ|E{(yZO!;zAAgqc=O@CeD<|H%NKCl z`f{%S%x=#k-?(+pQ`7FQkLk99ET{%SaDe*=_s??Axc?B>KJGupy`TH?dPRAWU$iUg z>pQ?*Ji6__1-#)>KSlki>B;udIR-H?>py`T1YeD^phn#r!Yrt8-@;wEe!}1HhcJAI z_@2%edUx=p;rrX|=D~wIMTaNadr59@@12>Qyq8bYTIP;@6SM7|`d+W4=EjfgIXJb~ zT24*dM|khI5B$>7eMPtBKGpmEGkmXi2Os@yHzyBGP3vR1bBFoXEg#YSE$~Ue>+9Tw zuOol^=;5i^iTSCS>0Jlglh0G{lE?ecxsOuMST>pOe)O6d0F4sYJFJD-`( zC-U8N+1{PMIC1buJ7`{5LN=Z)iN@sAi&K;Be9y7`v+da#!0Gqy@*cq{mrqPi_DYre z#$Y<(KeXDp`R@i7-w7`6_G#eav%vl{!~Rhp2zDO_{tM5-zveCyMX^};&o>X-=aJzb zG~D~*R>R$0+()GYW4Lk#N*_|z^J-oARZWKHl#KtFOOao5;-dn~PgR3opC1MVz4@JQ zDhGr{y+8M5>mUeyb~x`6MPEhj(x`7w6tNb~hu5w9!s zdnF!R38&s~yRY;O`7TbEmB}(*%k=3=^7{Vqg2=rex3^vjT3rsWE6La@ld)x<7rGZR zcqQDHf9ziTD(qhE(8TnFJQ%-1&z071g>T|pe$h6@e<`DQwn8rN{%*c2QN03R|D8C&*%54Sm0GL-E}Qhe>onP`B1+#c)u`~f7D-%WwZ2KNjFxK zf#rDh{#^hEYk8f^{;>e6f6)F*e{R4!FW@Ei=LEX)QY)e*YOO@y&R;5^ywHL7f}swp z&eJH_k(<$X$6i)mz_kZ1H6Ih`x!_?mHEG2w;n@AV2{;_91+L4+8O^&`tdO~t@bgWB zWq*6YvI`uS(@TXPq%Zep9lHEp4(m#Imi`ok;aH6Q{or^dxZS@hVPK61#rSQ!_LnBQ zWtx~2zv8b?6wl(H$_qX!zh7bfeJ{4BecYx=gnm^wS+aD&rz^!RSF*X^jow;^T>8I{ zKb2C#tDxt1i`VkLd&Yhre}d(G_Hm{0UCss-V;Q`+eRyWB+tvS%u?#)Q?00f@;-%7f z3OQMcW><=ZKgd|CZZ2sjj zk10K%i~rU9thad9eV{u9E@uZdKOrt>rlr|&Ie(~Us$4Ds{!UG&ZNA)7ke24r<${6k zq`I6P^xf~L*rnX6n{Hc9dHjQZ{MI$4(%nM7`#Y0!2Z;RI1(I1Oze~KLP0i2a)k1lN zeb;lvCihCMP-b)f-ZJ+@J6j6qmKFIc;Zcljx!qlELkoNbYq&F>Cu|Wwc?F!6?CO>L zULl8qQMqq+cE+N)Ao#E{_zjX*uxFCz0*{pZ?{7cPLI!_Dh+olvKlzVLO|#sh+^#>g z{E4HT{G#7XaAxLvB(<=|t0{YMnm}=Ck~JIFbRKTogt(Yzu4*2fZBI-ddyv03HRb+L zlJ%*@7X1d)ey+u$moO)mvMV~}`s@^FAxl4v^^u9ACR%em7y4!SQ`1knzroavCw%=* z{-8k#f+4|~nl4EedA@7|Wlppooj!Q1Fkt!%O7PX!@%?r1&;p!(8c$hu3%_UmO&oo2 zdb`$@TwN_B>F3Jk_ciqgpN_h`Rqkf+9-cZhHUFTIwG+dOK9>KeTbo$p>kn&O6GzGI zcC^-)iI1&`NozK4f0`-?*7-8w&{IJE`Vvet7ab}F!3JL@S{V_Vws862TuI=r@^#iz z2l;6pncp`vt3Q?1I@Zy?jU_k_PR|{A?zySGQ+WN3`cS^f*BJrMz3qt(7-e7W%hpj= zZeM2XHNK8$)0~`qv{B-$=RFt@}DF zk`KEDNmaSQ*Hb?Q*&m&Krn98@Az!Ys8IL?LWy^LHc0$iXR^gHM{KO>AOF3P;Q1fep z$}4Pw`%7XjZc~0arptnBM~g+m_VkM^cu#cJ37wqIbQTeN3M;d7@J8SOc+{;U81 literal 0 HcmV?d00001 diff --git a/apps/contracts/strategies/external_wasms/blend/emitter.wasm b/apps/contracts/strategies/external_wasms/blend/emitter.wasm new file mode 100644 index 0000000000000000000000000000000000000000..c6f00d0e3465362f801dca34a43f38aa1f3f6cf6 GIT binary patch literal 10448 zcmbVSYiu0Xb-wq`?1P+LYGknyP07*Sv0PKJCGUHeN>X!H4_mRVhi$2C`h!|>$I>pz zU2=Cw*@Z&VmHbG976#%U{Slx6ib8+tHU$C{Xwy^y(*9{$I6we5Kic$>AW6}p4*En9 z!2Qm-Gs~sK22M!K-aGf6d+xdCeCM2dXGSy!D^ds{*Cwy3tu48ARc^}7tJW6R)h68t zYS`qe+S(ML5KN06an(i#5fSMY{i1(MfPtw|&lc{P48u054(6CieNG;fZ8U|xK%33WGd-ovQ}EA_qk4bB5BKvy?@M3rLtp*lszGB%eHO# zKvEn~P}!JB+X=ZU)9HjI#s1`j)|T|Qx9nxq=hmL6WvFGLxwte4d#j>;U~N5E59S9q znyWjlvpkG@THGa0PA)dPi^1|egdflD9{35n)d$y4LUU)w=jU6^usI)eTb6X@=dTAm z#UQZMSXK&OI;pwSrye@<&{N~zJ6Sv;v}k+~{fS?)=Wv^Ty^*}V&(Xpa&KV`Q0C7eSvi)`Em z+4h(IJ7Fqcd^72OWZJ1nxvAzbQn`oDWI>iwe4{+s_(0xj{FS(r6#~*|X*eq4=zt?; znQX{QQ61y0X-5gCE!Eb;!grTEb(G{57th#p{@=ZNSNJLS2&D7BMfGv_h?5hB&^ii1 z4S!1u@YhOPzH)OkqiS%A<+~k_sbkc{b?5h`0#I0bf9#no1j=D}&bH>XWzVTCUuyff z5K!57#M!Kv#<=_vDbXLlz#9CTFt^j@_8+3#2cO9%K>P6}QmOJQOQcfepICCCCq61vXiqx8pCwWx3 zW}U}8^=Zt?!hFV491ix~YHYvrkM<@eR1N)Rbc5>aH$6xrNC=&{@(%ajq^STD_hUK< zAxUGFPEw)V$It=8xsQ`zMkHD>2nhuH9N~OY!G$8BfJ(LL9`MBOSc91KCX}2!o0ZcP z3J_gl6g?^91<}~K29)l8)I%6?4`EG`;*P7_DMr_wGg*lV8DjDH2Zb2|dmjX;HEnL) z2N72Ml>bBE#C_ViLndU`0f=mv@Q=uZwo4`?tXggrC3NkguwfIx7RF5Y?pXwaIbY-w z=9VI-4QuE`2PM#!Aa#*K63|>^aMmuN6cNbHa1>O}BfQuQvwcn?X3=0(?u-=9LDAqS z`^EpYOy#Z5*{(fJi%I+MnZ@iAT=UcJBT&|12luf%@cqBhVlDDaES9yZh5tQ_r3HHy zt9DaUiO4}w!=IvMNx)94j**ExGp7uEc>&)L&u0M<7K(kB$anj0Vwx;7g&9oTrvYft zo;}(C#?(4vY?{7fh+H^OETa1$f8Cca@wfE@p;q;1L>8szDY>$%XUVih*jK8FQ-p9F;Uq0~4P z!iiu>=-S1yXyJ&{7wyf4NH%Mj#rVlIgwvl-UPQv-NjewUN4R|96{YwNcz!I{h+_7ouK$ej@g)CzOMwDf! zRB^^q7qZ9*NHjq1I8tXW-N2Sm%~=?Sbf12n5(27NjM<^N4zNs7g=a#lP#jZT6H^iG z_K2x)K|dI3i+qfpl~eTUPQs%EYGKOT5g|Md zXtxGe=VOz96k=8t5m_e%4B_jlI!r^VY6i$bq0QZ-DKgj$8y8TR%^RoCp!`e+(s=?q zG>zu82YGxe#JL8g#3>1XI5**-gIzx;bHbWKkIkbJWW*UvLo3uc7tN@nM%t_m?NFnI z31B&U%({j; zU12NfWo8u422VkWsF5~uNyo>*f~HMYm5aizstg#gCUzL^;$}zOl0$B&F*lpIQ6M2U zQz*u&Y7!ckMqOkvZ%=(Ioh5x|V|_c&KT=eR^zCT2seJ)rvl&UFI?c@3qWG~#v`D*n zU&2a&Ck#tRFXum!$}w9E;4*~``lC4oMbU82dIwZngWp4hAOxO2Kx@tauIPF=sD=Iy5ED922=Q@2=uk`8 zy?<8XS2=0Nr zcmk9-glK~p+Hr9Di4+Gv5dK4GN~a$nJGqn-vD-ozk9bd5 zLJErHIR!#NgwX5;J$8W*R0Fa>2zjs&4hK**BzF=1XaPBSkDQWbx<^j(5@G=wYou>lBx;c}^XvECRt zAIIOcC;GJQ(TMM)wiJc&F%#Tql>k#tT0|gobj*eJZK6aJIGe@ZOpC{bK*$v5$-wjk z4G1JvvF45o=|8zf3i6LohxF&41D)k3L!In1rHUyPC=o4_VV~(&&w&u?@iS;3mKGCQ z{sSRU|Grq$;<&JeWBQ)O&Ttm_gOZQqNhD3NM0PSg2))1uogmry+&ec+AMlPXH7ZZTW31#4(Sd5gI9l?T7x#Z z?D(&4+snSYfs6;_rlHT_S~z_p&Kv1*-i@V)G18=9I-GHYwj&yQhlX}iX&(xYh_H>@ zW2Fdq6hw?3RR(*a6lq#Q#VOy0M?#wl7d_IZDq$EsK&5S-H?dn8oKX-Mf)1H@^kxKS z6j*JN&O$2oEQXt;gC?ahHXA5nKA4f%f*R<<6EILiV3HXrhE#bNVPP*#5;&E1D5fBM zBjrPS5rxCC<3fWQ_G=Q1R8G*!2t$g)Jrx}Ic^000EDHRR+|-33QB3kPVn~N)3PyZ{ zyV0-@Z5m)A$Wjl*c^fYx5-iG=MFPU<=s{|{NNlY}c~J8b#5%`}Xif^)h}N8j3`fWL zc7k7h;2dBc=@45yMDP-{cS&z}7M%!SIUIno%c&}CF*tN#V{?Flv+ZxIbF|-s|9F=F z-Pf_7f)85$SGY#ub)595{7>M~6*I#@1J4$jEq00EnZX1$*RX%|G2>wr+ppb47v34r zs4|H~GYJ1*&~CQXlic_=&BKG~#R5G&qH_w>T-54ZOQVKIcBBIQ5Kla;X=JdQX0gl~ zcf^WC_`u`Qn@E(g~U)aOiv0A@!@9KVb%kHHDQUE^<#ToZ7hqy`qZ{D~o z{Cx-mqu9^K5BA*XeUg@VRua8Q67icPdb~?o^G~U`bImvu6r9n|E1;L4Rnw857rmLeseM0O>}N>4sW3wP4i~C@nUZ&=)Qp0 z%8h5wpMG(v+YN3EUoel>=R+b~?=JTim*&IvN`Sdm@y0iU@+Qg$Q2r*p0YzM8M)>-pJ2zECI>3#CH2 zP$^UkwL-lxTg(>=#bU8kEEg-qYOz+V7iUZPQlV5Vl}hDOrBp4|O7+rgIbSZ6i{(qe6>(5R!h}#wNkBCYt?#nwwA9IYQ1V-u7Q<%Iw9s6pH}EU%Zs_-6 zoYTFPX1jZ?+X`N8^wzsAXnzA=0JP3^SJ%Vm+Jiy6d+kbdc|ADuGBmPtvls-ep!IBf zr5#2i{Kc@{1E(5d8~x_$%(1Jw*VWCgzKVrk)iCdR!1I7L>x$;S*NoofG#5xK)S;M%#_ka!=gv>~`UyoJ2JG zeG1*jbB!-7cUyb#N-soF1hg^#iMVYKdg4icqo2N*7NaM!ef)Rd7cuA{+|i#ioTE*l zgXg9`vTgjg`}-NwN;I*Y)UxMCHE1WC)8EgkV>4Qa`##T!Iv|Jj13>a!+{bo}$L#$9 zPu#mx-t$GzPRB^ieC4yFH+vZ&26O*2u73p`t&{W->zy$A+YCp&*lPs?{Zg;5!|Q=Y zI78a$qt(Qe6Z%wdWd)!QC<+a9vmZnw!t2dYuQbEO>w10FBpzb0u-;w{kGH$yF^7Q} zs{6reuTNp`ggz5ZLhx_D)Lx9455i_Y)L>gE;WG#<)4? zFZY9H>lI3X<}<8TJbZ}t{g=B<1i)S&A#|tL_%CsrI@cYnzXb8x2%B*hrFaXHXCoO> zjb@878*c6AqP8sg@A+PMiN51v)C&82)VH7dBH1_%47kI-5cThi#$M*^%cJd!QQsu> zooaTwy|59W#K&JmU|&LijAJ65i1c+D-+Db0yuzcYKi19oPEzK+*jM8I)K04AF$cs) z_s7Nzx*ID&*yNZ+gD06oZy3;abtd`)1U{w^$-;?R?L^Vs;5XeL3|dR3`-x)yMCC;O p;n|?LSjrcR3rOyjg<`SXtTpR}a!@EOG%JN#wGadgh4R9J_&=XdQRV;u literal 0 HcmV?d00001 diff --git a/apps/contracts/strategies/external_wasms/blend/pool_factory.wasm b/apps/contracts/strategies/external_wasms/blend/pool_factory.wasm new file mode 100644 index 0000000000000000000000000000000000000000..cc662d3dc8e54ccebbd00aedd32cf753679895ca GIT binary patch literal 2898 zcmZ`*&2QYs6@N42F1gEHX>6ylEZ5GE77*(YWhGgb-Cjhda-bSP9RUG~9=hW0($;>< zB%|6zp%q}k2oRv?Ej<-QFF}E-e}j8#ffnd7x4JzP=%oR2?8W^(en?J(&Vqbz-q*ZO z&Qh3+1rZ6~*%L?NXipyT+dRSoG;$zkGi(TtIHEnGJvjqp(b-;=MOj#WDlUtW*d&Sf z9TH+J?veq#jdv(oIAkPNK@Y_m@QxT}??;gDK%OaUz`KwkaR{vn-nSwD1U4(sU5A}s zX6;F4XDmX4*W|Bb>tW8$`zZT$N1IBHOH0>o!>xL(qll6=Np+QbN%j7upZ3F1|ECdsyV{EmM$@O{TK%MbFrAL*2Ao)`x7)oi4cpPA zX9%a=-jBkAb|*|CL)O1^=B|+@wGfElP8a9C3G)N0ysztojV2PaH3kmm+_clNPn~TSNbqcElr8`1&X7&ZjMm7#MQyb{lJ zC8$0>aVy&J#SkZ&z8JVBWE^np=fT{`yrbzf(9Z+&M2iAZZ#Zuv2j3uHaxPPzi(mi8 z$dO-sYAUhloC;*c;H>B@E1U{-jiX&Q=m7!{{=xvLi@=c(#*nUM!*&gIH7lxLRo4Tl z-r8=8;2F~1QraQMf6m#p)pZy&HVwsg&r_Vc@X0Y!Uig|(T1vu_v3PD*WP2Q~QHwx2 zUkNE^lHF|$J-I|&1%KiFEYS-CZ482}f`)GoT!XVExA><8=QQ{;eaI1=pDq#H*B!Ws z0xla1Uas&L+HImKmJRKhnFS_Dl*t}2^``O|*q?8+1Iva&y(mDOr~xc%Gso0Giwx5h zq@ZDP6ze=Va~HkEc`|q7Oq?Tt;>RXPF`&` zhZuQRQP*@8S$nXJL(D*b^11)&cmFUyzNS*=IehRe1IN~G)6|W?%%UxN#cSj(WGNf%qNS>p zDwxGHUR^n^R1M^>iSjkIfyX=-#4b+_PBKrhYvOTK(h=U{Xm-;|#pV~XmSB2xGy z$?W4MFd;xM!=qm^8}sL(ogM_zC11D}N4JeGMaG86jBu$zn8<86U;IWW&0m})3 zeRky*+M0WdCy3Nl1hnAEK&ZFOBOfCMtb(o)k3Hej`@Tpq^WxrB?BqR+AR%04oK^yI z=HZV-7yMXIeyx18lkDK~cz}E2gD4HpFOvKgd2c#NPpXI45N_ebeF{YkyFkmRa5 zjt-`A+MhgH(H!R4NeLY5KkRqQ6OuHHQw`gz>#f!boGq4Ot$Vq9nfss{1+Td?NuziY zj!FjTqTpTjM{yMPo^pQk%ei+ZRq9{bnH=KY?(q>U=f{r{s8`-7Y%qBJcISO*e~$Ck z=8Cn)C>^t`zv9&>jd4Ml`r0c095AU`&?{kY+@Iu|O9joGgyRUfD)&h^N)h(IvDXEy zIz?xUSc<6ByIA%~I}L|XI}X#F&$Z{(9EVTvrzAl}rW1}7i+LPVX@hBJ|6K|m(;8X4 zVXqfQ39GU^>+vJ;lDvn8avl2&u3V!|IK4rGrNotf~C(^ zF&C^`(rTH%*^n@~$ldh|Wq(GKL#|sk8!V95e0nxGUt?C{d^424@=+1y;gpVDI4 zagy|gIs4tU*2>08>&D$^t-Ib@TkG6f-`MD^t=$SY!#k_DqSf_IxUsr Date: Tue, 3 Dec 2024 17:13:24 -0300 Subject: [PATCH 11/28] fixed typescript scripts for blend strategy --- apps/contracts/src/strategies/deploy_blend.ts | 4 +- apps/contracts/src/tests/blend/test_vault.ts | 2 +- apps/contracts/src/tests/vault.ts | 2 +- .../strategies/blend/src/constants.rs | 2 +- apps/contracts/strategies/blend/src/lib.rs | 5 +- apps/contracts/strategies/blend/src/test.rs | 77 +++++++++---------- .../strategies/blend/src/test/success.rs | 74 +++++++++--------- 7 files changed, 82 insertions(+), 84 deletions(-) diff --git a/apps/contracts/src/strategies/deploy_blend.ts b/apps/contracts/src/strategies/deploy_blend.ts index ba2473ff..73ab8b37 100644 --- a/apps/contracts/src/strategies/deploy_blend.ts +++ b/apps/contracts/src/strategies/deploy_blend.ts @@ -47,7 +47,9 @@ export async function deployBlendStrategy(addressBook: AddressBook) { const initArgs = xdr.ScVal.scvVec([ new Address("CCEVW3EEW4GRUZTZRTAMJAXD6XIF5IG7YQJMEEMKMVVGFPESTRXY2ZAV").toScVal(), //Blend pool on testnet! - nativeToScVal(0, {type: "u32"}) // ReserveId 0 is XLM + nativeToScVal(0, { type: "u32" }), // ReserveId 0 is XLM + new Address("CB22KRA3YZVCNCQI64JQ5WE7UY2VAV7WFLK6A2JN3HEX56T2EDAFO7QF").toScVal(), // BLND Token + new Address("CAG5LRYQ5JVEUI5TEID72EYOVX44TTUJT5BQR2J6J77FH65PCCFAJDDH").toScVal(), // Soroswap router ]); const args: xdr.ScVal[] = [ diff --git a/apps/contracts/src/tests/blend/test_vault.ts b/apps/contracts/src/tests/blend/test_vault.ts index 4be22505..22038029 100644 --- a/apps/contracts/src/tests/blend/test_vault.ts +++ b/apps/contracts/src/tests/blend/test_vault.ts @@ -139,7 +139,7 @@ export async function testBlendVault(user?: Keypair) { console.log(purple, '----------------------- Depositing XLM to the vault -----------------------') console.log(purple, '---------------------------------------------------------------------------') const { user, balanceBefore: depositBalanceBefore, result: depositResult, balanceAfter: depositBalanceAfter } - = await depositToVault(blendVaultAddress, [initialAmount], newUser); + = await depositToVault(blendVaultAddress, [initialAmount], newUser, false); console.log(green, '------------ XLM deposited to the vault ------------') console.log(green, 'Deposit balance before: ', depositBalanceBefore) diff --git a/apps/contracts/src/tests/vault.ts b/apps/contracts/src/tests/vault.ts index 3b99bada..9a536f92 100644 --- a/apps/contracts/src/tests/vault.ts +++ b/apps/contracts/src/tests/vault.ts @@ -42,7 +42,7 @@ export async function depositToVault(deployedVault: string, amount: number[], us const depositParams: xdr.ScVal[] = [ xdr.ScVal.scvVec(amountsDesired.map((amount) => nativeToScVal(amount, { type: "i128" }))), xdr.ScVal.scvVec(amountsMin.map((min) => nativeToScVal(min, { type: "i128" }))), - (new Address(newUser.publicKey())).toScVal(), + new Address(newUser.publicKey()).toScVal(), xdr.ScVal.scvBool(investDeposit) ]; diff --git a/apps/contracts/strategies/blend/src/constants.rs b/apps/contracts/strategies/blend/src/constants.rs index b2417fec..1a61405b 100644 --- a/apps/contracts/strategies/blend/src/constants.rs +++ b/apps/contracts/strategies/blend/src/constants.rs @@ -1,5 +1,5 @@ /// 1 with 7 decimal places -pub const SCALAR_7: i128 = 1_0000000; +// pub const SCALAR_7: i128 = 1_0000000; /// 1 with 9 decimal places pub const SCALAR_9: i128 = 1_000_000_000; /// The minimum amount of tokens than can be deposited or withdrawn from the vault diff --git a/apps/contracts/strategies/blend/src/lib.rs b/apps/contracts/strategies/blend/src/lib.rs index 3edb42fe..38c44058 100644 --- a/apps/contracts/strategies/blend/src/lib.rs +++ b/apps/contracts/strategies/blend/src/lib.rs @@ -2,7 +2,7 @@ use blend_pool::perform_reinvest; use constants::{MIN_DUST, SCALAR_9}; use soroban_sdk::{ - contract, contractimpl, token::TokenClient, vec, Address, Env, IntoVal, String, Val, Vec}; + contract, contractimpl, token::TokenClient, Address, Env, IntoVal, String, Val, Vec}; mod blend_pool; mod constants; @@ -10,7 +10,6 @@ mod reserves; mod soroswap; mod storage; -use soroswap::internal_swap_exact_tokens_for_tokens; use storage::{extend_instance_ttl, is_initialized, set_initialized, Config}; pub use defindex_strategy_core::{ @@ -96,6 +95,7 @@ impl DeFindexStrategyTrait for BlendStrategy { } let config = storage::get_config(&e); + blend_pool::claim(&e, &e.current_contract_address(), &config); perform_reinvest(&e, &config)?; let reserves = storage::get_strategy_reserves(&e); @@ -184,5 +184,4 @@ impl DeFindexStrategyTrait for BlendStrategy { } } -#[cfg(any(test, feature = "testutils"))] mod test; \ No newline at end of file diff --git a/apps/contracts/strategies/blend/src/test.rs b/apps/contracts/strategies/blend/src/test.rs index 041fedaf..9d268443 100644 --- a/apps/contracts/strategies/blend/src/test.rs +++ b/apps/contracts/strategies/blend/src/test.rs @@ -2,10 +2,9 @@ extern crate std; use crate::{ - blend_pool::{self, BlendPoolClient, Request, ReserveConfig, ReserveEmissionMetadata}, constants::SCALAR_7, storage::DAY_IN_LEDGERS, BlendStrategy, BlendStrategyClient + blend_pool::{self, BlendPoolClient, Request, ReserveConfig, ReserveEmissionMetadata}, storage::DAY_IN_LEDGERS, BlendStrategy, BlendStrategyClient }; use sep_41_token::testutils::MockTokenClient; -use soroban_fixed_point_math::FixedPoint; use soroban_sdk::{ testutils::{Address as _, BytesN as _, Ledger as _, LedgerInfo}, token::StellarAssetClient, vec, Address, BytesN, Env, IntoVal, String, Symbol, Val, Vec }; @@ -33,7 +32,7 @@ pub(crate) fn register_blend_strategy(e: &Env) -> Address { pub struct BlendFixture<'a> { pub backstop: blend_backstop::Client<'a>, pub emitter: blend_emitter::Client<'a>, - pub backstop_token: blend_comet::Client<'a>, + pub _backstop_token: blend_comet::Client<'a>, pub pool_factory: blend_factory_pool::Client<'a>, } @@ -177,7 +176,7 @@ pub trait EnvTestUtils { fn jump(&self, ledgers: u32); /// Jump the env by the given amount of seconds. Incremends the sequence by 1. - fn jump_time(&self, seconds: u64); + // fn jump_time(&self, seconds: u64); /// Set the ledger to the default LedgerInfo /// @@ -200,18 +199,18 @@ impl EnvTestUtils for Env { }); } - fn jump_time(&self, seconds: u64) { - self.ledger().set(LedgerInfo { - timestamp: self.ledger().timestamp().saturating_add(seconds), - protocol_version: 21, - sequence_number: self.ledger().sequence().saturating_add(1), - network_id: Default::default(), - base_reserve: 10, - min_temp_entry_ttl: 30 * DAY_IN_LEDGERS, - min_persistent_entry_ttl: 30 * DAY_IN_LEDGERS, - max_entry_ttl: 365 * DAY_IN_LEDGERS, - }); - } + // fn jump_time(&self, seconds: u64) { + // self.ledger().set(LedgerInfo { + // timestamp: self.ledger().timestamp().saturating_add(seconds), + // protocol_version: 21, + // sequence_number: self.ledger().sequence().saturating_add(1), + // network_id: Default::default(), + // base_reserve: 10, + // min_temp_entry_ttl: 30 * DAY_IN_LEDGERS, + // min_persistent_entry_ttl: 30 * DAY_IN_LEDGERS, + // max_entry_ttl: 365 * DAY_IN_LEDGERS, + // }); + // } fn set_default_info(&self) { self.ledger().set(LedgerInfo { @@ -227,32 +226,32 @@ impl EnvTestUtils for Env { } } -pub fn assert_approx_eq_abs(a: i128, b: i128, delta: i128) { - assert!( - a > b - delta && a < b + delta, - "assertion failed: `(left != right)` \ - (left: `{:?}`, right: `{:?}`, epsilon: `{:?}`)", - a, - b, - delta - ); -} +// pub fn assert_approx_eq_abs(a: i128, b: i128, delta: i128) { +// assert!( +// a > b - delta && a < b + delta, +// "assertion failed: `(left != right)` \ +// (left: `{:?}`, right: `{:?}`, epsilon: `{:?}`)", +// a, +// b, +// delta +// ); +// } /// Asset that `b` is within `percentage` of `a` where `percentage` /// is a percentage in decimal form as a fixed-point number with 7 decimal /// places -pub fn assert_approx_eq_rel(a: i128, b: i128, percentage: i128) { - let rel_delta = b.fixed_mul_floor(percentage, SCALAR_7).unwrap(); - - assert!( - a > b - rel_delta && a < b + rel_delta, - "assertion failed: `(left != right)` \ - (left: `{:?}`, right: `{:?}`, epsilon: `{:?}`)", - a, - b, - rel_delta - ); -} +// pub fn assert_approx_eq_rel(a: i128, b: i128, percentage: i128) { +// let rel_delta = b.fixed_mul_floor(percentage, SCALAR_7).unwrap(); + +// assert!( +// a > b - rel_delta && a < b + rel_delta, +// "assertion failed: `(left != right)` \ +// (left: `{:?}`, right: `{:?}`, epsilon: `{:?}`)", +// a, +// b, +// rel_delta +// ); +// } /// Oracle use sep_40_oracle::testutils::{Asset, MockPriceOracleClient, MockPriceOracleWASM}; @@ -344,7 +343,7 @@ impl<'a> BlendFixture<'a> { BlendFixture { backstop: backstop_client, emitter: emitter_client, - backstop_token: comet_client, + _backstop_token: comet_client, pool_factory: pool_factory_client, } } diff --git a/apps/contracts/strategies/blend/src/test/success.rs b/apps/contracts/strategies/blend/src/test/success.rs index 46511ff2..43f7e858 100644 --- a/apps/contracts/strategies/blend/src/test/success.rs +++ b/apps/contracts/strategies/blend/src/test/success.rs @@ -1,14 +1,13 @@ #![cfg(test)] use crate::blend_pool::{BlendPoolClient, Request}; -use crate::constants::{MIN_DUST, SCALAR_7}; +use crate::constants::MIN_DUST; use crate::storage::DAY_IN_LEDGERS; use crate::test::{create_blend_pool, create_blend_strategy, BlendFixture, EnvTestUtils}; use crate::BlendStrategyClient; use defindex_strategy_core::StrategyError; use sep_41_token::testutils::MockTokenClient; -use soroban_fixed_point_math::FixedPoint; use soroban_sdk::testutils::{Address as _, AuthorizedFunction, AuthorizedInvocation}; -use soroban_sdk::{vec, Address, Env, Error, IntoVal, Symbol}; +use soroban_sdk::{vec, Address, Env, IntoVal, Symbol}; use crate::test::std; #[test] @@ -22,12 +21,11 @@ fn success() { let user_2 = Address::generate(&e); let user_3 = Address::generate(&e); let user_4 = Address::generate(&e); - let user_5 = Address::generate(&e); let blnd = e.register_stellar_asset_contract_v2(admin.clone()); let usdc = e.register_stellar_asset_contract_v2(admin.clone()); let xlm = e.register_stellar_asset_contract_v2(admin.clone()); - let blnd_client = MockTokenClient::new(&e, &blnd.address()); + let _blnd_client = MockTokenClient::new(&e, &blnd.address()); let usdc_client = MockTokenClient::new(&e, &usdc.address()); let xlm_client = MockTokenClient::new(&e, &xlm.address()); @@ -43,27 +41,27 @@ fn success() { /* * Deposit into pool - * -> deposit 100 into blend strategy for each user_3 and user_4 - * -> deposit 200 into pool for user_5 + * -> deposit 100 into blend strategy for each user_2 and user_3 + * -> deposit 200 into pool for user_4 * -> admin borrow from pool to return to 50% util rate * -> verify a deposit into an uninitialized vault fails */ let pool_usdc_balace_start = usdc_client.balance(&pool); let starting_balance = 100_0000000; + usdc_client.mint(&user_2, &starting_balance); usdc_client.mint(&user_3, &starting_balance); - usdc_client.mint(&user_4, &starting_balance); - let user_3_balance = usdc_client.balance(&user_3); + let user_3_balance = usdc_client.balance(&user_2); assert_eq!(user_3_balance, starting_balance); - strategy_client.deposit(&starting_balance, &user_3); + strategy_client.deposit(&starting_balance, &user_2); // -> verify deposit auth assert_eq!( e.auths()[0], ( - user_3.clone(), + user_2.clone(), AuthorizedInvocation { function: AuthorizedFunction::Contract(( strategy.clone(), @@ -71,7 +69,7 @@ fn success() { vec![ &e, starting_balance.into_val(&e), - user_3.to_val(), + user_2.to_val(), ] )), sub_invocations: std::vec![AuthorizedInvocation { @@ -80,7 +78,7 @@ fn success() { Symbol::new(&e, "transfer"), vec![ &e, - user_3.to_val(), + user_2.to_val(), strategy.to_val(), starting_balance.into_val(&e) ] @@ -91,13 +89,13 @@ fn success() { ) ); - strategy_client.deposit(&starting_balance, &user_4); + strategy_client.deposit(&starting_balance, &user_3); // verify deposit (pool b_rate still 1 as no time has passed) + assert_eq!(usdc_client.balance(&user_2), 0); assert_eq!(usdc_client.balance(&user_3), 0); - assert_eq!(usdc_client.balance(&user_4), 0); + assert_eq!(strategy_client.balance(&user_2), starting_balance); assert_eq!(strategy_client.balance(&user_3), starting_balance); - assert_eq!(strategy_client.balance(&user_4), starting_balance); assert_eq!( usdc_client.balance(&pool), pool_usdc_balace_start + starting_balance * 2 @@ -105,13 +103,13 @@ fn success() { let vault_positions = pool_client.get_positions(&strategy); assert_eq!(vault_positions.supply.get(0).unwrap(), starting_balance * 2); - // user_5 deposit directly into pool + // user_4 deposit directly into pool let merry_starting_balance = 200_0000000; - usdc_client.mint(&user_5, &merry_starting_balance); + usdc_client.mint(&user_4, &merry_starting_balance); pool_client.submit( - &user_5, - &user_5, - &user_5, + &user_4, + &user_4, + &user_4, &vec![ &e, Request { @@ -145,18 +143,18 @@ fn success() { /* * Withdraw from pool - * -> withdraw all funds from pool for user_5 - * -> withdraw (excluding dust) from blend strategy for user_3 and user_4 + * -> withdraw all funds from pool for user_4 + * -> withdraw (excluding dust) from blend strategy for user_2 and user_3 * -> verify a withdraw from an uninitialized vault fails * -> verify a withdraw from an empty vault fails * -> verify an over withdraw fails */ - // withdraw all funds from pool for user_5 + // withdraw all funds from pool for user_4 pool_client.submit( - &user_5, - &user_5, - &user_5, + &user_4, + &user_4, + &user_4, &vec![ &e, Request { @@ -166,25 +164,25 @@ fn success() { }, ], ); - let user_5_final_balance = usdc_client.balance(&user_5); + let user_5_final_balance = usdc_client.balance(&user_4); let user_5_profit = user_5_final_balance - merry_starting_balance; - // withdraw from blend strategy for user_3 and user_4 - // they are expected to receive half of the profit of user_5 + // withdraw from blend strategy for user_2 and user_3 + // they are expected to receive half of the profit of user_4 let expected_user_4_profit = user_5_profit / 2; let withdraw_amount = starting_balance + expected_user_4_profit; // withdraw_amount = 100_0958904 // -> verify over withdraw fails - let result = strategy_client.try_withdraw(&(withdraw_amount + 100_000_000_0000000), &user_4); + let result = strategy_client.try_withdraw(&(withdraw_amount + 100_000_000_0000000), &user_3); assert_eq!(result, Err(Ok(StrategyError::InvalidArgument))); // TODO: Check which is the one failing - strategy_client.withdraw(&withdraw_amount, &user_3); + strategy_client.withdraw(&withdraw_amount, &user_2); // -> verify withdraw auth assert_eq!( e.auths()[0], ( - user_3.clone(), + user_2.clone(), AuthorizedInvocation { function: AuthorizedFunction::Contract(( strategy.clone(), @@ -192,7 +190,7 @@ fn success() { vec![ &e, withdraw_amount.into_val(&e), - user_3.to_val(), + user_2.to_val(), ] )), sub_invocations: std::vec![] @@ -200,16 +198,16 @@ fn success() { ) ); - strategy_client.withdraw(&withdraw_amount, &user_4); + strategy_client.withdraw(&withdraw_amount, &user_3); // -> verify withdraw + assert_eq!(usdc_client.balance(&user_2), withdraw_amount); assert_eq!(usdc_client.balance(&user_3), withdraw_amount); - assert_eq!(usdc_client.balance(&user_4), withdraw_amount); + assert_eq!(strategy_client.balance(&user_2), 0); assert_eq!(strategy_client.balance(&user_3), 0); - assert_eq!(strategy_client.balance(&user_4), 0); // -> verify withdraw from empty vault fails - let result = strategy_client.try_withdraw(&MIN_DUST, &user_4); + let result = strategy_client.try_withdraw(&MIN_DUST, &user_3); assert_eq!(result, Err(Ok(StrategyError::InsufficientBalance))); // TODO: Finish harvest testings, pending soroswap router setup with a blend token pair with the underlying asset From f3a2b1eaa8ce8d7ab15a55903617ef253fa59cff Mon Sep 17 00:00:00 2001 From: esteblock Date: Wed, 4 Dec 2024 10:30:34 -0300 Subject: [PATCH 12/28] fix merge double code --- apps/contracts/vault/src/lib.rs | 82 +-------------------------------- 1 file changed, 1 insertion(+), 81 deletions(-) diff --git a/apps/contracts/vault/src/lib.rs b/apps/contracts/vault/src/lib.rs index 103b8dcf..28d92320 100755 --- a/apps/contracts/vault/src/lib.rs +++ b/apps/contracts/vault/src/lib.rs @@ -1,6 +1,6 @@ #![no_std] use deposit::{generate_and_execute_investments, process_deposit}; -use soroban_sdk::{ +use soroban_sdk::{vec, contract, contractimpl, panic_with_error, token::{TokenClient, TokenInterface}, Address, Env, Map, String, Vec, @@ -211,86 +211,6 @@ impl VaultTrait for DeFindexVault { collect_fees(&e)?; let assets = get_assets(&e); - let assets_length = assets.len(); - - // assets lenght should be equal to amounts_desired and amounts_min length - if assets_length != amounts_desired.len() || assets_length != amounts_min.len() { - panic_with_error!(&e, ContractError::WrongAmountsLength); - } - - // for every amount desired, check non negative - for amount in amounts_desired.iter() { - check_nonnegative_amount(amount)?; - } - // for amount min is not necesary to check if it is negative - - let total_supply = VaultToken::total_supply(e.clone()); - let (amounts, shares_to_mint) = if assets_length == 1 { - let shares = if total_supply == 0 { - // If we have only one asset, and this is the first deposit, we will mint a share proportional to the amount desired - // TODO In this case we might also want to mint a MINIMUM LIQUIDITY to be locked forever in the contract - // this might be for security and practical reasons as well - // shares will be equal to the amount desired to deposit, just for simplicity - amounts_desired.get(0).unwrap() // here we have already check same lenght - } else { - // If we have only one asset, but we already have some shares minted - // we will mint a share proportional to the total managed funds - // read whitepaper! - let total_managed_funds = fetch_total_managed_funds(&e); - // if checked mul gives error, return ArithmeticError - VaultToken::total_supply(e.clone()).checked_mul(amounts_desired.get(0) - .unwrap()).unwrap_or_else(|| panic_with_error!(&e, ContractError::ArithmeticError)) - .checked_div( - total_managed_funds.get(assets.get(0).unwrap().address.clone()) - .unwrap().total_amount - ).unwrap_or_else(|| panic_with_error!(&e, ContractError::ArithmeticError)) - }; - // TODO check that min amount is ok - (amounts_desired.clone(), shares) - } else { - if total_supply == 0 { - // for ths first supply, we will consider the amounts desired, and the shares to mint will just be the sum - // of the amounts desired - (amounts_desired.clone(), amounts_desired.iter().sum()) - } - else { - // If Total Assets > 1 - calculate_deposit_amounts_and_shares_to_mint( - &e, - &assets, - &amounts_desired, - &amounts_min, - )? - } - }; - - // for every asset - for (i, amount) in amounts.iter().enumerate() { - // if amount is less than minimum, return error InsufficientAmount - if amount < amounts_min.get(i as u32).unwrap() { - panic_with_error!(&e, ContractError::InsufficientAmount); - } - // its possible that some amounts are 0. - if amount > 0 { - let asset = assets.get(i as u32).unwrap(); - let asset_client = TokenClient::new(&e, &asset.address); - // send the current amount to this contract. This will be held as idle funds. - asset_client.transfer(&from, &e.current_contract_address(), &amount); - } - } - - // Now we mint the corresponding dfToken shares to the user - // If total_sypply==0, mint minimum liquidity to be locked forever in the contract. So we will never come again to total_supply==0 - if total_supply == 0 { - if shares_to_mint < MINIMUM_LIQUIDITY { - panic_with_error!(&e, ContractError::InsufficientAmount); - } - internal_mint(e.clone(), e.current_contract_address(), MINIMUM_LIQUIDITY); - internal_mint(e.clone(), from.clone(), shares_to_mint.checked_sub(MINIMUM_LIQUIDITY).unwrap()); - } - else { - internal_mint(e.clone(), from.clone(), shares_to_mint); - } let (amounts, shares_to_mint) = process_deposit(&e, &assets, &amounts_desired, &amounts_min, &from)?; From f4fe902f62dc426e3468c4a6c17f2836e14fec7d Mon Sep 17 00:00:00 2001 From: esteblock Date: Wed, 4 Dec 2024 10:30:54 -0300 Subject: [PATCH 13/28] refactor deposit tests --- apps/contracts/vault/src/test/deposit.rs | 104 +++++++++++++---------- 1 file changed, 57 insertions(+), 47 deletions(-) diff --git a/apps/contracts/vault/src/test/deposit.rs b/apps/contracts/vault/src/test/deposit.rs index c7c0b810..ce52b02d 100644 --- a/apps/contracts/vault/src/test/deposit.rs +++ b/apps/contracts/vault/src/test/deposit.rs @@ -298,21 +298,20 @@ fn deposit_one_asset_success() { // check balances after deposit let df_balance = test.defindex_contract.balance(&users[0]); assert_eq!(df_balance, amount - 1000); - + let user_balance = test.token0.balance(&users[0]); assert_eq!(user_balance, 0i128); - //map shuould be map - let mut expected_map = Map::new(&test.env); - expected_map.set(test.token0.address.clone(), amount); + // check that all the assets are in the vault + let vault_balance = test.token0.balance(&test.defindex_contract.address); + assert_eq!(vault_balance, amount); + + // check total manage funds // fn fetch_total_managed_funds(e: &Env) -> Map { // extend_instance_ttl(&e); // fetch_total_managed_funds(e) // } - // Current Asset Investment Allocation - // #[contracttype] - // #[derive(Clone, Debug, Eq, PartialEq)] // pub struct CurrentAssetInvestmentAllocation { // pub asset: Address, // pub total_amount: i128, @@ -320,18 +319,16 @@ fn deposit_one_asset_success() { // pub invested_amount: i128, // pub strategy_investments: Vec, // } - // #[contracttype] - // #[derive(Clone, Debug, Eq, PartialEq)] // pub struct StrategyInvestment { // pub strategy: Address, // pub amount: i128, // } - // construct expected total managed funds maa + // construct expected total manage funds let mut total_managed_funds_expected = Map::new(&test.env); let strategy_investments_expected = sorobanvec![&test.env, StrategyInvestment { strategy: test.strategy_client_token0.address.clone(), - amount: amount, + amount: 0, //funds has not been invested yet! }]; total_managed_funds_expected.set(test.token0.address.clone(), CurrentAssetInvestmentAllocation { @@ -343,18 +340,18 @@ fn deposit_one_asset_success() { } ); - - // check that all the assets are in the vault - let vault_balance = test.token0.balance(&test.defindex_contract.address); - assert_eq!(vault_balance, amount); + // check that fetch_total_managed_funds returns correct amount let total_managed_funds = test.defindex_contract.fetch_total_managed_funds(); assert_eq!(total_managed_funds, total_managed_funds_expected); // check current idle funds, + let mut expected_idle_funds_map = Map::new(&test.env); + expected_idle_funds_map.set(test.token0.address.clone(), amount); + let current_idle_funds = test.defindex_contract.fetch_current_idle_funds(); - assert_eq!(current_idle_funds, expected_map); + assert_eq!(current_idle_funds, expected_idle_funds_map); //map shuould be map let mut expected_map = Map::new(&test.env); @@ -397,7 +394,7 @@ fn deposit_one_asset_success() { let mut total_managed_funds_expected = Map::new(&test.env); let strategy_investments_expected = sorobanvec![&test.env, StrategyInvestment { strategy: test.strategy_client_token0.address.clone(), - amount: amount + amount2, + amount: 0, // funds have not been invested yet! }]; total_managed_funds_expected.set(test.token0.address.clone(), CurrentAssetInvestmentAllocation { @@ -559,36 +556,43 @@ fn deposit_several_assets_success() { let vault_balance1 = test.token1.balance(&test.defindex_contract.address); assert_eq!(vault_balance1, amount1); - //map shuould be map - let mut expected_map = Map::new(&test.env); - expected_map.set(test.token0.address.clone(), amount0); - expected_map.set(test.token1.address.clone(), amount1); - - // check that fetch_total_managed_funds returns correct amount + // check total managed funds let mut total_managed_funds_expected = Map::new(&test.env); - let mut strategy_investments_expected = sorobanvec![&test.env, StrategyInvestment { + let mut strategy_investments_expected_token_0 = sorobanvec![&test.env, StrategyInvestment { strategy: test.strategy_client_token0.address.clone(), - amount: amount0, + amount: 0, // funds have not been invested yet! }]; - strategy_investments_expected.push_back(StrategyInvestment { + let mut strategy_investments_expected_token_1 = sorobanvec![&test.env, StrategyInvestment { strategy: test.strategy_client_token1.address.clone(), - amount: amount1, - }); + amount: 0, // funds have not been invested yet! + }]; total_managed_funds_expected.set(test.token0.address.clone(), CurrentAssetInvestmentAllocation { asset: test.token0.address.clone(), total_amount: amount0, idle_amount: amount0, invested_amount: 0i128, - strategy_investments: sorobanvec![&test.env, StrategyInvestment { - strategy: test.strategy_client_token0.address.clone(), - amount: amount0, - }], + strategy_investments: strategy_investments_expected_token_0, + } + ); + total_managed_funds_expected.set(test.token1.address.clone(), + CurrentAssetInvestmentAllocation { + asset: test.token1.address.clone(), + total_amount: amount1, + idle_amount: amount1, + invested_amount: 0i128, + strategy_investments: strategy_investments_expected_token_1, } ); let total_managed_funds = test.defindex_contract.fetch_total_managed_funds(); assert_eq!(total_managed_funds, total_managed_funds_expected); + //map shuould be map + let mut expected_map = Map::new(&test.env); + expected_map.set(test.token0.address.clone(), amount0); + expected_map.set(test.token1.address.clone(), amount1); + + // check current idle funds let current_idle_funds = test.defindex_contract.fetch_current_idle_funds(); assert_eq!(current_idle_funds, expected_map); @@ -650,36 +654,42 @@ fn deposit_several_assets_success() { let vault_balance1 = test.token1.balance(&test.defindex_contract.address); assert_eq!(vault_balance1, 3*amount1); - //map shuould be map - let mut expected_map = Map::new(&test.env); - expected_map.set(test.token0.address.clone(), 3*amount0); - expected_map.set(test.token1.address.clone(), 3*amount1); - - // check that fetch_total_managed_funds returns correct amount + + // check total managed funds let mut total_managed_funds_expected = Map::new(&test.env); - let mut strategy_investments_expected = sorobanvec![&test.env, StrategyInvestment { + let mut strategy_investments_expected_token_0 = sorobanvec![&test.env, StrategyInvestment { strategy: test.strategy_client_token0.address.clone(), - amount: 3*amount0, + amount: 0, // funds have not been invested yet! }]; - strategy_investments_expected.push_back(StrategyInvestment { + let mut strategy_investments_expected_token_1 = sorobanvec![&test.env, StrategyInvestment { strategy: test.strategy_client_token1.address.clone(), - amount: 3*amount1, - }); + amount: 0, // funds have not been invested yet! + }]; total_managed_funds_expected.set(test.token0.address.clone(), CurrentAssetInvestmentAllocation { asset: test.token0.address.clone(), total_amount: 3*amount0, idle_amount: 3*amount0, invested_amount: 0i128, - strategy_investments: sorobanvec![&test.env, StrategyInvestment { - strategy: test.strategy_client_token0.address.clone(), - amount: 3*amount0, - }], + strategy_investments: strategy_investments_expected_token_0, + } + ); + total_managed_funds_expected.set(test.token1.address.clone(), + CurrentAssetInvestmentAllocation { + asset: test.token1.address.clone(), + total_amount: 3*amount1, + idle_amount: 3*amount1, + invested_amount: 0i128, + strategy_investments: strategy_investments_expected_token_1, } ); let total_managed_funds = test.defindex_contract.fetch_total_managed_funds(); assert_eq!(total_managed_funds, total_managed_funds_expected); + //map shuould be map + let mut expected_map = Map::new(&test.env); + expected_map.set(test.token0.address.clone(), 3*amount0); + expected_map.set(test.token1.address.clone(), 3*amount1); // check current idle funds let current_idle_funds = test.defindex_contract.fetch_current_idle_funds(); assert_eq!(current_idle_funds, expected_map); From c97ce4f18f5400160f028a785c175a624e993a32 Mon Sep 17 00:00:00 2001 From: esteblock Date: Wed, 4 Dec 2024 10:35:22 -0300 Subject: [PATCH 14/28] fix warnings --- apps/contracts/vault/src/lib.rs | 6 +++--- apps/contracts/vault/src/test/deposit.rs | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/apps/contracts/vault/src/lib.rs b/apps/contracts/vault/src/lib.rs index 28d92320..5706caea 100755 --- a/apps/contracts/vault/src/lib.rs +++ b/apps/contracts/vault/src/lib.rs @@ -1,6 +1,6 @@ #![no_std] use deposit::{generate_and_execute_investments, process_deposit}; -use soroban_sdk::{vec, +use soroban_sdk::{ contract, contractimpl, panic_with_error, token::{TokenClient, TokenInterface}, Address, Env, Map, String, Vec, @@ -44,9 +44,9 @@ use strategies::{ get_strategy_struct, invest_in_strategy, pause_strategy, unpause_strategy, withdraw_from_strategy, }; -use token::{internal_mint, internal_burn, write_metadata, VaultToken}; +use token::{internal_burn, write_metadata, VaultToken}; use utils::{ - calculate_asset_amounts_per_vault_shares, calculate_deposit_amounts_and_shares_to_mint, + calculate_asset_amounts_per_vault_shares, calculate_withdrawal_amounts, check_initialized, check_nonnegative_amount, }; diff --git a/apps/contracts/vault/src/test/deposit.rs b/apps/contracts/vault/src/test/deposit.rs index ce52b02d..f25a70df 100644 --- a/apps/contracts/vault/src/test/deposit.rs +++ b/apps/contracts/vault/src/test/deposit.rs @@ -558,11 +558,11 @@ fn deposit_several_assets_success() { // check total managed funds let mut total_managed_funds_expected = Map::new(&test.env); - let mut strategy_investments_expected_token_0 = sorobanvec![&test.env, StrategyInvestment { + let strategy_investments_expected_token_0 = sorobanvec![&test.env, StrategyInvestment { strategy: test.strategy_client_token0.address.clone(), amount: 0, // funds have not been invested yet! }]; - let mut strategy_investments_expected_token_1 = sorobanvec![&test.env, StrategyInvestment { + let strategy_investments_expected_token_1 = sorobanvec![&test.env, StrategyInvestment { strategy: test.strategy_client_token1.address.clone(), amount: 0, // funds have not been invested yet! }]; @@ -657,11 +657,11 @@ fn deposit_several_assets_success() { // check total managed funds let mut total_managed_funds_expected = Map::new(&test.env); - let mut strategy_investments_expected_token_0 = sorobanvec![&test.env, StrategyInvestment { + let strategy_investments_expected_token_0 = sorobanvec![&test.env, StrategyInvestment { strategy: test.strategy_client_token0.address.clone(), amount: 0, // funds have not been invested yet! }]; - let mut strategy_investments_expected_token_1 = sorobanvec![&test.env, StrategyInvestment { + let strategy_investments_expected_token_1 = sorobanvec![&test.env, StrategyInvestment { strategy: test.strategy_client_token1.address.clone(), amount: 0, // funds have not been invested yet! }]; From 4942064af33e21b979863008f11d437f3fda1d39 Mon Sep 17 00:00:00 2001 From: esteblock Date: Wed, 4 Dec 2024 11:02:00 -0300 Subject: [PATCH 15/28] refactor invest tests --- apps/contracts/vault/src/test/invest.rs | 107 ++++++++++++++---------- 1 file changed, 61 insertions(+), 46 deletions(-) diff --git a/apps/contracts/vault/src/test/invest.rs b/apps/contracts/vault/src/test/invest.rs index 415ac19a..a3738965 100644 --- a/apps/contracts/vault/src/test/invest.rs +++ b/apps/contracts/vault/src/test/invest.rs @@ -5,6 +5,7 @@ use soroban_sdk::{ }; use crate::test::defindex_vault::{ + CurrentAssetInvestmentAllocation, AssetStrategySet, AssetInvestmentAllocation, StrategyInvestment, @@ -459,59 +460,50 @@ fn test_invest_in_strategy() { let vault_balance_1 = test.token1.balance(&test.defindex_contract.address); assert_eq!(vault_balance_0, amount_0); assert_eq!(vault_balance_1, amount_1); - - // EXAMPLE - // // check that fetch_total_managed_funds returns correct amount - // let total_managed_funds_expected = Map::new(&test.env); - // let mut strategy_investments_expected = sorobanvec![&test.env, StrategyInvestment { - // strategy: test.strategy_client_token0.address.clone(), - // amount: 3*amount0, - // }]; - // strategy_investments_expected.push_back(StrategyInvestment { - // strategy: test.strategy_client_token1.address.clone(), - // amount: 3*amount1, - // }); - // total_managed_funds_expected.set(test.token0.address.clone(), - // CurrentAssetInvestmentAllocation { - // asset: test.token0.address.clone(), - // total_amount: 3*amount0, - // idle_amount: 3*amount0, - // invested_amount: 0i128, - // strategy_investments: sorobanvec![&test.env, StrategyInvestment { - // strategy: test.strategy_client_token0.address.clone(), - // amount: 3*amount0, - // }], - // } - // ); - // let total_managed_funds = test.defindex_contract.fetch_total_managed_funds(); - // assert_eq!(total_managed_funds, total_managed_funds_expected); - - + + let mut total_managed_funds_expected = Map::new(&test.env); - total_managed_funds_expected.set(test.token0.address.clone(), amount_0); - total_managed_funds_expected.set(test.token1.address.clone(), amount_1); - + let strategy_investments_expected_token_0 = sorobanvec![&test.env, StrategyInvestment { + strategy: test.strategy_client_token0.address.clone(), + amount: 0, // funds have not been invested yet! + }]; + let strategy_investments_expected_token_1 = sorobanvec![&test.env, StrategyInvestment { + strategy: test.strategy_client_token1.address.clone(), + amount: 0, // funds have not been invested yet! + }]; + total_managed_funds_expected.set(test.token0.address.clone(), + CurrentAssetInvestmentAllocation { + asset: test.token0.address.clone(), + total_amount: amount_0, + idle_amount: amount_0, + invested_amount: 0i128, + strategy_investments: strategy_investments_expected_token_0, + }); + total_managed_funds_expected.set(test.token1.address.clone(), + CurrentAssetInvestmentAllocation { + asset: test.token1.address.clone(), + total_amount: amount_1, + idle_amount: amount_1, + invested_amount: 0i128, + strategy_investments: strategy_investments_expected_token_1, + }); - - - let total_managed_funds = test.defindex_contract.fetch_total_managed_funds(); - let mut expected_map = Map::new(&test.env); + assert_eq!(total_managed_funds, total_managed_funds_expected); + + + // check current idle funds, + let mut expected_map = Map::new(&test.env); expected_map.set(test.token0.address.clone(), amount_0); expected_map.set(test.token1.address.clone(), amount_1); - assert_eq!(total_managed_funds, expected_map); - - // check current idle funds, let current_idle_funds = test.defindex_contract.fetch_current_idle_funds(); assert_eq!(current_idle_funds, expected_map); - //map shuould be map + // check that current invested funds is now 0, funds still in idle funds let mut expected_map = Map::new(&test.env); expected_map.set(test.token0.address.clone(), 0i128); expected_map.set(test.token1.address.clone(), 0i128); - - // check that current invested funds is now 0, funds still in idle funds let current_invested_funds = test.defindex_contract.fetch_current_invested_funds(); assert_eq!(current_invested_funds, expected_map); @@ -550,12 +542,35 @@ fn test_invest_in_strategy() { assert_eq!(vault_balance_0, amount_0 - 100); assert_eq!(vault_balance_1, amount_1 - 200); - // check that fetch_total_managed_funds returns correct amount + // check total managed funds + let mut total_managed_funds_expected = Map::new(&test.env); + let strategy_investments_expected_token_0 = sorobanvec![&test.env, StrategyInvestment { + strategy: test.strategy_client_token0.address.clone(), + amount: 100, + }]; + let strategy_investments_expected_token_1 = sorobanvec![&test.env, StrategyInvestment { + strategy: test.strategy_client_token1.address.clone(), + amount: 200, + }]; + total_managed_funds_expected.set(test.token0.address.clone(), + CurrentAssetInvestmentAllocation { + asset: test.token0.address.clone(), + total_amount: amount_0, + idle_amount: amount_0 - 100, + invested_amount: 100i128, + strategy_investments: strategy_investments_expected_token_0, + }); + total_managed_funds_expected.set(test.token1.address.clone(), + CurrentAssetInvestmentAllocation { + asset: test.token1.address.clone(), + total_amount: amount_1, + idle_amount: amount_1 - 200, + invested_amount: 200i128, + strategy_investments: strategy_investments_expected_token_1, + }); + let total_managed_funds = test.defindex_contract.fetch_total_managed_funds(); - let mut expected_map = Map::new(&test.env); - expected_map.set(test.token0.address.clone(), amount_0); - expected_map.set(test.token1.address.clone(), amount_1); - assert_eq!(total_managed_funds, expected_map); + assert_eq!(total_managed_funds, total_managed_funds_expected); // check current idle funds, for token0 should be amount 0 - 100 let mut expected_map = Map::new(&test.env); From b02f62275076d8e2432e1f07c2e4843233950ed6 Mon Sep 17 00:00:00 2001 From: esteblock Date: Wed, 4 Dec 2024 11:22:22 -0300 Subject: [PATCH 16/28] include all tests again --- apps/contracts/vault/src/test.rs | 12 +- .../vault/src/test/deposit_and_invest.rs | 178 +++++++++++++----- .../src/test/get_asset_amounts_per_shares.rs | 9 +- 3 files changed, 146 insertions(+), 53 deletions(-) diff --git a/apps/contracts/vault/src/test.rs b/apps/contracts/vault/src/test.rs index c5f986d5..bbca09eb 100755 --- a/apps/contracts/vault/src/test.rs +++ b/apps/contracts/vault/src/test.rs @@ -170,10 +170,10 @@ impl<'a> DeFindexVaultTest<'a> { mod initialize; mod deposit; mod admin; -// mod withdraw; -// mod emergency_withdraw; +mod withdraw; +mod emergency_withdraw; mod rebalance; -// mod fees; -// mod get_asset_amounts_per_shares; -// mod invest; -// mod deposit_and_invest; +mod fees; +mod get_asset_amounts_per_shares; +mod invest; +mod deposit_and_invest; diff --git a/apps/contracts/vault/src/test/deposit_and_invest.rs b/apps/contracts/vault/src/test/deposit_and_invest.rs index a85ff29b..a968f011 100644 --- a/apps/contracts/vault/src/test/deposit_and_invest.rs +++ b/apps/contracts/vault/src/test/deposit_and_invest.rs @@ -1,6 +1,6 @@ use soroban_sdk::{vec as sorobanvec, String, Vec, Map}; -use crate::test::defindex_vault::{AssetStrategySet}; +use crate::test::defindex_vault::{AssetStrategySet, StrategyInvestment, CurrentAssetInvestmentAllocation}; use crate::test::{ create_strategy_params_token0, create_strategy_params_token1, DeFindexVaultTest, }; @@ -44,7 +44,7 @@ fn deposit_and_invest_one_asset_success() { let df_balance = test.defindex_contract.balance(&users[0]); assert_eq!(df_balance, 0i128); - // deposit + // deposit AND INVEST test.defindex_contract.deposit( &sorobanvec![&test.env, amount], &sorobanvec![&test.env, amount], @@ -59,26 +59,41 @@ fn deposit_and_invest_one_asset_success() { let user_balance = test.token0.balance(&users[0]); assert_eq!(user_balance, 0i128); - //map shuould be map - let mut expected_invested_map = Map::new(&test.env); - expected_invested_map.set(test.token0.address.clone(), amount); - - let mut expected_idle_map = Map::new(&test.env); - expected_idle_map.set(test.token0.address.clone(), 0); - - // check that all the assets are invested let vault_balance = test.token0.balance(&test.defindex_contract.address); assert_eq!(vault_balance, 0); - // check that fetch_total_managed_funds returns correct amount + // check total managed funds + let mut total_managed_funds_expected = Map::new(&test.env); + let strategy_investments_expected_token_0 = sorobanvec![&test.env, StrategyInvestment { + strategy: test.strategy_client_token0.address.clone(), + amount: amount, // everything has been invested + }]; + + total_managed_funds_expected.set(test.token0.address.clone(), + CurrentAssetInvestmentAllocation { + asset: test.token0.address.clone(), + total_amount: amount, + idle_amount: 0, + invested_amount: amount, + strategy_investments: strategy_investments_expected_token_0, + }); + let total_managed_funds = test.defindex_contract.fetch_total_managed_funds(); - assert_eq!(total_managed_funds, expected_invested_map); + assert_eq!(total_managed_funds, total_managed_funds_expected); + + + // check current idle funds, + let mut expected_idle_map = Map::new(&test.env); + expected_idle_map.set(test.token0.address.clone(), 0); let current_idle_funds = test.defindex_contract.fetch_current_idle_funds(); assert_eq!(current_idle_funds, expected_idle_map); - + // check that current invested funds is now 0, funds still in idle funds + //map shuould be map + let mut expected_invested_map = Map::new(&test.env); + expected_invested_map.set(test.token0.address.clone(), amount); let current_invested_funds = test.defindex_contract.fetch_current_invested_funds(); assert_eq!(current_invested_funds, expected_invested_map); @@ -88,7 +103,7 @@ fn deposit_and_invest_one_asset_success() { let user_balance = test.token0.balance(&users[0]); assert_eq!(user_balance, amount2); - // deposit + // deposit AND INVEST test.defindex_contract.deposit( &sorobanvec![&test.env, amount2], &sorobanvec![&test.env, amount2], @@ -96,17 +111,11 @@ fn deposit_and_invest_one_asset_success() { &true, ); - //map shuould be map - let mut expected_invested_map = Map::new(&test.env); - expected_invested_map.set(test.token0.address.clone(), amount + amount2); - - let mut expected_idle_map = Map::new(&test.env); - expected_idle_map.set(test.token0.address.clone(), 0); - + // check balances after deposit let df_balance = test.defindex_contract.balance(&users[0]); assert_eq!(df_balance, amount + amount2 - 1000); - + let user_balance = test.token0.balance(&users[0]); assert_eq!(user_balance, 0i128); @@ -115,14 +124,33 @@ fn deposit_and_invest_one_asset_success() { assert_eq!(vault_balance, 0); // check that fetch_total_managed_funds returns correct amount + let mut total_managed_funds_expected = Map::new(&test.env); + let strategy_investments_expected_token_0 = sorobanvec![&test.env, StrategyInvestment { + strategy: test.strategy_client_token0.address.clone(), + amount: amount + amount2, // everything has been invested + }]; + + total_managed_funds_expected.set(test.token0.address.clone(), + CurrentAssetInvestmentAllocation { + asset: test.token0.address.clone(), + total_amount: amount + amount2, + idle_amount: 0, + invested_amount: amount + amount2, + strategy_investments: strategy_investments_expected_token_0, + }); + let total_managed_funds = test.defindex_contract.fetch_total_managed_funds(); - assert_eq!(total_managed_funds, expected_invested_map); + assert_eq!(total_managed_funds, total_managed_funds_expected); // check current idle funds + let mut expected_idle_map = Map::new(&test.env); + expected_idle_map.set(test.token0.address.clone(), 0); let current_idle_funds = test.defindex_contract.fetch_current_idle_funds(); assert_eq!(current_idle_funds, expected_idle_map); // check that current invested funds is now 0, funds still in idle funds + let mut expected_invested_map = Map::new(&test.env); + expected_invested_map.set(test.token0.address.clone(), amount + amount2); let current_invested_funds = test.defindex_contract.fetch_current_invested_funds(); assert_eq!(current_invested_funds, expected_invested_map); } @@ -207,24 +235,47 @@ fn deposit_and_invest_several_assets_success() { let vault_balance1 = test.token1.balance(&test.defindex_contract.address); assert_eq!(vault_balance1, 0); - //map shuould be map - let mut expected_invested_map = Map::new(&test.env); - expected_invested_map.set(test.token0.address.clone(), amount0); - expected_invested_map.set(test.token1.address.clone(), amount1); + // check that fetch_total_managed_funds returns correct amount + let mut total_managed_funds_expected = Map::new(&test.env); + let strategy_investments_expected_token_0 = sorobanvec![&test.env, StrategyInvestment { + strategy: test.strategy_client_token0.address.clone(), + amount: amount0, // everything has been invested + }]; + let strategy_investments_expected_token_1 = sorobanvec![&test.env, StrategyInvestment { + strategy: test.strategy_client_token1.address.clone(), + amount: amount1, // everything has been invested + }]; + total_managed_funds_expected.set(test.token0.address.clone(), + CurrentAssetInvestmentAllocation { + asset: test.token0.address.clone(), + total_amount: amount0, + idle_amount: 0, + invested_amount: amount0, + strategy_investments: strategy_investments_expected_token_0, + }); + total_managed_funds_expected.set(test.token1.address.clone(), + CurrentAssetInvestmentAllocation { + asset: test.token1.address.clone(), + total_amount: amount1, + idle_amount: 0, + invested_amount: amount1, + strategy_investments: strategy_investments_expected_token_1, + }); + let total_managed_funds = test.defindex_contract.fetch_total_managed_funds(); + assert_eq!(total_managed_funds, total_managed_funds_expected); + + // check current idle funds let mut expected_idle_map = Map::new(&test.env); expected_idle_map.set(test.token0.address.clone(), 0); expected_idle_map.set(test.token1.address.clone(), 0); - - // check that fetch_total_managed_funds returns correct amount - let total_managed_funds = test.defindex_contract.fetch_total_managed_funds(); - assert_eq!(total_managed_funds, expected_invested_map); - - // check current idle funds let current_idle_funds = test.defindex_contract.fetch_current_idle_funds(); assert_eq!(current_idle_funds, expected_idle_map); // check that current invested funds is now correct, funds should be invested + let mut expected_invested_map = Map::new(&test.env); + expected_invested_map.set(test.token0.address.clone(), amount0); + expected_invested_map.set(test.token1.address.clone(), amount1); let current_invested_funds = test.defindex_contract.fetch_current_invested_funds(); assert_eq!(current_invested_funds, expected_invested_map); @@ -275,24 +326,47 @@ fn deposit_and_invest_several_assets_success() { let vault_balance1 = test.token1.balance(&test.defindex_contract.address); assert_eq!(vault_balance1, 0); - //map shuould be map - let mut expected_invested_map = Map::new(&test.env); - expected_invested_map.set(test.token0.address.clone(), 3*amount0); - expected_invested_map.set(test.token1.address.clone(), 3*amount1); - - let mut expected_idle_map = Map::new(&test.env); - expected_idle_map.set(test.token0.address.clone(), 0); - expected_idle_map.set(test.token1.address.clone(), 0); - + // check that fetch_total_managed_funds returns correct amount + let mut total_managed_funds_expected = Map::new(&test.env); + let strategy_investments_expected_token_0 = sorobanvec![&test.env, StrategyInvestment { + strategy: test.strategy_client_token0.address.clone(), + amount: amount0*3, // everything has been invested + }]; + let strategy_investments_expected_token_1 = sorobanvec![&test.env, StrategyInvestment { + strategy: test.strategy_client_token1.address.clone(), + amount: amount1*3, // everything has been invested + }]; + total_managed_funds_expected.set(test.token0.address.clone(), + CurrentAssetInvestmentAllocation { + asset: test.token0.address.clone(), + total_amount: amount0*3, + idle_amount: 0, + invested_amount: amount0*3, + strategy_investments: strategy_investments_expected_token_0, + }); + total_managed_funds_expected.set(test.token1.address.clone(), + CurrentAssetInvestmentAllocation { + asset: test.token1.address.clone(), + total_amount: amount1*3, + idle_amount: 0, + invested_amount: amount1*3, + strategy_investments: strategy_investments_expected_token_1, + }); let total_managed_funds = test.defindex_contract.fetch_total_managed_funds(); - assert_eq!(total_managed_funds, expected_invested_map); - + assert_eq!(total_managed_funds, total_managed_funds_expected); + // check current idle funds + let mut expected_idle_map = Map::new(&test.env); + expected_idle_map.set(test.token0.address.clone(), 0); + expected_idle_map.set(test.token1.address.clone(), 0); let current_idle_funds = test.defindex_contract.fetch_current_idle_funds(); assert_eq!(current_idle_funds, expected_idle_map); - + // check that current invested funds is now 0, funds still in idle funds + let mut expected_invested_map = Map::new(&test.env); + expected_invested_map.set(test.token0.address.clone(), 3*amount0); + expected_invested_map.set(test.token1.address.clone(), 3*amount1); let current_invested_funds = test.defindex_contract.fetch_current_invested_funds(); assert_eq!(current_invested_funds, expected_invested_map); @@ -322,4 +396,16 @@ fn deposit_and_invest_several_assets_success() { // Vec, i128 assert_eq!(deposit_result, (sorobanvec![&test.env, amount0*2, amount1*2], amount0*2 + amount1*2)); -} \ No newline at end of file +} + + + +#[test] +fn deposit_simple_then_deposit_and_invest() { + /* + Here we will check that everything works ok if the user first do a simple deposit without invest, and then does the deposit and invest + and if then does the deposit again without invest? + + */ + todo!(); +} diff --git a/apps/contracts/vault/src/test/get_asset_amounts_per_shares.rs b/apps/contracts/vault/src/test/get_asset_amounts_per_shares.rs index 553858cc..eb4fe42a 100644 --- a/apps/contracts/vault/src/test/get_asset_amounts_per_shares.rs +++ b/apps/contracts/vault/src/test/get_asset_amounts_per_shares.rs @@ -62,6 +62,7 @@ fn deposit_several_assets_get_asset_amounts_per_shares() { &sorobanvec![&test.env, amount0, amount1], &sorobanvec![&test.env, amount0, amount1], &users[0], + &false, ); // function is fn get_asset_amounts_per_shares(e: Env, vault_shares: i128) -> Map @@ -162,4 +163,10 @@ fn deposit_several_assets_get_asset_amounts_per_shares() { let result7 = test.defindex_contract.try_get_asset_amounts_per_shares(&1111111111i128); assert_eq!(result7, Err(Ok(ContractError::AmountOverTotalSupply))); -} \ No newline at end of file +} + +#[test] +fn deposit_and_invest_several_assets_get_asset_amounts_per_shares() { + todo!(); + +} From a96b1a346d2a5101ebe56a7601025a74162e8e9d Mon Sep 17 00:00:00 2001 From: esteblock Date: Wed, 4 Dec 2024 12:06:39 -0300 Subject: [PATCH 17/28] use total_managed_funds at the beggining of withdraw function, and pass it to calculate_asset_amounts_per_vault_shares --- apps/contracts/vault/src/lib.rs | 14 ++++++++++---- apps/contracts/vault/src/utils.rs | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/apps/contracts/vault/src/lib.rs b/apps/contracts/vault/src/lib.rs index 4fc57ad0..128e9c0f 100755 --- a/apps/contracts/vault/src/lib.rs +++ b/apps/contracts/vault/src/lib.rs @@ -168,7 +168,7 @@ impl VaultTrait for DeFindexVault { /// Handles user deposits into the DeFindex Vault. /// /// This function processes a deposit by transferring each specified asset amount from the user's address to - /// the vault, allocating assets according to the vault's defined strategy ratios, and minting dfTokens that + /// the vault, allocating assets according to the vault's defined strategy ratios, and minting vault shares that /// represent the user's proportional share in the vault. The `amounts_desired` and `amounts_min` vectors should /// align with the vault's asset order to ensure correct allocation. /// @@ -259,7 +259,9 @@ impl VaultTrait for DeFindexVault { // Calculate the withdrawal amounts for each asset based on the share amounts // Map Maps asset address to the amount to withdraw // this already considers the idle funds and all the invested amounts in strategies - let asset_amounts = calculate_asset_amounts_per_vault_shares(&e, shares_amount)?; + + let total_managed_funds = fetch_total_managed_funds(&e); + let asset_amounts = calculate_asset_amounts_per_vault_shares(&e, shares_amount, &total_managed_funds)?; // Burn the shares after calculating the withdrawal amounts (so total supply is correct // but before withdrawing to avoid reentrancy attacks) @@ -271,7 +273,10 @@ impl VaultTrait for DeFindexVault { // Loop through each asset in order to handle the withdrawal and if necesary to deallocate invested funds for (asset_address, required_amount) in asset_amounts.iter() { // Check idle funds for this asset - let idle_balance = fetch_idle_funds_for_asset(&e, &asset_address); + let idle_balance = total_managed_funds + .get(asset_address.clone()) + .unwrap_or_else(|| panic_with_error!(&e, ContractError::WrongAmountsLength)) + .idle_amount; // let amount_to_deallocate = if idle_balance >= required_amount { // 0 @@ -511,7 +516,8 @@ impl VaultTrait for DeFindexVault { /// * `Map` - A map containing each asset address and its corresponding proportional amount. fn get_asset_amounts_per_shares(e: Env, vault_shares: i128) -> Result, ContractError> { extend_instance_ttl(&e); - Ok(calculate_asset_amounts_per_vault_shares(&e, vault_shares)?) + let total_managed_funds = fetch_total_managed_funds(&e); + Ok(calculate_asset_amounts_per_vault_shares(&e, vault_shares, &total_managed_funds)?) } fn get_fees(e: Env) -> (u32, u32) { diff --git a/apps/contracts/vault/src/utils.rs b/apps/contracts/vault/src/utils.rs index 5ed05112..e532d937 100644 --- a/apps/contracts/vault/src/utils.rs +++ b/apps/contracts/vault/src/utils.rs @@ -84,12 +84,12 @@ pub fn calculate_withdrawal_amounts( pub fn calculate_asset_amounts_per_vault_shares( env: &Env, shares_amount: i128, + total_managed_funds: &Map, ) -> Result, ContractError> { let mut asset_amounts: Map = Map::new(env); // Fetch the total supply of vault shares and the total managed funds for each asset let total_shares_supply = VaultToken::total_supply(env.clone()); - let total_managed_funds = fetch_total_managed_funds(env); // if shares amount over total supply, return error AmountOverTotalSupply if shares_amount > total_shares_supply { From 110c325641698ef39fccb82530cfc3bf99ef12b4 Mon Sep 17 00:00:00 2001 From: esteblock Date: Wed, 4 Dec 2024 12:58:11 -0300 Subject: [PATCH 18/28] refactor withdraw function to get result of real sent amounts --- apps/contracts/vault/src/lib.rs | 150 ++++++++++++------------- apps/contracts/vault/src/strategies.rs | 30 ++--- apps/contracts/vault/src/utils.rs | 47 ++++---- 3 files changed, 112 insertions(+), 115 deletions(-) diff --git a/apps/contracts/vault/src/lib.rs b/apps/contracts/vault/src/lib.rs index 128e9c0f..b32fa311 100755 --- a/apps/contracts/vault/src/lib.rs +++ b/apps/contracts/vault/src/lib.rs @@ -27,7 +27,7 @@ mod utils; use access::{AccessControl, AccessControlTrait, RolesDataKey}; use aggregator::{internal_swap_exact_tokens_for_tokens, internal_swap_tokens_for_exact_tokens}; use fee::{collect_fees, fetch_defindex_fee}; -use funds::{fetch_current_idle_funds, fetch_current_invested_funds, fetch_total_managed_funds, fetch_idle_funds_for_asset}; +use funds::{fetch_current_idle_funds, fetch_current_invested_funds, fetch_total_managed_funds}; use interface::{AdminInterfaceTrait, VaultManagementTrait, VaultTrait}; use investment::check_and_execute_investments; use models::{ @@ -40,14 +40,14 @@ use storage::{ set_factory, set_total_assets, set_vault_fee, }; use strategies::{ - get_asset_allocation_from_address, get_strategy_asset, get_strategy_client, + get_strategy_asset, get_strategy_client, get_strategy_struct, invest_in_strategy, pause_strategy, unpause_strategy, withdraw_from_strategy, }; use token::{internal_burn, write_metadata, VaultToken}; use utils::{ calculate_asset_amounts_per_vault_shares, - calculate_withdrawal_amounts, check_initialized, + check_initialized, check_nonnegative_amount, }; @@ -238,102 +238,100 @@ impl VaultTrait for DeFindexVault { /// # Returns: /// * `Result<(), ContractError>` - Ok if successful, otherwise returns a ContractError. fn withdraw( - e: Env, - shares_amount: i128, - from: Address) -> Result, ContractError> { - - extend_instance_ttl(&e); + e: Env, + shares_amount: i128, + from: Address, + ) -> Result, ContractError> { + extend_instance_ttl(&e); check_initialized(&e)?; check_nonnegative_amount(shares_amount)?; from.require_auth(); - - // fees assesment + + // Assess fees collect_fees(&e)?; - - // Check if the user has enough dfTokens. // TODO, we can move this error into the internal_burn function + + // Check if the user has enough dfTokens. let df_user_balance = VaultToken::balance(e.clone(), from.clone()); if df_user_balance < shares_amount { return Err(ContractError::InsufficientBalance); } - + // Calculate the withdrawal amounts for each asset based on the share amounts - // Map Maps asset address to the amount to withdraw - // this already considers the idle funds and all the invested amounts in strategies - let total_managed_funds = fetch_total_managed_funds(&e); - let asset_amounts = calculate_asset_amounts_per_vault_shares(&e, shares_amount, &total_managed_funds)?; - // Burn the shares after calculating the withdrawal amounts (so total supply is correct - // but before withdrawing to avoid reentrancy attacks) + let asset_amounts = calculate_asset_amounts_per_vault_shares( + &e, + shares_amount, + &total_managed_funds, + )?; + + // Burn the shares after calculating the withdrawal amounts internal_burn(e.clone(), from.clone(), shares_amount); - - // Create a map to store the total amounts to transfer for each asset address - let mut total_amounts_to_transfer: Map = Map::new(&e); - - // Loop through each asset in order to handle the withdrawal and if necesary to deallocate invested funds + + // Loop through each asset to handle the withdrawal + let mut amounts_withdrawn: Vec = Vec::new(&e); for (asset_address, required_amount) in asset_amounts.iter() { - // Check idle funds for this asset - let idle_balance = total_managed_funds - .get(asset_address.clone()) - .unwrap_or_else(|| panic_with_error!(&e, ContractError::WrongAmountsLength)) - .idle_amount; - - // let amount_to_deallocate = if idle_balance >= required_amount { - // 0 - // } else { - // required_amount.checked_sub(idle_balance); - // } - - // if amount_to_deallocate>0{ - // // deallocate from strategies - // } + let asset_investment_allocation = total_managed_funds + .get(asset_address.clone()) + .unwrap_or_else(|| panic_with_error!(&e, ContractError::WrongAmountsLength)); - let mut remaining_amount = required_amount; - - // Withdraw as much as possible from idle funds first + // Check idle funds for this asset + let idle_balance = asset_investment_allocation.idle_amount; + + // Withdraw from idle funds first if idle_balance >= required_amount { // Idle funds cover the full amount - total_amounts_to_transfer.set(asset_address.clone(), required_amount); - continue; // No need to withdraw from the strategy + TokenClient::new(&e, &asset_address).transfer( + &e.current_contract_address(), + &from, + &required_amount, + ); + amounts_withdrawn.push_back(required_amount); + continue; } else { - // Partial withdrawal from idle funds - total_amounts_to_transfer.set(asset_address.clone(), idle_balance); - remaining_amount = required_amount - idle_balance; // Update remaining amount - } - - // Find the corresponding asset address for this strategy - let asset_allocation = get_asset_allocation_from_address(&e, asset_address.clone())?; - let withdrawal_amounts = - calculate_withdrawal_amounts(&e, remaining_amount, asset_allocation); - - for (strategy_address, amount) in withdrawal_amounts.iter() { - // TODO: What if the withdraw method exceeds the instructions limit? since im trying to ithdraw from all strategies of all assets... - withdraw_from_strategy(&e, &strategy_address, &amount)?; - - // Update the total amounts to transfer map - let current_amount = total_amounts_to_transfer - .get(strategy_address.clone()) - .unwrap_or(0); - total_amounts_to_transfer.set(asset_address.clone(), current_amount + amount); + let mut amounts_withdrawn_asset = 0; + // // Partial withdrawal from idle funds + TokenClient::new(&e, &asset_address).transfer( + &e.current_contract_address(), + &from, + &idle_balance, + ); + amounts_withdrawn_asset += idle_balance; + let remaining_amount = required_amount - idle_balance; + + // Withdraw the remaining amount from strategies + let invested_amount = asset_investment_allocation.invested_amount; + + for strategy in asset_investment_allocation.strategy_investments.iter() { + // TODO: If strategy is paused, shuold we skip it? Otherwise the calculation will go wrong. + // if strategy.paused { + // continue; + // } + + // amount to unwind from strategy + let strategy_share_of_withdrawal = + (remaining_amount * strategy.amount) / invested_amount; + + if strategy_share_of_withdrawal > 0 { + withdraw_from_strategy(&e, &strategy.strategy, &strategy_share_of_withdrawal)?; + TokenClient::new(&e, &asset_address).transfer( + &e.current_contract_address(), + &from, + &strategy_share_of_withdrawal, + ); + amounts_withdrawn_asset += strategy_share_of_withdrawal; + } + } + amounts_withdrawn.push_back(amounts_withdrawn_asset); } } - - // Perform the transfers for the total amounts - let mut amounts_withdrawn: Vec = Vec::new(&e); - for (asset_address, total_amount) in total_amounts_to_transfer.iter() { - TokenClient::new(&e, &asset_address).transfer( - &e.current_contract_address(), - &from, - &total_amount, - ); - amounts_withdrawn.push_back(total_amount); - } - + events::emit_withdraw_event(&e, from, shares_amount, amounts_withdrawn.clone()); - + Ok(amounts_withdrawn) } + /// Executes an emergency withdrawal from a specific strategy. /// diff --git a/apps/contracts/vault/src/strategies.rs b/apps/contracts/vault/src/strategies.rs index 51046e02..340896b4 100644 --- a/apps/contracts/vault/src/strategies.rs +++ b/apps/contracts/vault/src/strategies.rs @@ -34,21 +34,21 @@ pub fn get_strategy_asset( Err(ContractError::StrategyNotFound) } -/// Finds the AssetStrategySet corresponding to the given asset address. -pub fn get_asset_allocation_from_address( - e: &Env, - asset_address: Address, -) -> Result { - let assets = get_assets(e); - - for asset in assets.iter() { - if asset.address == asset_address { - return Ok(asset); - } - } - - Err(ContractError::AssetNotFound) -} +// /// Finds the AssetStrategySet corresponding to the given asset address. +// pub fn get_asset_allocation_from_address( +// e: &Env, +// asset_address: Address, +// ) -> Result { +// let assets = get_assets(e); + +// for asset in assets.iter() { +// if asset.address == asset_address { +// return Ok(asset); +// } +// } + +// Err(ContractError::AssetNotFound) +// } /// Finds the strategy struct corresponding to the given strategy address within the given asset. pub fn get_strategy_struct( diff --git a/apps/contracts/vault/src/utils.rs b/apps/contracts/vault/src/utils.rs index e532d937..6125b393 100644 --- a/apps/contracts/vault/src/utils.rs +++ b/apps/contracts/vault/src/utils.rs @@ -4,7 +4,6 @@ use crate::{ models::{CurrentAssetInvestmentAllocation}, access::{AccessControl, AccessControlTrait, RolesDataKey}, funds::{ - fetch_invested_funds_for_asset, fetch_invested_funds_for_strategy, fetch_total_managed_funds, }, token::VaultToken, @@ -39,33 +38,33 @@ pub fn check_nonnegative_amount(amount: i128) -> Result<(), ContractError> { } } -/// From an amount, calculates how much to withdraw from each strategy; -/// returns a map of strategy address to token amount -pub fn calculate_withdrawal_amounts( - e: &Env, - amount: i128, - asset: AssetStrategySet, -) -> Map { - let mut withdrawal_amounts = Map::::new(e); - - let (total_invested_in_strategies, _) = fetch_invested_funds_for_asset(&e, &asset); - - for strategy in asset.strategies.iter() { - // TODO: if strategy is paused but still holds assets on it shouldnt we withdraw them? - if strategy.paused { - continue; - } +// /// From an amount, calculates how much to withdraw from each strategy; +// /// returns a map of strategy address to token amount +// pub fn calculate_withdrawal_amounts( +// e: &Env, +// amount: i128, +// asset: AssetStrategySet, +// ) -> Map { +// let mut withdrawal_amounts = Map::::new(e); + +// let (total_invested_in_strategies, _) = fetch_invested_funds_for_asset(&e, &asset); + +// for strategy in asset.strategies.iter() { +// // TODO: if strategy is paused but still holds assets on it shouldnt we withdraw them? +// if strategy.paused { +// continue; +// } - let strategy_invested_funds = fetch_invested_funds_for_strategy(e, &strategy.address); +// let strategy_invested_funds = fetch_invested_funds_for_strategy(e, &strategy.address); - let strategy_share_of_withdrawal = - (amount * strategy_invested_funds) / total_invested_in_strategies; +// let strategy_share_of_withdrawal = +// (amount * strategy_invested_funds) / total_invested_in_strategies; - withdrawal_amounts.set(strategy.address.clone(), strategy_share_of_withdrawal); - } +// withdrawal_amounts.set(strategy.address.clone(), strategy_share_of_withdrawal); +// } - withdrawal_amounts -} +// withdrawal_amounts +// } /// Calculates the corresponding amounts of each asset per given number of vault shares. /// This function takes the number of vault shares (`shares_amount`) and computes how much of each asset in the vault From 0fca2a9929a0f1c3ddb5184dc8ea976002ce8df7 Mon Sep 17 00:00:00 2001 From: esteblock Date: Wed, 4 Dec 2024 13:07:59 -0300 Subject: [PATCH 19/28] withdraw: do only one token transfer --- apps/contracts/vault/src/lib.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/apps/contracts/vault/src/lib.rs b/apps/contracts/vault/src/lib.rs index b32fa311..cd6db26c 100755 --- a/apps/contracts/vault/src/lib.rs +++ b/apps/contracts/vault/src/lib.rs @@ -290,14 +290,9 @@ impl VaultTrait for DeFindexVault { amounts_withdrawn.push_back(required_amount); continue; } else { - let mut amounts_withdrawn_asset = 0; + let mut amounts_to_withdraw_asset = 0; // // Partial withdrawal from idle funds - TokenClient::new(&e, &asset_address).transfer( - &e.current_contract_address(), - &from, - &idle_balance, - ); - amounts_withdrawn_asset += idle_balance; + amounts_to_withdraw_asset += idle_balance; let remaining_amount = required_amount - idle_balance; // Withdraw the remaining amount from strategies @@ -320,10 +315,15 @@ impl VaultTrait for DeFindexVault { &from, &strategy_share_of_withdrawal, ); - amounts_withdrawn_asset += strategy_share_of_withdrawal; + amounts_to_withdraw_asset += strategy_share_of_withdrawal; } } - amounts_withdrawn.push_back(amounts_withdrawn_asset); + TokenClient::new(&e, &asset_address).transfer( + &e.current_contract_address(), + &from, + &amounts_to_withdraw_asset, + ); + amounts_withdrawn.push_back(amounts_to_withdraw_asset); } } From 5854ef6ce8633e5516ac18fc76ee98bad10e4f91 Mon Sep 17 00:00:00 2001 From: esteblock Date: Wed, 4 Dec 2024 13:21:10 -0300 Subject: [PATCH 20/28] Strategy Allocation Naming --- apps/contracts/vault/src/deposit.rs | 8 +- apps/contracts/vault/src/funds.rs | 20 ++--- apps/contracts/vault/src/investment.rs | 4 +- apps/contracts/vault/src/lib.rs | 68 +++++++-------- apps/contracts/vault/src/models.rs | 16 ++-- .../contracts/vault/src/test/vault/deposit.rs | 30 +++---- .../src/test/vault/deposit_and_invest.rs | 26 +++--- .../src/test/vault/emergency_withdraw.rs | 6 +- apps/contracts/vault/src/test/vault/invest.rs | 86 +++++++++---------- .../vault/src/test/vault/rebalance.rs | 10 +-- .../vault/src/test/vault/withdraw.rs | 6 +- apps/contracts/vault/src/token/balance.rs | 5 +- apps/contracts/vault/src/token/contract.rs | 1 + 13 files changed, 142 insertions(+), 144 deletions(-) diff --git a/apps/contracts/vault/src/deposit.rs b/apps/contracts/vault/src/deposit.rs index 9cd351a5..35ebbb9b 100644 --- a/apps/contracts/vault/src/deposit.rs +++ b/apps/contracts/vault/src/deposit.rs @@ -7,7 +7,7 @@ use crate::{ fetch_total_managed_funds, }, investment::check_and_execute_investments, - models::{AssetInvestmentAllocation, StrategyInvestment}, + models::{AssetInvestmentAllocation, StrategyAllocation}, storage::get_assets, token::{internal_mint, VaultToken}, utils::{calculate_deposit_amounts_and_shares_to_mint, check_nonnegative_amount}, @@ -120,7 +120,7 @@ pub fn generate_and_execute_investments( let asset = assets.get(i as u32).unwrap(); let (asset_invested_funds, _) = fetch_invested_funds_for_asset(&e, &asset); - let mut strategy_investments = Vec::new(&e); + let mut strategy_allocations = Vec::new(&e); let mut remaining_amount = amount; for (j, strategy) in asset.strategies.iter().enumerate() { @@ -138,7 +138,7 @@ pub fn generate_and_execute_investments( remaining_amount -= invest_amount; - strategy_investments.push_back(Some(StrategyInvestment { + strategy_allocations.push_back(Some(StrategyAllocation { strategy: strategy.address.clone(), amount: invest_amount, })); @@ -146,7 +146,7 @@ pub fn generate_and_execute_investments( asset_investments.push_back(Some(AssetInvestmentAllocation { asset: asset.address.clone(), - strategy_investments, + strategy_allocations, })); } diff --git a/apps/contracts/vault/src/funds.rs b/apps/contracts/vault/src/funds.rs index 54519555..ce3e033d 100644 --- a/apps/contracts/vault/src/funds.rs +++ b/apps/contracts/vault/src/funds.rs @@ -2,7 +2,7 @@ use soroban_sdk::token::TokenClient; use soroban_sdk::{Address, Env, Map, Vec}; use common::models::AssetStrategySet; -use crate::models::{StrategyInvestment, CurrentAssetInvestmentAllocation}; +use crate::models::{StrategyAllocation, CurrentAssetInvestmentAllocation}; use crate::storage::get_assets; use crate::strategies::get_strategy_client; @@ -38,25 +38,25 @@ pub fn fetch_invested_funds_for_strategy(e: &Env, strategy_address: &Address) -> // // Investment Allocation in Strategies // #[contracttype] // #[derive(Clone, Debug, Eq, PartialEq)] -// pub struct StrategyInvestment { +// pub struct StrategyAllocation { // pub strategy: Address, // pub amount: i128, // } -// return total invested funds but also a vec of StrategyInvestment -pub fn fetch_invested_funds_for_asset(e: &Env, asset: &AssetStrategySet) -> (i128, Vec){ +// return total invested funds but also a vec of StrategyAllocation +pub fn fetch_invested_funds_for_asset(e: &Env, asset: &AssetStrategySet) -> (i128, Vec){ let mut invested_funds = 0; - let mut strategy_investments: Vec = Vec::new(e); + let mut strategy_allocations: Vec = Vec::new(e); for strategy in asset.strategies.iter() { let strategy_balance = fetch_invested_funds_for_strategy(e, &strategy.address); invested_funds += strategy_balance; - strategy_investments.push_back(StrategyInvestment { + strategy_allocations.push_back(StrategyAllocation { strategy: strategy.address.clone(), amount: strategy_balance, }); } - (invested_funds, strategy_investments) + (invested_funds, strategy_allocations) } // Pub functions @@ -118,14 +118,14 @@ pub fn fetch_current_invested_funds(e: &Env) -> Map { // pub total_amount: i128, // pub idle_amount: i128, // pub invested_amount: i128, -// pub strategy_investments: Vec, +// pub strategy_allocations: Vec, // } pub fn fetch_total_managed_funds(e: &Env) -> Map { let assets = get_assets(e); let mut map: Map = Map::new(e); for asset in assets { let idle_amount = fetch_idle_funds_for_asset(e, &asset.address); - let (invested_amount, strategy_investments) = fetch_invested_funds_for_asset(e, &asset); + let (invested_amount, strategy_allocations) = fetch_invested_funds_for_asset(e, &asset); let total_amount = idle_amount + invested_amount; map.set( asset.address.clone(), @@ -134,7 +134,7 @@ pub fn fetch_total_managed_funds(e: &Env) -> Map` - Ok if successful, otherwise returns a ContractError. fn withdraw( e: Env, - shares_amount: i128, + withdraw_shares: i128, from: Address, ) -> Result, ContractError> { extend_instance_ttl(&e); check_initialized(&e)?; - check_nonnegative_amount(shares_amount)?; + check_nonnegative_amount(withdraw_shares)?; from.require_auth(); // Assess fees collect_fees(&e)?; - // Check if the user has enough dfTokens. - let df_user_balance = VaultToken::balance(e.clone(), from.clone()); - if df_user_balance < shares_amount { - return Err(ContractError::InsufficientBalance); - } - // Calculate the withdrawal amounts for each asset based on the share amounts let total_managed_funds = fetch_total_managed_funds(&e); - let asset_amounts = calculate_asset_amounts_per_vault_shares( + let asset_withdrawal_amounts = calculate_asset_amounts_per_vault_shares( &e, - shares_amount, + withdraw_shares, &total_managed_funds, )?; // Burn the shares after calculating the withdrawal amounts - internal_burn(e.clone(), from.clone(), shares_amount); + // this will panic with error if the user does not have enough balance + internal_burn(e.clone(), from.clone(), withdraw_shares); // Loop through each asset to handle the withdrawal - let mut amounts_withdrawn: Vec = Vec::new(&e); - for (asset_address, required_amount) in asset_amounts.iter() { + let mut withdrawn_amounts: Vec = Vec::new(&e); + for (asset_address, requested_withdrawal_amount) in asset_withdrawal_amounts.iter() { - let asset_investment_allocation = total_managed_funds + let asset_allocation = total_managed_funds .get(asset_address.clone()) .unwrap_or_else(|| panic_with_error!(&e, ContractError::WrongAmountsLength)); // Check idle funds for this asset - let idle_balance = asset_investment_allocation.idle_amount; + let idle_funds = asset_allocation.idle_amount; // Withdraw from idle funds first - if idle_balance >= required_amount { + if idle_funds >= requested_withdrawal_amount { // Idle funds cover the full amount TokenClient::new(&e, &asset_address).transfer( &e.current_contract_address(), &from, - &required_amount, + &requested_withdrawal_amount, ); - amounts_withdrawn.push_back(required_amount); + withdrawn_amounts.push_back(requested_withdrawal_amount); continue; } else { - let mut amounts_to_withdraw_asset = 0; - // // Partial withdrawal from idle funds - amounts_to_withdraw_asset += idle_balance; - let remaining_amount = required_amount - idle_balance; + let mut total_withdrawn_for_asset = 0; + // Partial withdrawal from idle funds + total_withdrawn_for_asset += idle_funds; + let remaining_withdrawal_amount = requested_withdrawal_amount - idle_funds; // Withdraw the remaining amount from strategies - let invested_amount = asset_investment_allocation.invested_amount; + let total_invested_amount = asset_allocation.invested_amount; - for strategy in asset_investment_allocation.strategy_investments.iter() { - // TODO: If strategy is paused, shuold we skip it? Otherwise the calculation will go wrong. + for strategy_allocation in asset_allocation.strategy_allocations.iter() { + // TODO: If strategy is paused, should we skip it? Otherwise, the calculation will go wrong. // if strategy.paused { // continue; // } - // amount to unwind from strategy - let strategy_share_of_withdrawal = - (remaining_amount * strategy.amount) / invested_amount; + // Amount to unwind from strategy + let strategy_withdrawal_share = + (remaining_withdrawal_amount * strategy_allocation.amount) / total_invested_amount; - if strategy_share_of_withdrawal > 0 { - withdraw_from_strategy(&e, &strategy.strategy, &strategy_share_of_withdrawal)?; + if strategy_withdrawal_share > 0 { + withdraw_from_strategy(&e, &strategy_allocation.strategy, &strategy_withdrawal_share)?; TokenClient::new(&e, &asset_address).transfer( &e.current_contract_address(), &from, - &strategy_share_of_withdrawal, + &strategy_withdrawal_share, ); - amounts_to_withdraw_asset += strategy_share_of_withdrawal; + total_withdrawn_for_asset += strategy_withdrawal_share; } } TokenClient::new(&e, &asset_address).transfer( &e.current_contract_address(), &from, - &amounts_to_withdraw_asset, + &total_withdrawn_for_asset, ); - amounts_withdrawn.push_back(amounts_to_withdraw_asset); + withdrawn_amounts.push_back(total_withdrawn_for_asset); } } - events::emit_withdraw_event(&e, from, shares_amount, amounts_withdrawn.clone()); + events::emit_withdraw_event(&e, from, withdraw_shares, withdrawn_amounts.clone()); - Ok(amounts_withdrawn) + Ok(withdrawn_amounts) } + /// Executes an emergency withdrawal from a specific strategy. diff --git a/apps/contracts/vault/src/models.rs b/apps/contracts/vault/src/models.rs index 5c16679b..0391665b 100644 --- a/apps/contracts/vault/src/models.rs +++ b/apps/contracts/vault/src/models.rs @@ -3,17 +3,11 @@ use soroban_sdk::{contracttype, Address, String, Vec}; // Investment Allocation in Strategies #[contracttype] #[derive(Clone, Debug, Eq, PartialEq)] -pub struct StrategyInvestment { +pub struct StrategyAllocation { pub strategy: Address, pub amount: i128, } -#[contracttype] -#[derive(Clone, Debug, Eq, PartialEq)] -pub struct AssetInvestmentAllocation { - pub asset: Address, - pub strategy_investments: Vec>, -} // Current Asset Investment Allocation #[contracttype] #[derive(Clone, Debug, Eq, PartialEq)] @@ -22,9 +16,15 @@ pub struct CurrentAssetInvestmentAllocation { pub total_amount: i128, pub idle_amount: i128, pub invested_amount: i128, - pub strategy_investments: Vec, + pub strategy_allocations: Vec, } +#[contracttype] +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct AssetInvestmentAllocation { + pub asset: Address, + pub strategy_allocations: Vec>, +} // #[contracttype] #[derive(Clone, Debug, Eq, PartialEq)] diff --git a/apps/contracts/vault/src/test/vault/deposit.rs b/apps/contracts/vault/src/test/vault/deposit.rs index cfc9cbbf..b0d8caf2 100644 --- a/apps/contracts/vault/src/test/vault/deposit.rs +++ b/apps/contracts/vault/src/test/vault/deposit.rs @@ -1,6 +1,6 @@ use soroban_sdk::{vec as sorobanvec, InvokeError, Map, String, Vec}; -use crate::test::defindex_vault::{AssetStrategySet, ContractError, CurrentAssetInvestmentAllocation, StrategyInvestment}; +use crate::test::defindex_vault::{AssetStrategySet, ContractError, CurrentAssetInvestmentAllocation, StrategyAllocation}; use crate::test::{ create_strategy_params_token0, create_strategy_params_token1, DeFindexVaultTest, }; @@ -317,16 +317,16 @@ fn one_asset_success() { // pub total_amount: i128, // pub idle_amount: i128, // pub invested_amount: i128, - // pub strategy_investments: Vec, + // pub strategy_allocations: Vec, // } - // pub struct StrategyInvestment { + // pub struct StrategyAllocation { // pub strategy: Address, // pub amount: i128, // } // construct expected total manage funds let mut total_managed_funds_expected = Map::new(&test.env); - let strategy_investments_expected = sorobanvec![&test.env, StrategyInvestment { + let strategy_investments_expected = sorobanvec![&test.env, StrategyAllocation { strategy: test.strategy_client_token0.address.clone(), amount: 0, //funds has not been invested yet! }]; @@ -336,7 +336,7 @@ fn one_asset_success() { total_amount: amount, idle_amount: amount, invested_amount: 0i128, - strategy_investments: strategy_investments_expected, + strategy_allocations: strategy_investments_expected, } ); @@ -392,7 +392,7 @@ fn one_asset_success() { // check that fetch_total_managed_funds returns correct amount let mut total_managed_funds_expected = Map::new(&test.env); - let strategy_investments_expected = sorobanvec![&test.env, StrategyInvestment { + let strategy_investments_expected = sorobanvec![&test.env, StrategyAllocation { strategy: test.strategy_client_token0.address.clone(), amount: 0, // funds have not been invested yet! }]; @@ -402,7 +402,7 @@ fn one_asset_success() { total_amount: amount + amount2, idle_amount: amount + amount2, invested_amount: 0i128, - strategy_investments: strategy_investments_expected, + strategy_allocations: strategy_investments_expected, } ); let total_managed_funds = test.defindex_contract.fetch_total_managed_funds(); @@ -558,11 +558,11 @@ fn several_assets_success() { // check total managed funds let mut total_managed_funds_expected = Map::new(&test.env); - let strategy_investments_expected_token_0 = sorobanvec![&test.env, StrategyInvestment { + let strategy_investments_expected_token_0 = sorobanvec![&test.env, StrategyAllocation { strategy: test.strategy_client_token0.address.clone(), amount: 0, // funds have not been invested yet! }]; - let strategy_investments_expected_token_1 = sorobanvec![&test.env, StrategyInvestment { + let strategy_investments_expected_token_1 = sorobanvec![&test.env, StrategyAllocation { strategy: test.strategy_client_token1.address.clone(), amount: 0, // funds have not been invested yet! }]; @@ -572,7 +572,7 @@ fn several_assets_success() { total_amount: amount0, idle_amount: amount0, invested_amount: 0i128, - strategy_investments: strategy_investments_expected_token_0, + strategy_allocations: strategy_investments_expected_token_0, } ); total_managed_funds_expected.set(test.token1.address.clone(), @@ -581,7 +581,7 @@ fn several_assets_success() { total_amount: amount1, idle_amount: amount1, invested_amount: 0i128, - strategy_investments: strategy_investments_expected_token_1, + strategy_allocations: strategy_investments_expected_token_1, } ); let total_managed_funds = test.defindex_contract.fetch_total_managed_funds(); @@ -657,11 +657,11 @@ fn several_assets_success() { // check total managed funds let mut total_managed_funds_expected = Map::new(&test.env); - let strategy_investments_expected_token_0 = sorobanvec![&test.env, StrategyInvestment { + let strategy_investments_expected_token_0 = sorobanvec![&test.env, StrategyAllocation { strategy: test.strategy_client_token0.address.clone(), amount: 0, // funds have not been invested yet! }]; - let strategy_investments_expected_token_1 = sorobanvec![&test.env, StrategyInvestment { + let strategy_investments_expected_token_1 = sorobanvec![&test.env, StrategyAllocation { strategy: test.strategy_client_token1.address.clone(), amount: 0, // funds have not been invested yet! }]; @@ -671,7 +671,7 @@ fn several_assets_success() { total_amount: 3*amount0, idle_amount: 3*amount0, invested_amount: 0i128, - strategy_investments: strategy_investments_expected_token_0, + strategy_allocations: strategy_investments_expected_token_0, } ); total_managed_funds_expected.set(test.token1.address.clone(), @@ -680,7 +680,7 @@ fn several_assets_success() { total_amount: 3*amount1, idle_amount: 3*amount1, invested_amount: 0i128, - strategy_investments: strategy_investments_expected_token_1, + strategy_allocations: strategy_investments_expected_token_1, } ); let total_managed_funds = test.defindex_contract.fetch_total_managed_funds(); diff --git a/apps/contracts/vault/src/test/vault/deposit_and_invest.rs b/apps/contracts/vault/src/test/vault/deposit_and_invest.rs index c2bd0a97..f875930c 100644 --- a/apps/contracts/vault/src/test/vault/deposit_and_invest.rs +++ b/apps/contracts/vault/src/test/vault/deposit_and_invest.rs @@ -1,6 +1,6 @@ use soroban_sdk::{vec as sorobanvec, String, Vec, Map}; -use crate::test::defindex_vault::{AssetStrategySet, StrategyInvestment, CurrentAssetInvestmentAllocation}; +use crate::test::defindex_vault::{AssetStrategySet, StrategyAllocation, CurrentAssetInvestmentAllocation}; use crate::test::{ create_strategy_params_token0, create_strategy_params_token1, DeFindexVaultTest, }; @@ -64,7 +64,7 @@ fn one_asset_success() { // check total managed funds let mut total_managed_funds_expected = Map::new(&test.env); - let strategy_investments_expected_token_0 = sorobanvec![&test.env, StrategyInvestment { + let strategy_investments_expected_token_0 = sorobanvec![&test.env, StrategyAllocation { strategy: test.strategy_client_token0.address.clone(), amount: amount, // everything has been invested }]; @@ -75,7 +75,7 @@ fn one_asset_success() { total_amount: amount, idle_amount: 0, invested_amount: amount, - strategy_investments: strategy_investments_expected_token_0, + strategy_allocations: strategy_investments_expected_token_0, }); let total_managed_funds = test.defindex_contract.fetch_total_managed_funds(); @@ -125,7 +125,7 @@ fn one_asset_success() { // check that fetch_total_managed_funds returns correct amount let mut total_managed_funds_expected = Map::new(&test.env); - let strategy_investments_expected_token_0 = sorobanvec![&test.env, StrategyInvestment { + let strategy_investments_expected_token_0 = sorobanvec![&test.env, StrategyAllocation { strategy: test.strategy_client_token0.address.clone(), amount: amount + amount2, // everything has been invested }]; @@ -136,7 +136,7 @@ fn one_asset_success() { total_amount: amount + amount2, idle_amount: 0, invested_amount: amount + amount2, - strategy_investments: strategy_investments_expected_token_0, + strategy_allocations: strategy_investments_expected_token_0, }); let total_managed_funds = test.defindex_contract.fetch_total_managed_funds(); @@ -237,11 +237,11 @@ fn several_assets_success() { // check that fetch_total_managed_funds returns correct amount let mut total_managed_funds_expected = Map::new(&test.env); - let strategy_investments_expected_token_0 = sorobanvec![&test.env, StrategyInvestment { + let strategy_investments_expected_token_0 = sorobanvec![&test.env, StrategyAllocation { strategy: test.strategy_client_token0.address.clone(), amount: amount0, // everything has been invested }]; - let strategy_investments_expected_token_1 = sorobanvec![&test.env, StrategyInvestment { + let strategy_investments_expected_token_1 = sorobanvec![&test.env, StrategyAllocation { strategy: test.strategy_client_token1.address.clone(), amount: amount1, // everything has been invested }]; @@ -251,7 +251,7 @@ fn several_assets_success() { total_amount: amount0, idle_amount: 0, invested_amount: amount0, - strategy_investments: strategy_investments_expected_token_0, + strategy_allocations: strategy_investments_expected_token_0, }); total_managed_funds_expected.set(test.token1.address.clone(), CurrentAssetInvestmentAllocation { @@ -259,7 +259,7 @@ fn several_assets_success() { total_amount: amount1, idle_amount: 0, invested_amount: amount1, - strategy_investments: strategy_investments_expected_token_1, + strategy_allocations: strategy_investments_expected_token_1, }); let total_managed_funds = test.defindex_contract.fetch_total_managed_funds(); @@ -329,11 +329,11 @@ fn several_assets_success() { // check that fetch_total_managed_funds returns correct amount let mut total_managed_funds_expected = Map::new(&test.env); - let strategy_investments_expected_token_0 = sorobanvec![&test.env, StrategyInvestment { + let strategy_investments_expected_token_0 = sorobanvec![&test.env, StrategyAllocation { strategy: test.strategy_client_token0.address.clone(), amount: amount0*3, // everything has been invested }]; - let strategy_investments_expected_token_1 = sorobanvec![&test.env, StrategyInvestment { + let strategy_investments_expected_token_1 = sorobanvec![&test.env, StrategyAllocation { strategy: test.strategy_client_token1.address.clone(), amount: amount1*3, // everything has been invested }]; @@ -343,7 +343,7 @@ fn several_assets_success() { total_amount: amount0*3, idle_amount: 0, invested_amount: amount0*3, - strategy_investments: strategy_investments_expected_token_0, + strategy_allocations: strategy_investments_expected_token_0, }); total_managed_funds_expected.set(test.token1.address.clone(), CurrentAssetInvestmentAllocation { @@ -351,7 +351,7 @@ fn several_assets_success() { total_amount: amount1*3, idle_amount: 0, invested_amount: amount1*3, - strategy_investments: strategy_investments_expected_token_1, + strategy_allocations: strategy_investments_expected_token_1, }); let total_managed_funds = test.defindex_contract.fetch_total_managed_funds(); assert_eq!(total_managed_funds, total_managed_funds_expected); diff --git a/apps/contracts/vault/src/test/vault/emergency_withdraw.rs b/apps/contracts/vault/src/test/vault/emergency_withdraw.rs index 0620bd97..f75f7d88 100644 --- a/apps/contracts/vault/src/test/vault/emergency_withdraw.rs +++ b/apps/contracts/vault/src/test/vault/emergency_withdraw.rs @@ -4,7 +4,7 @@ use crate::test::{ create_strategy_params_token0, defindex_vault::{AssetStrategySet, AssetInvestmentAllocation, - StrategyInvestment + StrategyAllocation }, DeFindexVaultTest, }; @@ -63,9 +63,9 @@ fn withdraw_success() { &test.env, Some(AssetInvestmentAllocation { asset: test.token0.address.clone(), - strategy_investments: sorobanvec![ + strategy_allocations: sorobanvec![ &test.env, - Some(StrategyInvestment { + Some(StrategyAllocation { strategy: test.strategy_client_token0.address.clone(), amount: amount, }), diff --git a/apps/contracts/vault/src/test/vault/invest.rs b/apps/contracts/vault/src/test/vault/invest.rs index d70e7c23..89968274 100644 --- a/apps/contracts/vault/src/test/vault/invest.rs +++ b/apps/contracts/vault/src/test/vault/invest.rs @@ -8,7 +8,7 @@ use crate::test::defindex_vault::{ CurrentAssetInvestmentAllocation, AssetStrategySet, AssetInvestmentAllocation, - StrategyInvestment, + StrategyAllocation, Strategy, ContractError}; use crate::test::{ @@ -24,9 +24,9 @@ fn not_yet_initialized() { &test.env, Some(AssetInvestmentAllocation { asset: test.token0.address.clone(), - strategy_investments: vec![ + strategy_allocations: vec![ &test.env, - Some(StrategyInvestment { + Some(StrategyAllocation { strategy: test.strategy_client_token0.address.clone(), amount: 100, })], @@ -77,9 +77,9 @@ fn wrong_asset_investment_length() { &test.env, Some(AssetInvestmentAllocation { asset: test.token0.address.clone(), - strategy_investments: vec![ + strategy_allocations: vec![ &test.env, - Some(StrategyInvestment { + Some(StrategyAllocation { strategy: test.strategy_client_token0.address.clone(), amount: 100, })], @@ -99,9 +99,9 @@ fn wrong_asset_investment_length() { &test.env, Some(AssetInvestmentAllocation { asset: test.token0.address.clone(), - strategy_investments: vec![ + strategy_allocations: vec![ &test.env, - Some(StrategyInvestment { + Some(StrategyAllocation { strategy: test.strategy_client_token0.address.clone(), amount: 100, }) @@ -168,13 +168,13 @@ fn wrong_strategy_length() { &test.env, Some(AssetInvestmentAllocation { asset: test.token0.address.clone(), - strategy_investments: vec![ + strategy_allocations: vec![ &test.env, - Some(StrategyInvestment { + Some(StrategyAllocation { strategy: test.strategy_client_token0.address.clone(), amount: 100, }), - Some(StrategyInvestment { + Some(StrategyAllocation { strategy: test.strategy_client_token1.address.clone(), amount: 100, }), @@ -195,15 +195,15 @@ fn wrong_strategy_length() { &test.env, Some(AssetInvestmentAllocation { asset: test.token0.address.clone(), - strategy_investments: vec![ + strategy_allocations: vec![ &test.env, // 0 instead of 1 ], }), Some(AssetInvestmentAllocation { asset: test.token1.address.clone(), - strategy_investments: vec![ + strategy_allocations: vec![ &test.env, - Some(StrategyInvestment { + Some(StrategyAllocation { strategy: test.strategy_client_token1.address.clone(), amount: 100, }), @@ -260,9 +260,9 @@ fn wrong_asset_address() { &test.env, Some(AssetInvestmentAllocation { asset: test.token1.address.clone(), // wrong address, should be asset 0 - strategy_investments: vec![ + strategy_allocations: vec![ &test.env, - Some(StrategyInvestment { + Some(StrategyAllocation { strategy: test.strategy_client_token0.address.clone(), amount: 100, }), @@ -317,9 +317,9 @@ fn negative_amount() { &test.env, Some(AssetInvestmentAllocation { asset: test.token0.address.clone(), - strategy_investments: vec![ + strategy_allocations: vec![ &test.env, - Some(StrategyInvestment { + Some(StrategyAllocation { strategy: test.strategy_client_token0.address.clone(), amount: -100, // negative amount }), @@ -374,9 +374,9 @@ fn paused_strategy() { &test.env, Some(AssetInvestmentAllocation { asset: test.token0.address.clone(), - strategy_investments: vec![ + strategy_allocations: vec![ &test.env, - Some(StrategyInvestment { + Some(StrategyAllocation { strategy: test.strategy_client_token0.address.clone(), amount: 100, }), @@ -463,11 +463,11 @@ fn in_strategy() { let mut total_managed_funds_expected = Map::new(&test.env); - let strategy_investments_expected_token_0 = sorobanvec![&test.env, StrategyInvestment { + let strategy_investments_expected_token_0 = sorobanvec![&test.env, StrategyAllocation { strategy: test.strategy_client_token0.address.clone(), amount: 0, // funds have not been invested yet! }]; - let strategy_investments_expected_token_1 = sorobanvec![&test.env, StrategyInvestment { + let strategy_investments_expected_token_1 = sorobanvec![&test.env, StrategyAllocation { strategy: test.strategy_client_token1.address.clone(), amount: 0, // funds have not been invested yet! }]; @@ -477,7 +477,7 @@ fn in_strategy() { total_amount: amount_0, idle_amount: amount_0, invested_amount: 0i128, - strategy_investments: strategy_investments_expected_token_0, + strategy_allocations: strategy_investments_expected_token_0, }); total_managed_funds_expected.set(test.token1.address.clone(), CurrentAssetInvestmentAllocation { @@ -485,7 +485,7 @@ fn in_strategy() { total_amount: amount_1, idle_amount: amount_1, invested_amount: 0i128, - strategy_investments: strategy_investments_expected_token_1, + strategy_allocations: strategy_investments_expected_token_1, }); let total_managed_funds = test.defindex_contract.fetch_total_managed_funds(); @@ -513,9 +513,9 @@ fn in_strategy() { &test.env, Some(AssetInvestmentAllocation { asset: test.token0.address.clone(), - strategy_investments: vec![ + strategy_allocations: vec![ &test.env, - Some(StrategyInvestment { + Some(StrategyAllocation { strategy: test.strategy_client_token0.address.clone(), amount: 100, }), @@ -523,9 +523,9 @@ fn in_strategy() { }), Some(AssetInvestmentAllocation { asset: test.token1.address.clone(), - strategy_investments: vec![ + strategy_allocations: vec![ &test.env, - Some(StrategyInvestment { + Some(StrategyAllocation { strategy: test.strategy_client_token1.address.clone(), amount: 200, }), @@ -544,11 +544,11 @@ fn in_strategy() { // check total managed funds let mut total_managed_funds_expected = Map::new(&test.env); - let strategy_investments_expected_token_0 = sorobanvec![&test.env, StrategyInvestment { + let strategy_investments_expected_token_0 = sorobanvec![&test.env, StrategyAllocation { strategy: test.strategy_client_token0.address.clone(), amount: 100, }]; - let strategy_investments_expected_token_1 = sorobanvec![&test.env, StrategyInvestment { + let strategy_investments_expected_token_1 = sorobanvec![&test.env, StrategyAllocation { strategy: test.strategy_client_token1.address.clone(), amount: 200, }]; @@ -558,7 +558,7 @@ fn in_strategy() { total_amount: amount_0, idle_amount: amount_0 - 100, invested_amount: 100i128, - strategy_investments: strategy_investments_expected_token_0, + strategy_allocations: strategy_investments_expected_token_0, }); total_managed_funds_expected.set(test.token1.address.clone(), CurrentAssetInvestmentAllocation { @@ -566,7 +566,7 @@ fn in_strategy() { total_amount: amount_1, idle_amount: amount_1 - 200, invested_amount: 200i128, - strategy_investments: strategy_investments_expected_token_1, + strategy_allocations: strategy_investments_expected_token_1, }); let total_managed_funds = test.defindex_contract.fetch_total_managed_funds(); @@ -673,9 +673,9 @@ fn more_than_idle_funds() { &test.env, Some(AssetInvestmentAllocation { asset: test.token0.address.clone(), - strategy_investments: vec![ + strategy_allocations: vec![ &test.env, - Some(StrategyInvestment { + Some(StrategyAllocation { strategy: test.strategy_client_token0.address.clone(), amount: vault_balance_0 + 1, }), @@ -683,9 +683,9 @@ fn more_than_idle_funds() { }), Some(AssetInvestmentAllocation { asset: test.token1.address.clone(), - strategy_investments: vec![ + strategy_allocations: vec![ &test.env, - Some(StrategyInvestment { + Some(StrategyAllocation { strategy: test.strategy_client_token1.address.clone(), amount: vault_balance_1 + 1, }), @@ -828,9 +828,9 @@ fn without_mock_all_auths() { Some( AssetInvestmentAllocation { asset: test.token0.address.clone(), - strategy_investments: + strategy_allocations: sorobanvec![&test.env, - Some(StrategyInvestment { + Some(StrategyAllocation { strategy: test.strategy_client_token0.address.clone(), amount: 100, })] @@ -839,8 +839,8 @@ fn without_mock_all_auths() { Some( AssetInvestmentAllocation { asset: test.token1.address.clone(), - strategy_investments: sorobanvec![&test.env, - Some(StrategyInvestment { + strategy_allocations: sorobanvec![&test.env, + Some(StrategyAllocation { strategy: test.strategy_client_token1.address.clone(), amount: 200, })] @@ -855,8 +855,8 @@ fn without_mock_all_auths() { Some( AssetInvestmentAllocation { asset: test.token0.address.clone(), - strategy_investments: sorobanvec![&test.env, - Some(StrategyInvestment { + strategy_allocations: sorobanvec![&test.env, + Some(StrategyAllocation { strategy: test.strategy_client_token0.address.clone(), amount: 100, })] @@ -865,8 +865,8 @@ fn without_mock_all_auths() { Some( AssetInvestmentAllocation { asset: test.token1.address.clone(), - strategy_investments: sorobanvec![&test.env, - Some(StrategyInvestment { + strategy_allocations: sorobanvec![&test.env, + Some(StrategyAllocation { strategy: test.strategy_client_token1.address.clone(), amount: 200, })] diff --git a/apps/contracts/vault/src/test/vault/rebalance.rs b/apps/contracts/vault/src/test/vault/rebalance.rs index 7e43422d..b9019fbb 100644 --- a/apps/contracts/vault/src/test/vault/rebalance.rs +++ b/apps/contracts/vault/src/test/vault/rebalance.rs @@ -2,7 +2,7 @@ use soroban_sdk::{vec as sorobanvec, InvokeError, String, Vec}; use crate::test::{ create_strategy_params_token0, defindex_vault::{ - ActionType, AssetInvestmentAllocation, AssetStrategySet, Instruction, OptionalSwapDetailsExactIn, OptionalSwapDetailsExactOut, StrategyInvestment + ActionType, AssetInvestmentAllocation, AssetStrategySet, Instruction, OptionalSwapDetailsExactIn, OptionalSwapDetailsExactOut, StrategyAllocation }, DeFindexVaultTest }; use crate::test::defindex_vault::ContractError; @@ -56,9 +56,9 @@ fn multi_instructions() { &test.env, Some(AssetInvestmentAllocation { asset: test.token0.address.clone(), - strategy_investments: sorobanvec![ + strategy_allocations: sorobanvec![ &test.env, - Some(StrategyInvestment { + Some(StrategyAllocation { strategy: test.strategy_client_token0.address.clone(), amount: amount, }), @@ -149,9 +149,9 @@ fn one_instruction() { &test.env, Some(AssetInvestmentAllocation { asset: test.token0.address.clone(), - strategy_investments: sorobanvec![ + strategy_allocations: sorobanvec![ &test.env, - Some(StrategyInvestment { + Some(StrategyAllocation { strategy: test.strategy_client_token0.address.clone(), amount: amount, }), diff --git a/apps/contracts/vault/src/test/vault/withdraw.rs b/apps/contracts/vault/src/test/vault/withdraw.rs index 0e596d65..5377b412 100644 --- a/apps/contracts/vault/src/test/vault/withdraw.rs +++ b/apps/contracts/vault/src/test/vault/withdraw.rs @@ -6,7 +6,7 @@ use crate::test::{ defindex_vault::{ AssetStrategySet, AssetInvestmentAllocation, - StrategyInvestment, + StrategyAllocation, ContractError }, DeFindexVaultTest, @@ -251,9 +251,9 @@ fn withdraw_from_strategy_success() { &test.env, Some(AssetInvestmentAllocation { asset: test.token0.address.clone(), - strategy_investments: sorobanvec![ + strategy_allocations: sorobanvec![ &test.env, - Some(StrategyInvestment { + Some(StrategyAllocation { strategy: test.strategy_client_token0.address.clone(), amount: amount, }), diff --git a/apps/contracts/vault/src/token/balance.rs b/apps/contracts/vault/src/token/balance.rs index f91b706c..4398b08f 100644 --- a/apps/contracts/vault/src/token/balance.rs +++ b/apps/contracts/vault/src/token/balance.rs @@ -1,5 +1,6 @@ use crate::token::storage_types::{DataKey, BALANCE_BUMP_AMOUNT, BALANCE_LIFETIME_THRESHOLD}; -use soroban_sdk::{Address, Env}; +use crate::ContractError; +use soroban_sdk::{Address, Env, panic_with_error}; pub fn read_balance(e: &Env, addr: Address) -> i128 { let key = DataKey::Balance(addr); @@ -34,7 +35,7 @@ pub fn receive_balance(e: &Env, addr: Address, amount: i128) { pub fn spend_balance(e: &Env, addr: Address, amount: i128) { let balance = read_balance(e, addr.clone()); if balance < amount { - panic!("insufficient balance"); + panic_with_error!(&e, ContractError::InsufficientBalance); } write_balance(e, addr, balance - amount); } diff --git a/apps/contracts/vault/src/token/contract.rs b/apps/contracts/vault/src/token/contract.rs index 430cf746..76412504 100644 --- a/apps/contracts/vault/src/token/contract.rs +++ b/apps/contracts/vault/src/token/contract.rs @@ -11,6 +11,7 @@ use crate::token::storage_types::{INSTANCE_BUMP_AMOUNT, INSTANCE_LIFETIME_THRESH use soroban_sdk::token::{self, Interface as _}; use soroban_sdk::{contract, contractimpl, Address, Env, String}; use soroban_token_sdk::TokenUtils; +use crate::ContractError; fn check_nonnegative_amount(amount: i128) { if amount < 0 { From af3bb7c250d182dc032905d6b5b401019edf43af Mon Sep 17 00:00:00 2001 From: esteblock Date: Wed, 4 Dec 2024 13:24:53 -0300 Subject: [PATCH 21/28] strategy_address naming --- apps/contracts/vault/src/deposit.rs | 2 +- apps/contracts/vault/src/funds.rs | 2 +- apps/contracts/vault/src/lib.rs | 2 +- apps/contracts/vault/src/models.rs | 2 +- .../contracts/vault/src/test/vault/deposit.rs | 12 +++--- .../src/test/vault/deposit_and_invest.rs | 12 +++--- .../src/test/vault/emergency_withdraw.rs | 2 +- apps/contracts/vault/src/test/vault/invest.rs | 42 +++++++++---------- .../vault/src/test/vault/rebalance.rs | 4 +- .../vault/src/test/vault/withdraw.rs | 2 +- 10 files changed, 41 insertions(+), 41 deletions(-) diff --git a/apps/contracts/vault/src/deposit.rs b/apps/contracts/vault/src/deposit.rs index 35ebbb9b..8cc872ff 100644 --- a/apps/contracts/vault/src/deposit.rs +++ b/apps/contracts/vault/src/deposit.rs @@ -139,7 +139,7 @@ pub fn generate_and_execute_investments( remaining_amount -= invest_amount; strategy_allocations.push_back(Some(StrategyAllocation { - strategy: strategy.address.clone(), + strategy_address: strategy.address.clone(), amount: invest_amount, })); } diff --git a/apps/contracts/vault/src/funds.rs b/apps/contracts/vault/src/funds.rs index ce3e033d..4e6a6888 100644 --- a/apps/contracts/vault/src/funds.rs +++ b/apps/contracts/vault/src/funds.rs @@ -52,7 +52,7 @@ pub fn fetch_invested_funds_for_asset(e: &Env, asset: &AssetStrategySet) -> (i12 let strategy_balance = fetch_invested_funds_for_strategy(e, &strategy.address); invested_funds += strategy_balance; strategy_allocations.push_back(StrategyAllocation { - strategy: strategy.address.clone(), + strategy_address: strategy.address.clone(), amount: strategy_balance, }); } diff --git a/apps/contracts/vault/src/lib.rs b/apps/contracts/vault/src/lib.rs index 350590f8..987ed0bf 100755 --- a/apps/contracts/vault/src/lib.rs +++ b/apps/contracts/vault/src/lib.rs @@ -304,7 +304,7 @@ impl VaultTrait for DeFindexVault { (remaining_withdrawal_amount * strategy_allocation.amount) / total_invested_amount; if strategy_withdrawal_share > 0 { - withdraw_from_strategy(&e, &strategy_allocation.strategy, &strategy_withdrawal_share)?; + withdraw_from_strategy(&e, &strategy_allocation.strategy_address, &strategy_withdrawal_share)?; TokenClient::new(&e, &asset_address).transfer( &e.current_contract_address(), &from, diff --git a/apps/contracts/vault/src/models.rs b/apps/contracts/vault/src/models.rs index 0391665b..c2f1d7b7 100644 --- a/apps/contracts/vault/src/models.rs +++ b/apps/contracts/vault/src/models.rs @@ -4,7 +4,7 @@ use soroban_sdk::{contracttype, Address, String, Vec}; #[contracttype] #[derive(Clone, Debug, Eq, PartialEq)] pub struct StrategyAllocation { - pub strategy: Address, + pub strategy_address: Address, pub amount: i128, } diff --git a/apps/contracts/vault/src/test/vault/deposit.rs b/apps/contracts/vault/src/test/vault/deposit.rs index b0d8caf2..2708a139 100644 --- a/apps/contracts/vault/src/test/vault/deposit.rs +++ b/apps/contracts/vault/src/test/vault/deposit.rs @@ -327,7 +327,7 @@ fn one_asset_success() { // construct expected total manage funds let mut total_managed_funds_expected = Map::new(&test.env); let strategy_investments_expected = sorobanvec![&test.env, StrategyAllocation { - strategy: test.strategy_client_token0.address.clone(), + strategy_address: test.strategy_client_token0.address.clone(), amount: 0, //funds has not been invested yet! }]; total_managed_funds_expected.set(test.token0.address.clone(), @@ -393,7 +393,7 @@ fn one_asset_success() { // check that fetch_total_managed_funds returns correct amount let mut total_managed_funds_expected = Map::new(&test.env); let strategy_investments_expected = sorobanvec![&test.env, StrategyAllocation { - strategy: test.strategy_client_token0.address.clone(), + strategy_address: test.strategy_client_token0.address.clone(), amount: 0, // funds have not been invested yet! }]; total_managed_funds_expected.set(test.token0.address.clone(), @@ -559,11 +559,11 @@ fn several_assets_success() { // check total managed funds let mut total_managed_funds_expected = Map::new(&test.env); let strategy_investments_expected_token_0 = sorobanvec![&test.env, StrategyAllocation { - strategy: test.strategy_client_token0.address.clone(), + strategy_address: test.strategy_client_token0.address.clone(), amount: 0, // funds have not been invested yet! }]; let strategy_investments_expected_token_1 = sorobanvec![&test.env, StrategyAllocation { - strategy: test.strategy_client_token1.address.clone(), + strategy_address: test.strategy_client_token1.address.clone(), amount: 0, // funds have not been invested yet! }]; total_managed_funds_expected.set(test.token0.address.clone(), @@ -658,11 +658,11 @@ fn several_assets_success() { // check total managed funds let mut total_managed_funds_expected = Map::new(&test.env); let strategy_investments_expected_token_0 = sorobanvec![&test.env, StrategyAllocation { - strategy: test.strategy_client_token0.address.clone(), + strategy_address: test.strategy_client_token0.address.clone(), amount: 0, // funds have not been invested yet! }]; let strategy_investments_expected_token_1 = sorobanvec![&test.env, StrategyAllocation { - strategy: test.strategy_client_token1.address.clone(), + strategy_address: test.strategy_client_token1.address.clone(), amount: 0, // funds have not been invested yet! }]; total_managed_funds_expected.set(test.token0.address.clone(), diff --git a/apps/contracts/vault/src/test/vault/deposit_and_invest.rs b/apps/contracts/vault/src/test/vault/deposit_and_invest.rs index f875930c..ba7d90e0 100644 --- a/apps/contracts/vault/src/test/vault/deposit_and_invest.rs +++ b/apps/contracts/vault/src/test/vault/deposit_and_invest.rs @@ -65,7 +65,7 @@ fn one_asset_success() { // check total managed funds let mut total_managed_funds_expected = Map::new(&test.env); let strategy_investments_expected_token_0 = sorobanvec![&test.env, StrategyAllocation { - strategy: test.strategy_client_token0.address.clone(), + strategy_address: test.strategy_client_token0.address.clone(), amount: amount, // everything has been invested }]; @@ -126,7 +126,7 @@ fn one_asset_success() { // check that fetch_total_managed_funds returns correct amount let mut total_managed_funds_expected = Map::new(&test.env); let strategy_investments_expected_token_0 = sorobanvec![&test.env, StrategyAllocation { - strategy: test.strategy_client_token0.address.clone(), + strategy_address: test.strategy_client_token0.address.clone(), amount: amount + amount2, // everything has been invested }]; @@ -238,11 +238,11 @@ fn several_assets_success() { // check that fetch_total_managed_funds returns correct amount let mut total_managed_funds_expected = Map::new(&test.env); let strategy_investments_expected_token_0 = sorobanvec![&test.env, StrategyAllocation { - strategy: test.strategy_client_token0.address.clone(), + strategy_address: test.strategy_client_token0.address.clone(), amount: amount0, // everything has been invested }]; let strategy_investments_expected_token_1 = sorobanvec![&test.env, StrategyAllocation { - strategy: test.strategy_client_token1.address.clone(), + strategy_address: test.strategy_client_token1.address.clone(), amount: amount1, // everything has been invested }]; total_managed_funds_expected.set(test.token0.address.clone(), @@ -330,11 +330,11 @@ fn several_assets_success() { // check that fetch_total_managed_funds returns correct amount let mut total_managed_funds_expected = Map::new(&test.env); let strategy_investments_expected_token_0 = sorobanvec![&test.env, StrategyAllocation { - strategy: test.strategy_client_token0.address.clone(), + strategy_address: test.strategy_client_token0.address.clone(), amount: amount0*3, // everything has been invested }]; let strategy_investments_expected_token_1 = sorobanvec![&test.env, StrategyAllocation { - strategy: test.strategy_client_token1.address.clone(), + strategy_address: test.strategy_client_token1.address.clone(), amount: amount1*3, // everything has been invested }]; total_managed_funds_expected.set(test.token0.address.clone(), diff --git a/apps/contracts/vault/src/test/vault/emergency_withdraw.rs b/apps/contracts/vault/src/test/vault/emergency_withdraw.rs index f75f7d88..7c308f9a 100644 --- a/apps/contracts/vault/src/test/vault/emergency_withdraw.rs +++ b/apps/contracts/vault/src/test/vault/emergency_withdraw.rs @@ -66,7 +66,7 @@ fn withdraw_success() { strategy_allocations: sorobanvec![ &test.env, Some(StrategyAllocation { - strategy: test.strategy_client_token0.address.clone(), + strategy_address: test.strategy_client_token0.address.clone(), amount: amount, }), ], diff --git a/apps/contracts/vault/src/test/vault/invest.rs b/apps/contracts/vault/src/test/vault/invest.rs index 89968274..dddf4a95 100644 --- a/apps/contracts/vault/src/test/vault/invest.rs +++ b/apps/contracts/vault/src/test/vault/invest.rs @@ -27,7 +27,7 @@ fn not_yet_initialized() { strategy_allocations: vec![ &test.env, Some(StrategyAllocation { - strategy: test.strategy_client_token0.address.clone(), + strategy_address: test.strategy_client_token0.address.clone(), amount: 100, })], })]; @@ -80,7 +80,7 @@ fn wrong_asset_investment_length() { strategy_allocations: vec![ &test.env, Some(StrategyAllocation { - strategy: test.strategy_client_token0.address.clone(), + strategy_address: test.strategy_client_token0.address.clone(), amount: 100, })], }) // First Asset @@ -102,7 +102,7 @@ fn wrong_asset_investment_length() { strategy_allocations: vec![ &test.env, Some(StrategyAllocation { - strategy: test.strategy_client_token0.address.clone(), + strategy_address: test.strategy_client_token0.address.clone(), amount: 100, }) ], @@ -171,11 +171,11 @@ fn wrong_strategy_length() { strategy_allocations: vec![ &test.env, Some(StrategyAllocation { - strategy: test.strategy_client_token0.address.clone(), + strategy_address: test.strategy_client_token0.address.clone(), amount: 100, }), Some(StrategyAllocation { - strategy: test.strategy_client_token1.address.clone(), + strategy_address: test.strategy_client_token1.address.clone(), amount: 100, }), ], @@ -204,7 +204,7 @@ fn wrong_strategy_length() { strategy_allocations: vec![ &test.env, Some(StrategyAllocation { - strategy: test.strategy_client_token1.address.clone(), + strategy_address: test.strategy_client_token1.address.clone(), amount: 100, }), None @@ -263,7 +263,7 @@ fn wrong_asset_address() { strategy_allocations: vec![ &test.env, Some(StrategyAllocation { - strategy: test.strategy_client_token0.address.clone(), + strategy_address: test.strategy_client_token0.address.clone(), amount: 100, }), ], @@ -320,7 +320,7 @@ fn negative_amount() { strategy_allocations: vec![ &test.env, Some(StrategyAllocation { - strategy: test.strategy_client_token0.address.clone(), + strategy_address: test.strategy_client_token0.address.clone(), amount: -100, // negative amount }), ], @@ -377,7 +377,7 @@ fn paused_strategy() { strategy_allocations: vec![ &test.env, Some(StrategyAllocation { - strategy: test.strategy_client_token0.address.clone(), + strategy_address: test.strategy_client_token0.address.clone(), amount: 100, }), ], @@ -464,11 +464,11 @@ fn in_strategy() { let mut total_managed_funds_expected = Map::new(&test.env); let strategy_investments_expected_token_0 = sorobanvec![&test.env, StrategyAllocation { - strategy: test.strategy_client_token0.address.clone(), + strategy_address: test.strategy_client_token0.address.clone(), amount: 0, // funds have not been invested yet! }]; let strategy_investments_expected_token_1 = sorobanvec![&test.env, StrategyAllocation { - strategy: test.strategy_client_token1.address.clone(), + strategy_address: test.strategy_client_token1.address.clone(), amount: 0, // funds have not been invested yet! }]; total_managed_funds_expected.set(test.token0.address.clone(), @@ -516,7 +516,7 @@ fn in_strategy() { strategy_allocations: vec![ &test.env, Some(StrategyAllocation { - strategy: test.strategy_client_token0.address.clone(), + strategy_address: test.strategy_client_token0.address.clone(), amount: 100, }), ], @@ -526,7 +526,7 @@ fn in_strategy() { strategy_allocations: vec![ &test.env, Some(StrategyAllocation { - strategy: test.strategy_client_token1.address.clone(), + strategy_address: test.strategy_client_token1.address.clone(), amount: 200, }), ], @@ -545,11 +545,11 @@ fn in_strategy() { // check total managed funds let mut total_managed_funds_expected = Map::new(&test.env); let strategy_investments_expected_token_0 = sorobanvec![&test.env, StrategyAllocation { - strategy: test.strategy_client_token0.address.clone(), + strategy_address: test.strategy_client_token0.address.clone(), amount: 100, }]; let strategy_investments_expected_token_1 = sorobanvec![&test.env, StrategyAllocation { - strategy: test.strategy_client_token1.address.clone(), + strategy_address: test.strategy_client_token1.address.clone(), amount: 200, }]; total_managed_funds_expected.set(test.token0.address.clone(), @@ -676,7 +676,7 @@ fn more_than_idle_funds() { strategy_allocations: vec![ &test.env, Some(StrategyAllocation { - strategy: test.strategy_client_token0.address.clone(), + strategy_address: test.strategy_client_token0.address.clone(), amount: vault_balance_0 + 1, }), ], @@ -686,7 +686,7 @@ fn more_than_idle_funds() { strategy_allocations: vec![ &test.env, Some(StrategyAllocation { - strategy: test.strategy_client_token1.address.clone(), + strategy_address: test.strategy_client_token1.address.clone(), amount: vault_balance_1 + 1, }), ], @@ -831,7 +831,7 @@ fn without_mock_all_auths() { strategy_allocations: sorobanvec![&test.env, Some(StrategyAllocation { - strategy: test.strategy_client_token0.address.clone(), + strategy_address: test.strategy_client_token0.address.clone(), amount: 100, })] } @@ -841,7 +841,7 @@ fn without_mock_all_auths() { asset: test.token1.address.clone(), strategy_allocations: sorobanvec![&test.env, Some(StrategyAllocation { - strategy: test.strategy_client_token1.address.clone(), + strategy_address: test.strategy_client_token1.address.clone(), amount: 200, })] } @@ -857,7 +857,7 @@ fn without_mock_all_auths() { asset: test.token0.address.clone(), strategy_allocations: sorobanvec![&test.env, Some(StrategyAllocation { - strategy: test.strategy_client_token0.address.clone(), + strategy_address: test.strategy_client_token0.address.clone(), amount: 100, })] } @@ -867,7 +867,7 @@ fn without_mock_all_auths() { asset: test.token1.address.clone(), strategy_allocations: sorobanvec![&test.env, Some(StrategyAllocation { - strategy: test.strategy_client_token1.address.clone(), + strategy_address: test.strategy_client_token1.address.clone(), amount: 200, })] } diff --git a/apps/contracts/vault/src/test/vault/rebalance.rs b/apps/contracts/vault/src/test/vault/rebalance.rs index b9019fbb..c7fb3814 100644 --- a/apps/contracts/vault/src/test/vault/rebalance.rs +++ b/apps/contracts/vault/src/test/vault/rebalance.rs @@ -59,7 +59,7 @@ fn multi_instructions() { strategy_allocations: sorobanvec![ &test.env, Some(StrategyAllocation { - strategy: test.strategy_client_token0.address.clone(), + strategy_address: test.strategy_client_token0.address.clone(), amount: amount, }), ], @@ -152,7 +152,7 @@ fn one_instruction() { strategy_allocations: sorobanvec![ &test.env, Some(StrategyAllocation { - strategy: test.strategy_client_token0.address.clone(), + strategy_address: test.strategy_client_token0.address.clone(), amount: amount, }), ], diff --git a/apps/contracts/vault/src/test/vault/withdraw.rs b/apps/contracts/vault/src/test/vault/withdraw.rs index 5377b412..1d810388 100644 --- a/apps/contracts/vault/src/test/vault/withdraw.rs +++ b/apps/contracts/vault/src/test/vault/withdraw.rs @@ -254,7 +254,7 @@ fn withdraw_from_strategy_success() { strategy_allocations: sorobanvec![ &test.env, Some(StrategyAllocation { - strategy: test.strategy_client_token0.address.clone(), + strategy_address: test.strategy_client_token0.address.clone(), amount: amount, }), ], From 057e8725e04fbdecaa0770d8b54f7764d3caa7b0 Mon Sep 17 00:00:00 2001 From: esteblock Date: Wed, 4 Dec 2024 16:03:08 -0300 Subject: [PATCH 22/28] updated docs --- apps/contracts/vault/src/funds.rs | 23 - apps/rust_docs/crates.js | 3 +- apps/rust_docs/defindex_factory/all.html | 2 +- .../defindex_factory/fn.create_contract.html | 5 + apps/rust_docs/defindex_factory/index.html | 2 +- .../defindex_factory/sidebar-items.js | 2 +- .../struct.DeFindexFactoryClient.html | 298 ++++--- .../defindex_factory/trait.FactoryTrait.html | 143 ++- .../vault/fn.create_contract.html | 11 + .../rust_docs/defindex_strategy_core/all.html | 2 +- .../enum.StrategyError.html | 134 +-- .../event/fn.emit_deposit.html | 2 +- .../event/fn.emit_harvest.html | 2 +- .../event/fn.emit_initialize.html | 2 +- .../event/fn.emit_withdraw.html | 6 +- .../defindex_strategy_core/event/index.html | 4 +- .../static.__SPEC_XDR_TYPE_DEPOSITEVENT.html | 2 +- .../static.__SPEC_XDR_TYPE_HARVESTEVENT.html | 2 +- ...atic.__SPEC_XDR_TYPE_INITIALIZEDEVENT.html | 2 +- .../static.__SPEC_XDR_TYPE_WITHDRAWEVENT.html | 2 +- .../event/struct.DepositEvent.html | 118 +-- .../event/struct.HarvestEvent.html | 118 +-- .../event/struct.InitializedEvent.html | 120 +-- .../event/struct.WithdrawEvent.html | 118 +-- .../defindex_strategy_core/index.html | 4 +- .../struct.DeFindexStrategyClient.html | 146 ++-- .../defindex_strategy_core/struct.Spec.html | 118 +-- .../trait.DeFindexStrategyTrait.html | 50 +- apps/rust_docs/defindex_vault/all.html | 2 +- .../defindex_vault/enum.ContractError.html | 150 ++-- apps/rust_docs/defindex_vault/index.html | 2 +- .../defindex_vault/struct.DeFindexVault.html | 297 ++++--- .../struct.DeFindexVaultClient.html | 621 ++++++++----- apps/rust_docs/help.html | 2 +- apps/rust_docs/search-index.js | 7 +- .../defindex_factory-desc-0-.js | 2 +- .../defindex_vault/defindex_vault-desc-0-.js | 2 +- apps/rust_docs/settings.html | 2 +- apps/rust_docs/src-files.js | 7 +- .../src/defindex_factory/error.rs.html | 4 +- .../src/defindex_factory/events.rs.html | 32 +- .../src/defindex_factory/lib.rs.html | 312 ++++++- .../src/defindex_factory/storage.rs.html | 10 +- .../src/defindex_factory/vault.rs.html | 28 + .../src/defindex_strategy_core/error.rs.html | 4 +- .../src/defindex_strategy_core/event.rs.html | 2 +- .../src/defindex_strategy_core/lib.rs.html | 2 +- .../src/defindex_vault/access.rs.html | 18 +- .../src/defindex_vault/aggregator.rs.html | 173 ++++ .../src/defindex_vault/constants.rs.html | 5 +- .../src/defindex_vault/deposit.rs.html | 311 +++++++ .../src/defindex_vault/error.rs.html | 34 +- .../src/defindex_vault/events.rs.html | 45 +- apps/rust_docs/src/defindex_vault/fee.rs.html | 167 ++-- .../src/defindex_vault/funds.rs.html | 100 ++- .../src/defindex_vault/interface.rs.html | 269 ++++-- .../src/defindex_vault/investment.rs.html | 184 +++- apps/rust_docs/src/defindex_vault/lib.rs.html | 813 +++++++++++++----- .../src/defindex_vault/models.rs.html | 167 +++- .../src/defindex_vault/storage.rs.html | 92 +- .../src/defindex_vault/strategies.rs.html | 169 +++- .../defindex_vault/token/allowance.rs.html | 2 +- .../src/defindex_vault/token/balance.rs.html | 8 +- .../src/defindex_vault/token/contract.rs.html | 16 +- .../src/defindex_vault/token/metadata.rs.html | 2 +- .../src/defindex_vault/token/mod.rs.html | 6 +- .../token/storage_types.rs.html | 2 +- .../defindex_vault/token/total_supply.rs.html | 2 +- .../src/defindex_vault/utils.rs.html | 353 ++++---- .../static.files/main-921df33f47b8780c.js | 11 + .../noscript-3b12f09e550e0385.css | 1 + .../static.files/rustdoc-492a78a4a87dcc01.css | 47 + .../static.files/search-a99f1315e7cc5121.js | 5 + .../static.files/storage-118b08c4c78b968e.js | 24 + .../trait.impl/core/clone/trait.Clone.js | 13 +- .../rust_docs/trait.impl/core/cmp/trait.Eq.js | 13 +- .../trait.impl/core/cmp/trait.Ord.js | 13 +- .../trait.impl/core/cmp/trait.PartialEq.js | 13 +- .../trait.impl/core/cmp/trait.PartialOrd.js | 13 +- .../trait.impl/core/convert/trait.From.js | 13 +- .../trait.impl/core/convert/trait.TryFrom.js | 13 +- .../trait.impl/core/fmt/trait.Debug.js | 13 +- .../trait.impl/core/marker/trait.Copy.js | 13 +- .../trait.impl/core/marker/trait.Freeze.js | 14 +- .../trait.impl/core/marker/trait.Send.js | 14 +- .../core/marker/trait.StructuralPartialEq.js | 13 +- .../trait.impl/core/marker/trait.Sync.js | 14 +- .../trait.impl/core/marker/trait.Unpin.js | 14 +- .../panic/unwind_safe/trait.RefUnwindSafe.js | 14 +- .../panic/unwind_safe/trait.UnwindSafe.js | 14 +- .../convert/trait.TryFromVal.js | 13 +- 91 files changed, 4243 insertions(+), 1939 deletions(-) create mode 100644 apps/rust_docs/defindex_factory/fn.create_contract.html create mode 100644 apps/rust_docs/defindex_factory/vault/fn.create_contract.html create mode 100644 apps/rust_docs/src/defindex_factory/vault.rs.html create mode 100644 apps/rust_docs/src/defindex_vault/aggregator.rs.html create mode 100644 apps/rust_docs/src/defindex_vault/deposit.rs.html create mode 100644 apps/rust_docs/static.files/main-921df33f47b8780c.js create mode 100644 apps/rust_docs/static.files/noscript-3b12f09e550e0385.css create mode 100644 apps/rust_docs/static.files/rustdoc-492a78a4a87dcc01.css create mode 100644 apps/rust_docs/static.files/search-a99f1315e7cc5121.js create mode 100644 apps/rust_docs/static.files/storage-118b08c4c78b968e.js diff --git a/apps/contracts/vault/src/funds.rs b/apps/contracts/vault/src/funds.rs index 4e6a6888..5ef9e210 100644 --- a/apps/contracts/vault/src/funds.rs +++ b/apps/contracts/vault/src/funds.rs @@ -6,8 +6,6 @@ use crate::models::{StrategyAllocation, CurrentAssetInvestmentAllocation}; use crate::storage::get_assets; use crate::strategies::get_strategy_client; -// Funds for AssetStrategySet - /// Fetches the idle funds for a given asset. Idle funds refer to the balance of the asset /// that is currently not invested in any strategies. /// @@ -35,14 +33,6 @@ pub fn fetch_invested_funds_for_strategy(e: &Env, strategy_address: &Address) -> strategy_client.balance(&e.current_contract_address()) } -// // Investment Allocation in Strategies -// #[contracttype] -// #[derive(Clone, Debug, Eq, PartialEq)] -// pub struct StrategyAllocation { -// pub strategy: Address, -// pub amount: i128, -// } - // return total invested funds but also a vec of StrategyAllocation pub fn fetch_invested_funds_for_asset(e: &Env, asset: &AssetStrategySet) -> (i128, Vec){ @@ -59,7 +49,6 @@ pub fn fetch_invested_funds_for_asset(e: &Env, asset: &AssetStrategySet) -> (i12 (invested_funds, strategy_allocations) } -// Pub functions /// Fetches the current idle funds for all assets managed by the contract. /// It returns a map where the key is the asset's address and the value is the idle balance. @@ -108,18 +97,6 @@ pub fn fetch_current_invested_funds(e: &Env) -> Map { /// /// # Returns /// * A map where each entry represents an asset's address and its total managed balance. - - -// // Current Asset Investment Allocation -// #[contracttype] -// #[derive(Clone, Debug, Eq, PartialEq)] -// pub struct CurrentAssetInvestmentAllocation { -// pub asset: Address, -// pub total_amount: i128, -// pub idle_amount: i128, -// pub invested_amount: i128, -// pub strategy_allocations: Vec, -// } pub fn fetch_total_managed_funds(e: &Env) -> Map { let assets = get_assets(e); let mut map: Map = Map::new(e); diff --git a/apps/rust_docs/crates.js b/apps/rust_docs/crates.js index 5b4ba40e..302e16cf 100644 --- a/apps/rust_docs/crates.js +++ b/apps/rust_docs/crates.js @@ -1 +1,2 @@ -window.ALL_CRATES = ["defindex_factory","defindex_strategy_core","defindex_vault"]; \ No newline at end of file +window.ALL_CRATES = ["defindex_factory","defindex_strategy_core","defindex_vault"]; +//{"start":21,"fragment_lengths":[18,25,17]} \ No newline at end of file diff --git a/apps/rust_docs/defindex_factory/all.html b/apps/rust_docs/defindex_factory/all.html index ec979cb2..6b6db82c 100644 --- a/apps/rust_docs/defindex_factory/all.html +++ b/apps/rust_docs/defindex_factory/all.html @@ -1 +1 @@ -List of all items in this crate

List of all items

Structs

Traits

\ No newline at end of file +List of all items in this crate

List of all items

Structs

Traits

Functions

\ No newline at end of file diff --git a/apps/rust_docs/defindex_factory/fn.create_contract.html b/apps/rust_docs/defindex_factory/fn.create_contract.html new file mode 100644 index 00000000..a72df57b --- /dev/null +++ b/apps/rust_docs/defindex_factory/fn.create_contract.html @@ -0,0 +1,5 @@ +create_contract in defindex_factory - Rust

Function defindex_factory::create_contract

source ·
pub fn create_contract(
+    e: &Env,
+    defindex_wasm_hash: BytesN<32>,
+    salt: BytesN<32>,
+) -> Address
\ No newline at end of file diff --git a/apps/rust_docs/defindex_factory/index.html b/apps/rust_docs/defindex_factory/index.html index f8d5eafe..80789233 100644 --- a/apps/rust_docs/defindex_factory/index.html +++ b/apps/rust_docs/defindex_factory/index.html @@ -1 +1 @@ -defindex_factory - Rust

Crate defindex_factory

source ·

Structs§

  • DeFindexFactoryClient is a client for calling the contract defined in “DeFindexFactory”.

Traits§

\ No newline at end of file +defindex_factory - Rust

Crate defindex_factory

source ·

Structs§

  • DeFindexFactoryClient is a client for calling the contract defined in “DeFindexFactory”.

Traits§

Functions§

\ No newline at end of file diff --git a/apps/rust_docs/defindex_factory/sidebar-items.js b/apps/rust_docs/defindex_factory/sidebar-items.js index 37693339..a2e4bb15 100644 --- a/apps/rust_docs/defindex_factory/sidebar-items.js +++ b/apps/rust_docs/defindex_factory/sidebar-items.js @@ -1 +1 @@ -window.SIDEBAR_ITEMS = {"struct":["DeFindexFactoryClient"],"trait":["FactoryTrait"]}; \ No newline at end of file +window.SIDEBAR_ITEMS = {"fn":["create_contract"],"struct":["DeFindexFactoryClient"],"trait":["FactoryTrait"]}; \ No newline at end of file diff --git a/apps/rust_docs/defindex_factory/struct.DeFindexFactoryClient.html b/apps/rust_docs/defindex_factory/struct.DeFindexFactoryClient.html index 0b6cb69c..5d660999 100644 --- a/apps/rust_docs/defindex_factory/struct.DeFindexFactoryClient.html +++ b/apps/rust_docs/defindex_factory/struct.DeFindexFactoryClient.html @@ -1,300 +1,364 @@ -DeFindexFactoryClient in defindex_factory - Rust

Struct defindex_factory::DeFindexFactoryClient

source ·
pub struct DeFindexFactoryClient<'a> {
+DeFindexFactoryClient in defindex_factory - Rust

Struct defindex_factory::DeFindexFactoryClient

source ·
pub struct DeFindexFactoryClient<'a> {
     pub env: Env,
     pub address: Address,
     /* private fields */
 }
Expand description

DeFindexFactoryClient is a client for calling the contract defined in “DeFindexFactory”.

-

Fields§

§env: Env§address: Address

Implementations§

source§

impl<'a> DeFindexFactoryClient<'a>

source

pub fn new(env: &Env, address: &Address) -> Self

source§

impl<'a> DeFindexFactoryClient<'a>

Fields§

§env: Env§address: Address

Implementations§

source§

impl<'a> DeFindexFactoryClient<'a>

source

pub fn new(env: &Env, address: &Address) -> Self

source§

impl<'a> DeFindexFactoryClient<'a>

source

pub fn initialize( &self, admin: &Address, defindex_receiver: &Address, - fee_rate: &u32, - defi_wasm_hash: &BytesN<32> + defindex_fee: &u32, + vault_wasm_hash: &BytesN<32>, )

Initializes the factory contract with the given parameters.

§Arguments
  • e - The environment in which the contract is running.
  • admin - The address of the contract administrator, who can manage settings.
  • defindex_receiver - The default address designated to receive a portion of fees.
  • -
  • fee_rate - The initial annual fee rate (in basis points).
  • -
  • defindex_wasm_hash - The hash of the DeFindex Vault’s WASM file for deploying new vaults.
  • +
  • defindex_fee - The initial annual fee rate (in basis points).
  • +
  • vault_wasm_hash - The hash of the DeFindex Vault’s WASM file for deploying new vaults.
§Returns
  • Result<(), FactoryError> - Returns Ok(()) if successful, otherwise an error.
-
source

pub fn try_initialize( +

source

pub fn try_initialize( &self, admin: &Address, defindex_receiver: &Address, - fee_rate: &u32, - defi_wasm_hash: &BytesN<32> -) -> Result<Result<(), <() as TryFromVal<Env, Val>>::Error>, Result<FactoryError, InvokeError>>

Initializes the factory contract with the given parameters.

+ defindex_fee: &u32, + vault_wasm_hash: &BytesN<32>, +) -> Result<Result<(), <() as TryFromVal<Env, Val>>::Error>, Result<FactoryError, InvokeError>>

Initializes the factory contract with the given parameters.

§Arguments
  • e - The environment in which the contract is running.
  • admin - The address of the contract administrator, who can manage settings.
  • defindex_receiver - The default address designated to receive a portion of fees.
  • -
  • fee_rate - The initial annual fee rate (in basis points).
  • -
  • defindex_wasm_hash - The hash of the DeFindex Vault’s WASM file for deploying new vaults.
  • +
  • defindex_fee - The initial annual fee rate (in basis points).
  • +
  • vault_wasm_hash - The hash of the DeFindex Vault’s WASM file for deploying new vaults.
§Returns
  • Result<(), FactoryError> - Returns Ok(()) if successful, otherwise an error.
-
source

pub fn create_defindex_vault( +

source

pub fn create_defindex_vault( &self, emergency_manager: &Address, fee_receiver: &Address, - vault_share: &u32, + vault_fee: &u32, + vault_name: &String, + vault_symbol: &String, manager: &Address, - assets: &Vec<AssetAllocation>, - salt: &BytesN<32> + assets: &Vec<AssetStrategySet>, + salt: &BytesN<32>, ) -> Address

Creates a new DeFindex Vault with specified parameters.

§Arguments
  • e - The environment in which the contract is running.
  • emergency_manager - The address assigned emergency control over the vault.
  • fee_receiver - The address designated to receive fees from the vault.
  • -
  • vault_share - The percentage share of fees allocated to the vault’s fee receiver.
  • +
  • vault_fee - The percentage share of fees allocated to the vault’s fee receiver.
  • manager - The address assigned as the vault manager.
  • -
  • assets - A vector of AssetAllocation structs that define the assets managed by the vault.
  • +
  • assets - A vector of AssetStrategySet structs that define the assets managed by the vault.
  • salt - A salt used for ensuring unique addresses for each deployed vault.
§Returns
  • Result<Address, FactoryError> - Returns the address of the new vault, or an error if unsuccessful.
-
source

pub fn try_create_defindex_vault( +

source

pub fn try_create_defindex_vault( &self, emergency_manager: &Address, fee_receiver: &Address, - vault_share: &u32, + vault_fee: &u32, + vault_name: &String, + vault_symbol: &String, manager: &Address, - assets: &Vec<AssetAllocation>, - salt: &BytesN<32> -) -> Result<Result<Address, <Address as TryFromVal<Env, Val>>::Error>, Result<FactoryError, InvokeError>>

Creates a new DeFindex Vault with specified parameters.

+ assets: &Vec<AssetStrategySet>, + salt: &BytesN<32>, +) -> Result<Result<Address, <Address as TryFromVal<Env, Val>>::Error>, Result<FactoryError, InvokeError>>

Creates a new DeFindex Vault with specified parameters.

§Arguments
  • e - The environment in which the contract is running.
  • emergency_manager - The address assigned emergency control over the vault.
  • fee_receiver - The address designated to receive fees from the vault.
  • -
  • vault_share - The percentage share of fees allocated to the vault’s fee receiver.
  • +
  • vault_fee - The percentage share of fees allocated to the vault’s fee receiver.
  • manager - The address assigned as the vault manager.
  • -
  • assets - A vector of AssetAllocation structs that define the assets managed by the vault.
  • +
  • assets - A vector of AssetStrategySet structs that define the assets managed by the vault.
  • salt - A salt used for ensuring unique addresses for each deployed vault.
§Returns
  • Result<Address, FactoryError> - Returns the address of the new vault, or an error if unsuccessful.
-
source

pub fn set_new_admin(&self, new_admin: &Address)

Sets a new admin address.

+
source

pub fn create_defindex_vault_deposit( + &self, + caller: &Address, + emergency_manager: &Address, + fee_receiver: &Address, + vault_fee: &u32, + vault_name: &String, + vault_symbol: &String, + manager: &Address, + assets: &Vec<AssetStrategySet>, + amounts: &Vec<i128>, + salt: &BytesN<32>, +) -> Address

Creates a new DeFindex Vault with specified parameters and makes the first deposit to set ratios.

§Arguments
  • e - The environment in which the contract is running.
  • -
  • new_admin - The new administrator’s address.
  • +
  • emergency_manager - The address assigned emergency control over the vault.
  • +
  • fee_receiver - The address designated to receive fees from the vault.
  • +
  • vault_fee - The percentage share of fees allocated to the vault’s fee receiver.
  • +
  • vault_name - The name of the vault.
  • +
  • vault_symbol - The symbol of the vault.
  • +
  • manager - The address assigned as the vault manager.
  • +
  • assets - A vector of AssetStrategySet structs that define the assets managed by the vault.
  • +
  • amounts - A vector of AssetAmounts structs that define the initial deposit amounts.
  • +
  • salt - A salt used for ensuring unique addresses for each deployed vault.
§Returns
    -
  • Result<(), FactoryError> - Returns Ok(()) if successful, or an error if not authorized.
  • +
  • Result<Address, FactoryError> - Returns the address of the new vault, or an error if unsuccessful.
-
source

pub fn try_set_new_admin( +

source

pub fn try_create_defindex_vault_deposit( &self, - new_admin: &Address -) -> Result<Result<(), <() as TryFromVal<Env, Val>>::Error>, Result<FactoryError, InvokeError>>

Sets a new admin address.

+ caller: &Address, + emergency_manager: &Address, + fee_receiver: &Address, + vault_fee: &u32, + vault_name: &String, + vault_symbol: &String, + manager: &Address, + assets: &Vec<AssetStrategySet>, + amounts: &Vec<i128>, + salt: &BytesN<32>, +) -> Result<Result<Address, <Address as TryFromVal<Env, Val>>::Error>, Result<FactoryError, InvokeError>>

Creates a new DeFindex Vault with specified parameters and makes the first deposit to set ratios.

§Arguments
  • e - The environment in which the contract is running.
  • -
  • new_admin - The new administrator’s address.
  • +
  • emergency_manager - The address assigned emergency control over the vault.
  • +
  • fee_receiver - The address designated to receive fees from the vault.
  • +
  • vault_fee - The percentage share of fees allocated to the vault’s fee receiver.
  • +
  • vault_name - The name of the vault.
  • +
  • vault_symbol - The symbol of the vault.
  • +
  • manager - The address assigned as the vault manager.
  • +
  • assets - A vector of AssetStrategySet structs that define the assets managed by the vault.
  • +
  • amounts - A vector of AssetAmounts structs that define the initial deposit amounts.
  • +
  • salt - A salt used for ensuring unique addresses for each deployed vault.
§Returns
    -
  • Result<(), FactoryError> - Returns Ok(()) if successful, or an error if not authorized.
  • +
  • Result<Address, FactoryError> - Returns the address of the new vault, or an error if unsuccessful.
-
source

pub fn set_defindex_receiver(&self, new_fee_receiver: &Address)

Updates the default receiver address for the DeFindex portion of fees.

+
source

pub fn set_new_admin(&self, new_admin: &Address)

Sets a new admin address.

§Arguments
  • e - The environment in which the contract is running.
  • -
  • new_fee_receiver - The address of the new fee receiver.
  • +
  • new_admin - The new administrator’s address.
§Returns
  • Result<(), FactoryError> - Returns Ok(()) if successful, or an error if not authorized.
-
source

pub fn try_set_defindex_receiver( +

source

pub fn try_set_new_admin( &self, - new_fee_receiver: &Address -) -> Result<Result<(), <() as TryFromVal<Env, Val>>::Error>, Result<FactoryError, InvokeError>>

Updates the default receiver address for the DeFindex portion of fees.

+ new_admin: &Address, +) -> Result<Result<(), <() as TryFromVal<Env, Val>>::Error>, Result<FactoryError, InvokeError>>

Sets a new admin address.

§Arguments
  • e - The environment in which the contract is running.
  • -
  • new_fee_receiver - The address of the new fee receiver.
  • +
  • new_admin - The new administrator’s address.
§Returns
  • Result<(), FactoryError> - Returns Ok(()) if successful, or an error if not authorized.
-
source

pub fn set_fee_rate(&self, fee_rate: &u32)

Updates the default fee rate for new vaults.

+
source

pub fn set_defindex_receiver(&self, new_fee_receiver: &Address)

Updates the default receiver address for the DeFindex portion of fees.

§Arguments
  • e - The environment in which the contract is running.
  • -
  • new_fee_rate - The new annual fee rate in basis points.
  • +
  • new_fee_receiver - The address of the new fee receiver.
§Returns
  • Result<(), FactoryError> - Returns Ok(()) if successful, or an error if not authorized.
-
source

pub fn try_set_fee_rate( +

source

pub fn try_set_defindex_receiver( &self, - fee_rate: &u32 -) -> Result<Result<(), <() as TryFromVal<Env, Val>>::Error>, Result<FactoryError, InvokeError>>

Updates the default fee rate for new vaults.

+ new_fee_receiver: &Address, +) -> Result<Result<(), <() as TryFromVal<Env, Val>>::Error>, Result<FactoryError, InvokeError>>

Updates the default receiver address for the DeFindex portion of fees.

§Arguments
  • e - The environment in which the contract is running.
  • -
  • new_fee_rate - The new annual fee rate in basis points.
  • +
  • new_fee_receiver - The address of the new fee receiver.
§Returns
  • Result<(), FactoryError> - Returns Ok(()) if successful, or an error if not authorized.
-
source

pub fn admin(&self) -> Address

Retrieves the current admin’s address.

+
source

pub fn set_defindex_fee(&self, defindex_fee: &u32)

Updates the default fee rate for new vaults.

§Arguments
  • e - The environment in which the contract is running.
  • +
  • new_fee_rate - The new annual fee rate in basis points.
§Returns
    -
  • Result<Address, FactoryError> - Returns the admin’s address or an error if not found.
  • +
  • Result<(), FactoryError> - Returns Ok(()) if successful, or an error if not authorized.
-
source

pub fn try_admin( - &self -) -> Result<Result<Address, <Address as TryFromVal<Env, Val>>::Error>, Result<FactoryError, InvokeError>>

Retrieves the current admin’s address.

+
source

pub fn try_set_defindex_fee( + &self, + defindex_fee: &u32, +) -> Result<Result<(), <() as TryFromVal<Env, Val>>::Error>, Result<FactoryError, InvokeError>>

Updates the default fee rate for new vaults.

§Arguments
  • e - The environment in which the contract is running.
  • +
  • new_fee_rate - The new annual fee rate in basis points.
§Returns
    -
  • Result<Address, FactoryError> - Returns the admin’s address or an error if not found.
  • +
  • Result<(), FactoryError> - Returns Ok(()) if successful, or an error if not authorized.
-
source

pub fn defindex_receiver(&self) -> Address

Retrieves the current DeFindex receiver’s address.

+
source

pub fn admin(&self) -> Address

Retrieves the current admin’s address.

§Arguments
  • e - The environment in which the contract is running.
§Returns
    -
  • Result<Address, FactoryError> - Returns the DeFindex receiver’s address or an error if not found.
  • +
  • Result<Address, FactoryError> - Returns the admin’s address or an error if not found.
-
source

pub fn try_defindex_receiver( - &self -) -> Result<Result<Address, <Address as TryFromVal<Env, Val>>::Error>, Result<FactoryError, InvokeError>>

Retrieves the current DeFindex receiver’s address.

+
source

pub fn try_admin( + &self, +) -> Result<Result<Address, <Address as TryFromVal<Env, Val>>::Error>, Result<FactoryError, InvokeError>>

Retrieves the current admin’s address.

§Arguments
  • e - The environment in which the contract is running.
§Returns
    -
  • Result<Address, FactoryError> - Returns the DeFindex receiver’s address or an error if not found.
  • +
  • Result<Address, FactoryError> - Returns the admin’s address or an error if not found.
-
source

pub fn deployed_defindexes(&self) -> Map<u32, Address>

Retrieves a map of all deployed DeFindex vaults.

+
source

pub fn defindex_receiver(&self) -> Address

Retrieves the current DeFindex receiver’s address.

§Arguments
  • e - The environment in which the contract is running.
§Returns
    -
  • Result<Map<u32, Address>, FactoryError> - Returns a map with vault identifiers and addresses or an error if retrieval fails.
  • +
  • Result<Address, FactoryError> - Returns the DeFindex receiver’s address or an error if not found.
-
source

pub fn try_deployed_defindexes( - &self -) -> Result<Result<Map<u32, Address>, <Map<u32, Address> as TryFromVal<Env, Val>>::Error>, Result<FactoryError, InvokeError>>

Retrieves a map of all deployed DeFindex vaults.

+
source

pub fn try_defindex_receiver( + &self, +) -> Result<Result<Address, <Address as TryFromVal<Env, Val>>::Error>, Result<FactoryError, InvokeError>>

Retrieves the current DeFindex receiver’s address.

§Arguments
  • e - The environment in which the contract is running.
§Returns
    -
  • Result<Map<u32, Address>, FactoryError> - Returns a map with vault identifiers and addresses or an error if retrieval fails.
  • +
  • Result<Address, FactoryError> - Returns the DeFindex receiver’s address or an error if not found.
-
source

pub fn fee_rate(&self) -> u32

Retrieves the current fee rate.

+
source

pub fn deployed_defindexes(&self) -> Map<u32, Address>

Retrieves a map of all deployed DeFindex vaults.

§Arguments
  • e - The environment in which the contract is running.
§Returns
    -
  • Result<u32, FactoryError> - Returns the fee rate in basis points or an error if not found.
  • +
  • Result<Map<u32, Address>, FactoryError> - Returns a map with vault identifiers and addresses or an error if retrieval fails.
-
source

pub fn try_fee_rate( - &self -) -> Result<Result<u32, <u32 as TryFromVal<Env, Val>>::Error>, Result<FactoryError, InvokeError>>

Retrieves the current fee rate.

+
source

pub fn try_deployed_defindexes( + &self, +) -> Result<Result<Map<u32, Address>, <Map<u32, Address> as TryFromVal<Env, Val>>::Error>, Result<FactoryError, InvokeError>>

Retrieves a map of all deployed DeFindex vaults.

§Arguments
  • e - The environment in which the contract is running.
§Returns
    +
  • Result<Map<u32, Address>, FactoryError> - Returns a map with vault identifiers and addresses or an error if retrieval fails.
  • +
+
source

pub fn defindex_fee(&self) -> u32

Retrieves the current fee rate.

+
§Arguments
+
    +
  • e - The environment in which the contract is running.
  • +
+
§Returns
+
    +
  • Result<u32, FactoryError> - Returns the fee rate in basis points or an error if not found.
  • +
+
source

pub fn try_defindex_fee( + &self, +) -> Result<Result<u32, <u32 as TryFromVal<Env, Val>>::Error>, Result<FactoryError, InvokeError>>

Retrieves the current fee rate.

+
§Arguments
+
    +
  • e - The environment in which the contract is running.
  • +
+
§Returns
+
  • Result<u32, FactoryError> - Returns the fee rate in basis points or an error if not found.
-

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where - T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where - T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where - T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T, C> Compare<&T> for C
where - C: Compare<T>,

§

type Error = <C as Compare<T>>::Error

§

fn compare(&self, a: &&T, b: &&T) -> Result<Ordering, <C as Compare<&T>>::Error>

§

impl<T, U, E, C> Compare<(T, U)> for C
where - C: Compare<T, Error = E, Error = E> + Compare<U>,

§

type Error = E

§

fn compare( +

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T, C> Compare<&T> for C
where + C: Compare<T>,

§

type Error = <C as Compare<T>>::Error

§

fn compare(&self, a: &&T, b: &&T) -> Result<Ordering, <C as Compare<&T>>::Error>

§

impl<T, U, E, C> Compare<(T, U)> for C
where + C: Compare<T, Error = E, Error = E> + Compare<U>,

§

type Error = E

§

fn compare( &self, - a: &(T, U), - b: &(T, U) -) -> Result<Ordering, <C as Compare<(T, U)>>::Error>

§

impl<T, U, V, E, C> Compare<(T, U, V)> for C
where - C: Compare<T, Error = E, Error = E, Error = E> + Compare<U> + Compare<V>,

§

type Error = E

§

fn compare( + a: &(T, U), + b: &(T, U), +) -> Result<Ordering, <C as Compare<(T, U)>>::Error>

§

impl<T, U, V, E, C> Compare<(T, U, V)> for C
where + C: Compare<T, Error = E, Error = E, Error = E> + Compare<U> + Compare<V>,

§

type Error = E

§

fn compare( &self, - a: &(T, U, V), - b: &(T, U, V) -) -> Result<Ordering, <C as Compare<(T, U, V)>>::Error>

§

impl<T, U, V, W, E, C> Compare<(T, U, V, W)> for C
where - C: Compare<T, Error = E, Error = E, Error = E, Error = E> + Compare<U> + Compare<V> + Compare<W>,

§

type Error = E

§

fn compare( + a: &(T, U, V), + b: &(T, U, V), +) -> Result<Ordering, <C as Compare<(T, U, V)>>::Error>

§

impl<T, U, V, W, E, C> Compare<(T, U, V, W)> for C
where + C: Compare<T, Error = E, Error = E, Error = E, Error = E> + Compare<U> + Compare<V> + Compare<W>,

§

type Error = E

§

fn compare( &self, - a: &(T, U, V, W), - b: &(T, U, V, W) -) -> Result<Ordering, <C as Compare<(T, U, V, W)>>::Error>

§

impl<T, U, V, W, X, E, C> Compare<(T, U, V, W, X)> for C
where - C: Compare<T, Error = E, Error = E, Error = E, Error = E, Error = E> + Compare<U> + Compare<V> + Compare<W> + Compare<X>,

§

type Error = E

§

fn compare( + a: &(T, U, V, W), + b: &(T, U, V, W), +) -> Result<Ordering, <C as Compare<(T, U, V, W)>>::Error>

§

impl<T, U, V, W, X, E, C> Compare<(T, U, V, W, X)> for C
where + C: Compare<T, Error = E, Error = E, Error = E, Error = E, Error = E> + Compare<U> + Compare<V> + Compare<W> + Compare<X>,

§

type Error = E

§

fn compare( &self, - a: &(T, U, V, W, X), - b: &(T, U, V, W, X) -) -> Result<Ordering, <C as Compare<(T, U, V, W, X)>>::Error>

§

impl<T, C> Compare<Box<T>> for C
where - C: Compare<T>,

§

type Error = <C as Compare<T>>::Error

§

fn compare( + a: &(T, U, V, W, X), + b: &(T, U, V, W, X), +) -> Result<Ordering, <C as Compare<(T, U, V, W, X)>>::Error>

§

impl<T, C> Compare<Box<T>> for C
where + C: Compare<T>,

§

type Error = <C as Compare<T>>::Error

§

fn compare( &self, - a: &Box<T>, - b: &Box<T> -) -> Result<Ordering, <C as Compare<Box<T>>>::Error>

§

impl<T, C> Compare<Option<T>> for C
where - C: Compare<T>,

§

type Error = <C as Compare<T>>::Error

§

fn compare( + a: &Box<T>, + b: &Box<T>, +) -> Result<Ordering, <C as Compare<Box<T>>>::Error>

§

impl<T, C> Compare<Option<T>> for C
where + C: Compare<T>,

§

type Error = <C as Compare<T>>::Error

§

fn compare( &self, - a: &Option<T>, - b: &Option<T> -) -> Result<Ordering, <C as Compare<Option<T>>>::Error>

§

impl<T, C> Compare<Rc<T>> for C
where - C: Compare<T>,

§

type Error = <C as Compare<T>>::Error

§

fn compare( + a: &Option<T>, + b: &Option<T>, +) -> Result<Ordering, <C as Compare<Option<T>>>::Error>

§

impl<T, C> Compare<Rc<T>> for C
where + C: Compare<T>,

§

type Error = <C as Compare<T>>::Error

§

fn compare( &self, - a: &Rc<T>, - b: &Rc<T> -) -> Result<Ordering, <C as Compare<Rc<T>>>::Error>

§

impl<T, C> Compare<Vec<T>> for C
where - C: Compare<T>,

§

type Error = <C as Compare<T>>::Error

§

fn compare( + a: &Rc<T>, + b: &Rc<T>, +) -> Result<Ordering, <C as Compare<Rc<T>>>::Error>

§

impl<T, C> Compare<Vec<T>> for C
where + C: Compare<T>,

§

type Error = <C as Compare<T>>::Error

§

fn compare( &self, - a: &Vec<T>, - b: &Vec<T> -) -> Result<Ordering, <C as Compare<Vec<T>>>::Error>

§

impl<T> Downcast for T
where - T: Any,

§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can -then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be -further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot -generate &Any’s vtable from &Trait’s.
§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot -generate &mut Any’s vtable from &mut Trait’s.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

-
source§

impl<T, U> Into<U> for T
where - U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+ a: &Vec<T>, + b: &Vec<T>, +) -> Result<Ordering, <C as Compare<Vec<T>>>::Error>
§

impl<T> Downcast for T
where + T: Any,

§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can +then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be +further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot +generate &Any’s vtable from &Trait’s.
§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot +generate &mut Any’s vtable from &mut Trait’s.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+
source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

+From<T> for U chooses to do.

§

impl<E, T, U> IntoVal<E, T> for U
where E: Env, - T: FromVal<E, U>,

§

fn into_val(&self, e: &E) -> T

source§

impl<T> Same for T

§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for T
where - U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where - U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<E, T, U> TryIntoVal<E, T> for U
where + T: FromVal<E, U>,

§

fn into_val(&self, e: &E) -> T

source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<E, T, U> TryIntoVal<E, T> for U
where E: Env, - T: TryFromVal<E, U>,

§

type Error = <T as TryFromVal<E, U>>::Error

§

fn try_into_val(&self, env: &E) -> Result<T, <U as TryIntoVal<E, T>>::Error>

§

impl<V, T> VZip<V> for T
where + T: TryFromVal<E, U>,

§

type Error = <T as TryFromVal<E, U>>::Error

§

fn try_into_val(&self, env: &E) -> Result<T, <U as TryIntoVal<E, T>>::Error>

§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

\ No newline at end of file diff --git a/apps/rust_docs/defindex_factory/trait.FactoryTrait.html b/apps/rust_docs/defindex_factory/trait.FactoryTrait.html index c0b7643d..a14f63d9 100644 --- a/apps/rust_docs/defindex_factory/trait.FactoryTrait.html +++ b/apps/rust_docs/defindex_factory/trait.FactoryTrait.html @@ -1,140 +1,189 @@ -FactoryTrait in defindex_factory - Rust

Trait defindex_factory::FactoryTrait

source ·
pub trait FactoryTrait {
+FactoryTrait in defindex_factory - Rust

Trait defindex_factory::FactoryTrait

source ·
pub trait FactoryTrait {
     // Required methods
     fn initialize(
         e: Env,
         admin: Address,
         defindex_receiver: Address,
-        fee_rate: u32,
-        defindex_wasm_hash: BytesN<32>
-    ) -> Result<(), FactoryError>;
+        defindex_fee: u32,
+        vault_wasm_hash: BytesN<32>,
+    ) -> Result<(), FactoryError>;
     fn create_defindex_vault(
         e: Env,
         emergency_manager: Address,
         fee_receiver: Address,
-        vault_share: u32,
+        vault_fee: u32,
+        vault_name: String,
+        vault_symbol: String,
         manager: Address,
-        assets: Vec<AssetAllocation>,
-        salt: BytesN<32>
-    ) -> Result<Address, FactoryError>;
-    fn set_new_admin(e: Env, new_admin: Address) -> Result<(), FactoryError>;
+        assets: Vec<AssetStrategySet>,
+        salt: BytesN<32>,
+    ) -> Result<Address, FactoryError>;
+    fn create_defindex_vault_deposit(
+        e: Env,
+        caller: Address,
+        emergency_manager: Address,
+        fee_receiver: Address,
+        vault_fee: u32,
+        vault_name: String,
+        vault_symbol: String,
+        manager: Address,
+        assets: Vec<AssetStrategySet>,
+        amounts: Vec<i128>,
+        salt: BytesN<32>,
+    ) -> Result<Address, FactoryError>;
+    fn set_new_admin(e: Env, new_admin: Address) -> Result<(), FactoryError>;
     fn set_defindex_receiver(
         e: Env,
-        new_fee_receiver: Address
-    ) -> Result<(), FactoryError>;
-    fn set_fee_rate(e: Env, new_fee_rate: u32) -> Result<(), FactoryError>;
-    fn admin(e: Env) -> Result<Address, FactoryError>;
-    fn defindex_receiver(e: Env) -> Result<Address, FactoryError>;
-    fn deployed_defindexes(e: Env) -> Result<Map<u32, Address>, FactoryError>;
-    fn fee_rate(e: Env) -> Result<u32, FactoryError>;
-}

Required Methods§

source

fn initialize( + new_fee_receiver: Address, + ) -> Result<(), FactoryError>; + fn set_defindex_fee(e: Env, new_fee_rate: u32) -> Result<(), FactoryError>; + fn admin(e: Env) -> Result<Address, FactoryError>; + fn defindex_receiver(e: Env) -> Result<Address, FactoryError>; + fn deployed_defindexes(e: Env) -> Result<Map<u32, Address>, FactoryError>; + fn defindex_fee(e: Env) -> Result<u32, FactoryError>; +}

Required Methods§

source

fn initialize( e: Env, admin: Address, defindex_receiver: Address, - fee_rate: u32, - defindex_wasm_hash: BytesN<32> -) -> Result<(), FactoryError>

Initializes the factory contract with the given parameters.

+ defindex_fee: u32, + vault_wasm_hash: BytesN<32>, +) -> Result<(), FactoryError>

Initializes the factory contract with the given parameters.

§Arguments
  • e - The environment in which the contract is running.
  • admin - The address of the contract administrator, who can manage settings.
  • defindex_receiver - The default address designated to receive a portion of fees.
  • -
  • fee_rate - The initial annual fee rate (in basis points).
  • -
  • defindex_wasm_hash - The hash of the DeFindex Vault’s WASM file for deploying new vaults.
  • +
  • defindex_fee - The initial annual fee rate (in basis points).
  • +
  • vault_wasm_hash - The hash of the DeFindex Vault’s WASM file for deploying new vaults.
§Returns
  • Result<(), FactoryError> - Returns Ok(()) if successful, otherwise an error.
-
source

fn create_defindex_vault( +

source

fn create_defindex_vault( e: Env, emergency_manager: Address, fee_receiver: Address, - vault_share: u32, + vault_fee: u32, + vault_name: String, + vault_symbol: String, manager: Address, - assets: Vec<AssetAllocation>, - salt: BytesN<32> -) -> Result<Address, FactoryError>

Creates a new DeFindex Vault with specified parameters.

+ assets: Vec<AssetStrategySet>, + salt: BytesN<32>, +) -> Result<Address, FactoryError>

Creates a new DeFindex Vault with specified parameters.

§Arguments
  • e - The environment in which the contract is running.
  • emergency_manager - The address assigned emergency control over the vault.
  • fee_receiver - The address designated to receive fees from the vault.
  • -
  • vault_share - The percentage share of fees allocated to the vault’s fee receiver.
  • +
  • vault_fee - The percentage share of fees allocated to the vault’s fee receiver.
  • +
  • vault_name - The name of the vault.
  • +
  • vault_symbol - The symbol of the vault.
  • manager - The address assigned as the vault manager.
  • -
  • assets - A vector of AssetAllocation structs that define the assets managed by the vault.
  • +
  • assets - A vector of AssetStrategySet structs that define the assets managed by the vault.
  • salt - A salt used for ensuring unique addresses for each deployed vault.
§Returns
  • Result<Address, FactoryError> - Returns the address of the new vault, or an error if unsuccessful.
-
source

fn set_new_admin(e: Env, new_admin: Address) -> Result<(), FactoryError>

Sets a new admin address.

+
source

fn create_defindex_vault_deposit( + e: Env, + caller: Address, + emergency_manager: Address, + fee_receiver: Address, + vault_fee: u32, + vault_name: String, + vault_symbol: String, + manager: Address, + assets: Vec<AssetStrategySet>, + amounts: Vec<i128>, + salt: BytesN<32>, +) -> Result<Address, FactoryError>

Creates a new DeFindex Vault with specified parameters and makes the first deposit to set ratios.

§Arguments
  • e - The environment in which the contract is running.
  • -
  • new_admin - The new administrator’s address.
  • +
  • emergency_manager - The address assigned emergency control over the vault.
  • +
  • fee_receiver - The address designated to receive fees from the vault.
  • +
  • vault_fee - The percentage share of fees allocated to the vault’s fee receiver.
  • +
  • vault_name - The name of the vault.
  • +
  • vault_symbol - The symbol of the vault.
  • +
  • manager - The address assigned as the vault manager.
  • +
  • assets - A vector of AssetStrategySet structs that define the assets managed by the vault.
  • +
  • amounts - A vector of AssetAmounts structs that define the initial deposit amounts.
  • +
  • salt - A salt used for ensuring unique addresses for each deployed vault.
§Returns
    -
  • Result<(), FactoryError> - Returns Ok(()) if successful, or an error if not authorized.
  • +
  • Result<Address, FactoryError> - Returns the address of the new vault, or an error if unsuccessful.
-
source

fn set_defindex_receiver( - e: Env, - new_fee_receiver: Address -) -> Result<(), FactoryError>

Updates the default receiver address for the DeFindex portion of fees.

+
source

fn set_new_admin(e: Env, new_admin: Address) -> Result<(), FactoryError>

Sets a new admin address.

§Arguments
  • e - The environment in which the contract is running.
  • -
  • new_fee_receiver - The address of the new fee receiver.
  • +
  • new_admin - The new administrator’s address.
§Returns
  • Result<(), FactoryError> - Returns Ok(()) if successful, or an error if not authorized.
-
source

fn set_fee_rate(e: Env, new_fee_rate: u32) -> Result<(), FactoryError>

Updates the default fee rate for new vaults.

+
source

fn set_defindex_receiver( + e: Env, + new_fee_receiver: Address, +) -> Result<(), FactoryError>

Updates the default receiver address for the DeFindex portion of fees.

§Arguments
  • e - The environment in which the contract is running.
  • -
  • new_fee_rate - The new annual fee rate in basis points.
  • +
  • new_fee_receiver - The address of the new fee receiver.
§Returns
  • Result<(), FactoryError> - Returns Ok(()) if successful, or an error if not authorized.
-
source

fn admin(e: Env) -> Result<Address, FactoryError>

Retrieves the current admin’s address.

+
source

fn set_defindex_fee(e: Env, new_fee_rate: u32) -> Result<(), FactoryError>

Updates the default fee rate for new vaults.

§Arguments
  • e - The environment in which the contract is running.
  • +
  • new_fee_rate - The new annual fee rate in basis points.
§Returns
    -
  • Result<Address, FactoryError> - Returns the admin’s address or an error if not found.
  • +
  • Result<(), FactoryError> - Returns Ok(()) if successful, or an error if not authorized.
-
source

fn defindex_receiver(e: Env) -> Result<Address, FactoryError>

Retrieves the current DeFindex receiver’s address.

+
source

fn admin(e: Env) -> Result<Address, FactoryError>

Retrieves the current admin’s address.

§Arguments
  • e - The environment in which the contract is running.
§Returns
    -
  • Result<Address, FactoryError> - Returns the DeFindex receiver’s address or an error if not found.
  • +
  • Result<Address, FactoryError> - Returns the admin’s address or an error if not found.
-
source

fn deployed_defindexes(e: Env) -> Result<Map<u32, Address>, FactoryError>

Retrieves a map of all deployed DeFindex vaults.

+
source

fn defindex_receiver(e: Env) -> Result<Address, FactoryError>

Retrieves the current DeFindex receiver’s address.

§Arguments
  • e - The environment in which the contract is running.
§Returns
    -
  • Result<Map<u32, Address>, FactoryError> - Returns a map with vault identifiers and addresses or an error if retrieval fails.
  • +
  • Result<Address, FactoryError> - Returns the DeFindex receiver’s address or an error if not found.
-
source

fn fee_rate(e: Env) -> Result<u32, FactoryError>

Retrieves the current fee rate.

+
source

fn deployed_defindexes(e: Env) -> Result<Map<u32, Address>, FactoryError>

Retrieves a map of all deployed DeFindex vaults.

§Arguments
  • e - The environment in which the contract is running.
§Returns
    +
  • Result<Map<u32, Address>, FactoryError> - Returns a map with vault identifiers and addresses or an error if retrieval fails.
  • +
+
source

fn defindex_fee(e: Env) -> Result<u32, FactoryError>

Retrieves the current fee rate.

+
§Arguments
+
    +
  • e - The environment in which the contract is running.
  • +
+
§Returns
+
  • Result<u32, FactoryError> - Returns the fee rate in basis points or an error if not found.
-

Object Safety§

This trait is not object safe.

Implementors§

\ No newline at end of file +

Object Safety§

This trait is not object safe.

Implementors§

\ No newline at end of file diff --git a/apps/rust_docs/defindex_factory/vault/fn.create_contract.html b/apps/rust_docs/defindex_factory/vault/fn.create_contract.html new file mode 100644 index 00000000..3071fccc --- /dev/null +++ b/apps/rust_docs/defindex_factory/vault/fn.create_contract.html @@ -0,0 +1,11 @@ + + + + + Redirection + + +

Redirecting to ../../defindex_factory/fn.create_contract.html...

+ + + \ No newline at end of file diff --git a/apps/rust_docs/defindex_strategy_core/all.html b/apps/rust_docs/defindex_strategy_core/all.html index df4dd3b8..e4050eb9 100644 --- a/apps/rust_docs/defindex_strategy_core/all.html +++ b/apps/rust_docs/defindex_strategy_core/all.html @@ -1 +1 @@ -List of all items in this crate
\ No newline at end of file +List of all items in this crate
\ No newline at end of file diff --git a/apps/rust_docs/defindex_strategy_core/enum.StrategyError.html b/apps/rust_docs/defindex_strategy_core/enum.StrategyError.html index 6c748c3d..c1b91997 100644 --- a/apps/rust_docs/defindex_strategy_core/enum.StrategyError.html +++ b/apps/rust_docs/defindex_strategy_core/enum.StrategyError.html @@ -1,90 +1,92 @@ -StrategyError in defindex_strategy_core - Rust

Enum defindex_strategy_core::StrategyError

source ·
#[repr(u32)]
pub enum StrategyError { +StrategyError in defindex_strategy_core - Rust

Enum defindex_strategy_core::StrategyError

source ·
#[repr(u32)]
pub enum StrategyError { NotInitialized = 401, AlreadyInitialized = 402, NegativeNotAllowed = 410, InvalidArgument = 411, + InsufficientBalance = 412, ProtocolAddressNotFound = 420, DeadlineExpired = 421, ExternalError = 422, -}

Variants§

§

NotInitialized = 401

§

AlreadyInitialized = 402

§

NegativeNotAllowed = 410

§

InvalidArgument = 411

§

ProtocolAddressNotFound = 420

§

DeadlineExpired = 421

§

ExternalError = 422

Implementations§

source§

impl StrategyError

source

pub const fn spec_xdr() -> [u8; 248]

Trait Implementations§

source§

impl Clone for StrategyError

source§

fn clone(&self) -> StrategyError

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for StrategyError

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl From<&StrategyError> for Error

source§

fn from(val: &StrategyError) -> Error

Converts to this type from the input type.
source§

impl From<&StrategyError> for InvokeError

source§

fn from(val: &StrategyError) -> InvokeError

Converts to this type from the input type.
source§

impl From<StrategyError> for Error

source§

fn from(val: StrategyError) -> Error

Converts to this type from the input type.
source§

impl From<StrategyError> for InvokeError

source§

fn from(val: StrategyError) -> InvokeError

Converts to this type from the input type.
source§

impl Ord for StrategyError

source§

fn cmp(&self, other: &StrategyError) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · source§

fn max(self, other: Self) -> Self
where - Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · source§

fn min(self, other: Self) -> Self
where - Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 · source§

fn clamp(self, min: Self, max: Self) -> Self
where - Self: Sized + PartialOrd,

Restrict a value to a certain interval. Read more
source§

impl PartialEq for StrategyError

source§

fn eq(&self, other: &StrategyError) -> bool

This method tests for self and other values to be equal, and is used -by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason.
source§

impl PartialOrd for StrategyError

source§

fn partial_cmp(&self, other: &StrategyError) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · source§

fn lt(&self, other: &Rhs) -> bool

This method tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · source§

fn le(&self, other: &Rhs) -> bool

This method tests less than or equal to (for self and other) and is used by the <= -operator. Read more
1.0.0 · source§

fn gt(&self, other: &Rhs) -> bool

This method tests greater than (for self and other) and is used by the > operator. Read more
1.0.0 · source§

fn ge(&self, other: &Rhs) -> bool

This method tests greater than or equal to (for self and other) and is used by the >= -operator. Read more
source§

impl TryFrom<&Error> for StrategyError

§

type Error = Error

The type returned in the event of a conversion error.
source§

fn try_from(error: &Error) -> Result<Self, Error>

Performs the conversion.
source§

impl TryFrom<&InvokeError> for StrategyError

§

type Error = InvokeError

The type returned in the event of a conversion error.
source§

fn try_from(error: &InvokeError) -> Result<Self, InvokeError>

Performs the conversion.
source§

impl TryFrom<Error> for StrategyError

§

type Error = Error

The type returned in the event of a conversion error.
source§

fn try_from(error: Error) -> Result<Self, Error>

Performs the conversion.
source§

impl TryFrom<InvokeError> for StrategyError

§

type Error = InvokeError

The type returned in the event of a conversion error.
source§

fn try_from(error: InvokeError) -> Result<Self, InvokeError>

Performs the conversion.
source§

impl TryFromVal<Env, StrategyError> for Val

§

type Error = ConversionError

source§

fn try_from_val(env: &Env, val: &StrategyError) -> Result<Self, ConversionError>

source§

impl TryFromVal<Env, Val> for StrategyError

§

type Error = ConversionError

source§

fn try_from_val(env: &Env, val: &Val) -> Result<Self, ConversionError>

source§

impl Copy for StrategyError

source§

impl Eq for StrategyError

source§

impl StructuralPartialEq for StrategyError

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where - T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where - T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where - T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<Q, K> Comparable<K> for Q
where - Q: Ord + ?Sized, - K: Borrow<Q> + ?Sized,

§

fn compare(&self, key: &K) -> Ordering

Compare self to key and return their ordering.
§

impl<T, C> Compare<&T> for C
where - C: Compare<T>,

§

type Error = <C as Compare<T>>::Error

§

fn compare(&self, a: &&T, b: &&T) -> Result<Ordering, <C as Compare<&T>>::Error>

§

impl<T, U, E, C> Compare<(T, U)> for C
where - C: Compare<T, Error = E, Error = E> + Compare<U>,

§

type Error = E

§

fn compare( +}

Variants§

§

NotInitialized = 401

§

AlreadyInitialized = 402

§

NegativeNotAllowed = 410

§

InvalidArgument = 411

§

InsufficientBalance = 412

§

ProtocolAddressNotFound = 420

§

DeadlineExpired = 421

§

ExternalError = 422

Implementations§

source§

impl StrategyError

source

pub const fn spec_xdr() -> [u8; 280]

Trait Implementations§

source§

impl Clone for StrategyError

source§

fn clone(&self) -> StrategyError

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for StrategyError

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl From<&StrategyError> for Error

source§

fn from(val: &StrategyError) -> Error

Converts to this type from the input type.
source§

impl From<&StrategyError> for InvokeError

source§

fn from(val: &StrategyError) -> InvokeError

Converts to this type from the input type.
source§

impl From<StrategyError> for Error

source§

fn from(val: StrategyError) -> Error

Converts to this type from the input type.
source§

impl From<StrategyError> for InvokeError

source§

fn from(val: StrategyError) -> InvokeError

Converts to this type from the input type.
source§

impl Ord for StrategyError

source§

fn cmp(&self, other: &StrategyError) -> Ordering

This method returns an Ordering between self and other. Read more
1.21.0 · source§

fn max(self, other: Self) -> Self
where + Self: Sized,

Compares and returns the maximum of two values. Read more
1.21.0 · source§

fn min(self, other: Self) -> Self
where + Self: Sized,

Compares and returns the minimum of two values. Read more
1.50.0 · source§

fn clamp(self, min: Self, max: Self) -> Self
where + Self: Sized + PartialOrd,

Restrict a value to a certain interval. Read more
source§

impl PartialEq for StrategyError

source§

fn eq(&self, other: &StrategyError) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, +and should not be overridden without very good reason.
source§

impl PartialOrd for StrategyError

source§

fn partial_cmp(&self, other: &StrategyError) -> Option<Ordering>

This method returns an ordering between self and other values if one exists. Read more
1.0.0 · source§

fn lt(&self, other: &Rhs) -> bool

Tests less than (for self and other) and is used by the < operator. Read more
1.0.0 · source§

fn le(&self, other: &Rhs) -> bool

Tests less than or equal to (for self and other) and is used by the +<= operator. Read more
1.0.0 · source§

fn gt(&self, other: &Rhs) -> bool

Tests greater than (for self and other) and is used by the > +operator. Read more
1.0.0 · source§

fn ge(&self, other: &Rhs) -> bool

Tests greater than or equal to (for self and other) and is used by +the >= operator. Read more
source§

impl TryFrom<&Error> for StrategyError

source§

type Error = Error

The type returned in the event of a conversion error.
source§

fn try_from(error: &Error) -> Result<Self, Error>

Performs the conversion.
source§

impl TryFrom<&InvokeError> for StrategyError

source§

type Error = InvokeError

The type returned in the event of a conversion error.
source§

fn try_from(error: &InvokeError) -> Result<Self, InvokeError>

Performs the conversion.
source§

impl TryFrom<Error> for StrategyError

source§

type Error = Error

The type returned in the event of a conversion error.
source§

fn try_from(error: Error) -> Result<Self, Error>

Performs the conversion.
source§

impl TryFrom<InvokeError> for StrategyError

source§

type Error = InvokeError

The type returned in the event of a conversion error.
source§

fn try_from(error: InvokeError) -> Result<Self, InvokeError>

Performs the conversion.
source§

impl TryFromVal<Env, StrategyError> for Val

source§

type Error = ConversionError

source§

fn try_from_val(env: &Env, val: &StrategyError) -> Result<Self, ConversionError>

source§

impl TryFromVal<Env, Val> for StrategyError

source§

type Error = ConversionError

source§

fn try_from_val(env: &Env, val: &Val) -> Result<Self, ConversionError>

source§

impl Copy for StrategyError

source§

impl Eq for StrategyError

source§

impl StructuralPartialEq for StrategyError

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
§

impl<Q, K> Comparable<K> for Q
where + Q: Ord + ?Sized, + K: Borrow<Q> + ?Sized,

§

fn compare(&self, key: &K) -> Ordering

Compare self to key and return their ordering.
§

impl<T, C> Compare<&T> for C
where + C: Compare<T>,

§

type Error = <C as Compare<T>>::Error

§

fn compare(&self, a: &&T, b: &&T) -> Result<Ordering, <C as Compare<&T>>::Error>

§

impl<T, U, E, C> Compare<(T, U)> for C
where + C: Compare<T, Error = E, Error = E> + Compare<U>,

§

type Error = E

§

fn compare( &self, - a: &(T, U), - b: &(T, U) -) -> Result<Ordering, <C as Compare<(T, U)>>::Error>

§

impl<T, U, V, E, C> Compare<(T, U, V)> for C
where - C: Compare<T, Error = E, Error = E, Error = E> + Compare<U> + Compare<V>,

§

type Error = E

§

fn compare( + a: &(T, U), + b: &(T, U), +) -> Result<Ordering, <C as Compare<(T, U)>>::Error>

§

impl<T, U, V, E, C> Compare<(T, U, V)> for C
where + C: Compare<T, Error = E, Error = E, Error = E> + Compare<U> + Compare<V>,

§

type Error = E

§

fn compare( &self, - a: &(T, U, V), - b: &(T, U, V) -) -> Result<Ordering, <C as Compare<(T, U, V)>>::Error>

§

impl<T, U, V, W, E, C> Compare<(T, U, V, W)> for C
where - C: Compare<T, Error = E, Error = E, Error = E, Error = E> + Compare<U> + Compare<V> + Compare<W>,

§

type Error = E

§

fn compare( + a: &(T, U, V), + b: &(T, U, V), +) -> Result<Ordering, <C as Compare<(T, U, V)>>::Error>

§

impl<T, U, V, W, E, C> Compare<(T, U, V, W)> for C
where + C: Compare<T, Error = E, Error = E, Error = E, Error = E> + Compare<U> + Compare<V> + Compare<W>,

§

type Error = E

§

fn compare( &self, - a: &(T, U, V, W), - b: &(T, U, V, W) -) -> Result<Ordering, <C as Compare<(T, U, V, W)>>::Error>

§

impl<T, U, V, W, X, E, C> Compare<(T, U, V, W, X)> for C
where - C: Compare<T, Error = E, Error = E, Error = E, Error = E, Error = E> + Compare<U> + Compare<V> + Compare<W> + Compare<X>,

§

type Error = E

§

fn compare( + a: &(T, U, V, W), + b: &(T, U, V, W), +) -> Result<Ordering, <C as Compare<(T, U, V, W)>>::Error>

§

impl<T, U, V, W, X, E, C> Compare<(T, U, V, W, X)> for C
where + C: Compare<T, Error = E, Error = E, Error = E, Error = E, Error = E> + Compare<U> + Compare<V> + Compare<W> + Compare<X>,

§

type Error = E

§

fn compare( &self, - a: &(T, U, V, W, X), - b: &(T, U, V, W, X) -) -> Result<Ordering, <C as Compare<(T, U, V, W, X)>>::Error>

§

impl<T, C> Compare<Box<T>> for C
where - C: Compare<T>,

§

type Error = <C as Compare<T>>::Error

§

fn compare( + a: &(T, U, V, W, X), + b: &(T, U, V, W, X), +) -> Result<Ordering, <C as Compare<(T, U, V, W, X)>>::Error>

§

impl<T, C> Compare<Box<T>> for C
where + C: Compare<T>,

§

type Error = <C as Compare<T>>::Error

§

fn compare( &self, - a: &Box<T>, - b: &Box<T> -) -> Result<Ordering, <C as Compare<Box<T>>>::Error>

§

impl<T, C> Compare<Option<T>> for C
where - C: Compare<T>,

§

type Error = <C as Compare<T>>::Error

§

fn compare( + a: &Box<T>, + b: &Box<T>, +) -> Result<Ordering, <C as Compare<Box<T>>>::Error>

§

impl<T, C> Compare<Option<T>> for C
where + C: Compare<T>,

§

type Error = <C as Compare<T>>::Error

§

fn compare( &self, - a: &Option<T>, - b: &Option<T> -) -> Result<Ordering, <C as Compare<Option<T>>>::Error>

§

impl<T, C> Compare<Rc<T>> for C
where - C: Compare<T>,

§

type Error = <C as Compare<T>>::Error

§

fn compare( + a: &Option<T>, + b: &Option<T>, +) -> Result<Ordering, <C as Compare<Option<T>>>::Error>

§

impl<T, C> Compare<Rc<T>> for C
where + C: Compare<T>,

§

type Error = <C as Compare<T>>::Error

§

fn compare( &self, - a: &Rc<T>, - b: &Rc<T> -) -> Result<Ordering, <C as Compare<Rc<T>>>::Error>

§

impl<T, C> Compare<Vec<T>> for C
where - C: Compare<T>,

§

type Error = <C as Compare<T>>::Error

§

fn compare( + a: &Rc<T>, + b: &Rc<T>, +) -> Result<Ordering, <C as Compare<Rc<T>>>::Error>

§

impl<T, C> Compare<Vec<T>> for C
where + C: Compare<T>,

§

type Error = <C as Compare<T>>::Error

§

fn compare( &self, - a: &Vec<T>, - b: &Vec<T> -) -> Result<Ordering, <C as Compare<Vec<T>>>::Error>

§

impl<T> Downcast for T
where - T: Any,

§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can -then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be -further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot -generate &Any’s vtable from &Trait’s.
§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot + a: &Vec<T>, + b: &Vec<T>, +) -> Result<Ordering, <C as Compare<Vec<T>>>::Error>
§

impl<T> Downcast for T
where + T: Any,

§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can +then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be +further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot +generate &Any’s vtable from &Trait’s.
§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
§

impl<T> DowncastSync for T
where - T: Any + Send + Sync,

§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be + T: Any + Send + Sync,
§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
§

impl<Q, K> Equivalent<K> for Q
where - Q: Eq + ?Sized, - K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
§

impl<Q, K> Equivalent<K> for Q
where - Q: Eq + ?Sized, - K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+ Q: Eq + ?Sized, + K: Borrow<Q> + ?Sized,
§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
§

impl<Q, K> Equivalent<K> for Q
where + Q: Eq + ?Sized, + K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<E, T, U> FromVal<E, T> for U
where E: Env, - U: TryFromVal<E, T>,

§

fn from_val(e: &E, v: &T) -> U

§

impl<T> FromXdr for T
where - T: TryFromVal<Env, Val>,

§

type Error = <T as TryFromVal<Env, Val>>::Error

§

fn from_xdr(env: &Env, b: &Bytes) -> Result<T, <T as FromXdr>::Error>

source§

impl<T, U> Into<U> for T
where - U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+ U: TryFromVal<E, T>,
§

fn from_val(e: &E, v: &T) -> U

§

impl<T> FromXdr for T
where + T: TryFromVal<Env, Val>,

§

type Error = <T as TryFromVal<Env, Val>>::Error

§

fn from_xdr(env: &Env, b: &Bytes) -> Result<T, <T as FromXdr>::Error>

source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

+From<T> for U chooses to do.

§

impl<E, T, U> IntoVal<E, T> for U
where E: Env, - T: FromVal<E, U>,

§

fn into_val(&self, e: &E) -> T

source§

impl<T> Same for T

§

type Output = T

Should always be Self
source§

impl<T> ToOwned for T
where - T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
§

impl<T> ToXdr for T
where - T: IntoVal<Env, Val>,

§

fn to_xdr(self, env: &Env) -> Bytes

source§

impl<T, U> TryFrom<U> for T
where - U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where - U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<E, T, U> TryIntoVal<E, T> for U
where + T: FromVal<E, U>,

§

fn into_val(&self, e: &E) -> T

source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
§

impl<T> ToXdr for T
where + T: IntoVal<Env, Val>,

§

fn to_xdr(self, env: &Env) -> Bytes

source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<E, T, U> TryIntoVal<E, T> for U
where E: Env, - T: TryFromVal<E, U>,

§

type Error = <T as TryFromVal<E, U>>::Error

§

fn try_into_val(&self, env: &E) -> Result<T, <U as TryIntoVal<E, T>>::Error>

§

impl<V, T> VZip<V> for T
where + T: TryFromVal<E, U>,

§

type Error = <T as TryFromVal<E, U>>::Error

§

fn try_into_val(&self, env: &E) -> Result<T, <U as TryIntoVal<E, T>>::Error>

§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

\ No newline at end of file diff --git a/apps/rust_docs/defindex_strategy_core/event/fn.emit_deposit.html b/apps/rust_docs/defindex_strategy_core/event/fn.emit_deposit.html index 902dee3b..021bfcac 100644 --- a/apps/rust_docs/defindex_strategy_core/event/fn.emit_deposit.html +++ b/apps/rust_docs/defindex_strategy_core/event/fn.emit_deposit.html @@ -1,4 +1,4 @@ -emit_deposit in defindex_strategy_core::event - Rust

Function defindex_strategy_core::event::emit_deposit

source ·
pub fn emit_deposit(e: &Env, strategy_name: String, amount: i128, from: Address)
Expand description

Publishes an DepositEvent to the event stream.

+emit_deposit in defindex_strategy_core::event - Rust

Function defindex_strategy_core::event::emit_deposit

source ·
pub fn emit_deposit(e: &Env, strategy_name: String, amount: i128, from: Address)
Expand description

Publishes an DepositEvent to the event stream.

§Arguments

§

impl<Q, K> Equivalent<K> for Q
where + Q: Eq + ?Sized, + K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<E, T, U> FromVal<E, T> for U
where E: Env, - U: TryFromVal<E, T>,

§

fn from_val(e: &E, v: &T) -> U

§

impl<T> FromXdr for T
where - T: TryFromVal<Env, Val>,

§

type Error = <T as TryFromVal<Env, Val>>::Error

§

fn from_xdr(env: &Env, b: &Bytes) -> Result<T, <T as FromXdr>::Error>

source§

impl<T, U> Into<U> for T
where - U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+ U: TryFromVal<E, T>,
§

fn from_val(e: &E, v: &T) -> U

§

impl<T> FromXdr for T
where + T: TryFromVal<Env, Val>,

§

type Error = <T as TryFromVal<Env, Val>>::Error

§

fn from_xdr(env: &Env, b: &Bytes) -> Result<T, <T as FromXdr>::Error>

source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

+From<T> for U chooses to do.

§

impl<E, T, U> IntoVal<E, T> for U
where E: Env, - T: FromVal<E, U>,

§

fn into_val(&self, e: &E) -> T

source§

impl<T> Same for T

§

type Output = T

Should always be Self
source§

impl<T> ToOwned for T
where - T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
§

impl<T> ToXdr for T
where - T: IntoVal<Env, Val>,

§

fn to_xdr(self, env: &Env) -> Bytes

source§

impl<T, U> TryFrom<U> for T
where - U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where - U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<E, T, U> TryIntoVal<E, T> for U
where + T: FromVal<E, U>,

§

fn into_val(&self, e: &E) -> T

source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
§

impl<T> ToXdr for T
where + T: IntoVal<Env, Val>,

§

fn to_xdr(self, env: &Env) -> Bytes

source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<E, T, U> TryIntoVal<E, T> for U
where E: Env, - T: TryFromVal<E, U>,

§

type Error = <T as TryFromVal<E, U>>::Error

§

fn try_into_val(&self, env: &E) -> Result<T, <U as TryIntoVal<E, T>>::Error>

§

impl<V, T> VZip<V> for T
where + T: TryFromVal<E, U>,

§

type Error = <T as TryFromVal<E, U>>::Error

§

fn try_into_val(&self, env: &E) -> Result<T, <U as TryIntoVal<E, T>>::Error>

§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

\ No newline at end of file diff --git a/apps/rust_docs/defindex_strategy_core/event/struct.InitializedEvent.html b/apps/rust_docs/defindex_strategy_core/event/struct.InitializedEvent.html index dea2db9c..352f1576 100644 --- a/apps/rust_docs/defindex_strategy_core/event/struct.InitializedEvent.html +++ b/apps/rust_docs/defindex_strategy_core/event/struct.InitializedEvent.html @@ -1,78 +1,78 @@ -InitializedEvent in defindex_strategy_core::event - Rust

Struct defindex_strategy_core::event::InitializedEvent

source ·
pub struct InitializedEvent {
+InitializedEvent in defindex_strategy_core::event - Rust

Struct defindex_strategy_core::event::InitializedEvent

source ·
pub struct InitializedEvent {
     pub asset: Address,
-}

Fields§

§asset: Address

Implementations§

source§

impl InitializedEvent

source

pub const fn spec_xdr() -> [u8; 56]

Trait Implementations§

source§

impl Clone for InitializedEvent

source§

fn clone(&self) -> InitializedEvent

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for InitializedEvent

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl PartialEq for InitializedEvent

source§

fn eq(&self, other: &InitializedEvent) -> bool

This method tests for self and other values to be equal, and is used -by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason.
source§

impl TryFromVal<Env, InitializedEvent> for Val

§

type Error = ConversionError

source§

fn try_from_val( +}

Fields§

§asset: Address

Implementations§

source§

impl InitializedEvent

source

pub const fn spec_xdr() -> [u8; 56]

Trait Implementations§

source§

impl Clone for InitializedEvent

source§

fn clone(&self) -> InitializedEvent

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for InitializedEvent

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl PartialEq for InitializedEvent

source§

fn eq(&self, other: &InitializedEvent) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, +and should not be overridden without very good reason.
source§

impl TryFromVal<Env, InitializedEvent> for Val

source§

type Error = ConversionError

source§

fn try_from_val( env: &Env, - val: &InitializedEvent -) -> Result<Self, ConversionError>

source§

impl TryFromVal<Env, Val> for InitializedEvent

§

type Error = ConversionError

source§

fn try_from_val(env: &Env, val: &Val) -> Result<Self, ConversionError>

source§

impl Eq for InitializedEvent

source§

impl StructuralPartialEq for InitializedEvent

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where - T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where - T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where - T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T, C> Compare<&T> for C
where - C: Compare<T>,

§

type Error = <C as Compare<T>>::Error

§

fn compare(&self, a: &&T, b: &&T) -> Result<Ordering, <C as Compare<&T>>::Error>

§

impl<T, U, E, C> Compare<(T, U)> for C
where - C: Compare<T, Error = E, Error = E> + Compare<U>,

§

type Error = E

§

fn compare( + val: &InitializedEvent, +) -> Result<Self, ConversionError>

source§

impl TryFromVal<Env, Val> for InitializedEvent

source§

type Error = ConversionError

source§

fn try_from_val(env: &Env, val: &Val) -> Result<Self, ConversionError>

source§

impl Eq for InitializedEvent

source§

impl StructuralPartialEq for InitializedEvent

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
§

impl<T, C> Compare<&T> for C
where + C: Compare<T>,

§

type Error = <C as Compare<T>>::Error

§

fn compare(&self, a: &&T, b: &&T) -> Result<Ordering, <C as Compare<&T>>::Error>

§

impl<T, U, E, C> Compare<(T, U)> for C
where + C: Compare<T, Error = E, Error = E> + Compare<U>,

§

type Error = E

§

fn compare( &self, - a: &(T, U), - b: &(T, U) -) -> Result<Ordering, <C as Compare<(T, U)>>::Error>

§

impl<T, U, V, E, C> Compare<(T, U, V)> for C
where - C: Compare<T, Error = E, Error = E, Error = E> + Compare<U> + Compare<V>,

§

type Error = E

§

fn compare( + a: &(T, U), + b: &(T, U), +) -> Result<Ordering, <C as Compare<(T, U)>>::Error>

§

impl<T, U, V, E, C> Compare<(T, U, V)> for C
where + C: Compare<T, Error = E, Error = E, Error = E> + Compare<U> + Compare<V>,

§

type Error = E

§

fn compare( &self, - a: &(T, U, V), - b: &(T, U, V) -) -> Result<Ordering, <C as Compare<(T, U, V)>>::Error>

§

impl<T, U, V, W, E, C> Compare<(T, U, V, W)> for C
where - C: Compare<T, Error = E, Error = E, Error = E, Error = E> + Compare<U> + Compare<V> + Compare<W>,

§

type Error = E

§

fn compare( + a: &(T, U, V), + b: &(T, U, V), +) -> Result<Ordering, <C as Compare<(T, U, V)>>::Error>

§

impl<T, U, V, W, E, C> Compare<(T, U, V, W)> for C
where + C: Compare<T, Error = E, Error = E, Error = E, Error = E> + Compare<U> + Compare<V> + Compare<W>,

§

type Error = E

§

fn compare( &self, - a: &(T, U, V, W), - b: &(T, U, V, W) -) -> Result<Ordering, <C as Compare<(T, U, V, W)>>::Error>

§

impl<T, U, V, W, X, E, C> Compare<(T, U, V, W, X)> for C
where - C: Compare<T, Error = E, Error = E, Error = E, Error = E, Error = E> + Compare<U> + Compare<V> + Compare<W> + Compare<X>,

§

type Error = E

§

fn compare( + a: &(T, U, V, W), + b: &(T, U, V, W), +) -> Result<Ordering, <C as Compare<(T, U, V, W)>>::Error>

§

impl<T, U, V, W, X, E, C> Compare<(T, U, V, W, X)> for C
where + C: Compare<T, Error = E, Error = E, Error = E, Error = E, Error = E> + Compare<U> + Compare<V> + Compare<W> + Compare<X>,

§

type Error = E

§

fn compare( &self, - a: &(T, U, V, W, X), - b: &(T, U, V, W, X) -) -> Result<Ordering, <C as Compare<(T, U, V, W, X)>>::Error>

§

impl<T, C> Compare<Box<T>> for C
where - C: Compare<T>,

§

type Error = <C as Compare<T>>::Error

§

fn compare( + a: &(T, U, V, W, X), + b: &(T, U, V, W, X), +) -> Result<Ordering, <C as Compare<(T, U, V, W, X)>>::Error>

§

impl<T, C> Compare<Box<T>> for C
where + C: Compare<T>,

§

type Error = <C as Compare<T>>::Error

§

fn compare( &self, - a: &Box<T>, - b: &Box<T> -) -> Result<Ordering, <C as Compare<Box<T>>>::Error>

§

impl<T, C> Compare<Option<T>> for C
where - C: Compare<T>,

§

type Error = <C as Compare<T>>::Error

§

fn compare( + a: &Box<T>, + b: &Box<T>, +) -> Result<Ordering, <C as Compare<Box<T>>>::Error>

§

impl<T, C> Compare<Option<T>> for C
where + C: Compare<T>,

§

type Error = <C as Compare<T>>::Error

§

fn compare( &self, - a: &Option<T>, - b: &Option<T> -) -> Result<Ordering, <C as Compare<Option<T>>>::Error>

§

impl<T, C> Compare<Rc<T>> for C
where - C: Compare<T>,

§

type Error = <C as Compare<T>>::Error

§

fn compare( + a: &Option<T>, + b: &Option<T>, +) -> Result<Ordering, <C as Compare<Option<T>>>::Error>

§

impl<T, C> Compare<Rc<T>> for C
where + C: Compare<T>,

§

type Error = <C as Compare<T>>::Error

§

fn compare( &self, - a: &Rc<T>, - b: &Rc<T> -) -> Result<Ordering, <C as Compare<Rc<T>>>::Error>

§

impl<T, C> Compare<Vec<T>> for C
where - C: Compare<T>,

§

type Error = <C as Compare<T>>::Error

§

fn compare( + a: &Rc<T>, + b: &Rc<T>, +) -> Result<Ordering, <C as Compare<Rc<T>>>::Error>

§

impl<T, C> Compare<Vec<T>> for C
where + C: Compare<T>,

§

type Error = <C as Compare<T>>::Error

§

fn compare( &self, - a: &Vec<T>, - b: &Vec<T> -) -> Result<Ordering, <C as Compare<Vec<T>>>::Error>

§

impl<T> Downcast for T
where - T: Any,

§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can -then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be -further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot -generate &Any’s vtable from &Trait’s.
§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot + a: &Vec<T>, + b: &Vec<T>, +) -> Result<Ordering, <C as Compare<Vec<T>>>::Error>
§

impl<T> Downcast for T
where + T: Any,

§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can +then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be +further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot +generate &Any’s vtable from &Trait’s.
§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
§

impl<Q, K> Equivalent<K> for Q
where - Q: Eq + ?Sized, - K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
§

impl<Q, K> Equivalent<K> for Q
where - Q: Eq + ?Sized, - K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+ Q: Eq + ?Sized, + K: Borrow<Q> + ?Sized,
§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
§

impl<Q, K> Equivalent<K> for Q
where + Q: Eq + ?Sized, + K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<E, T, U> FromVal<E, T> for U
where E: Env, - U: TryFromVal<E, T>,

§

fn from_val(e: &E, v: &T) -> U

§

impl<T> FromXdr for T
where - T: TryFromVal<Env, Val>,

§

type Error = <T as TryFromVal<Env, Val>>::Error

§

fn from_xdr(env: &Env, b: &Bytes) -> Result<T, <T as FromXdr>::Error>

source§

impl<T, U> Into<U> for T
where - U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+ U: TryFromVal<E, T>,
§

fn from_val(e: &E, v: &T) -> U

§

impl<T> FromXdr for T
where + T: TryFromVal<Env, Val>,

§

type Error = <T as TryFromVal<Env, Val>>::Error

§

fn from_xdr(env: &Env, b: &Bytes) -> Result<T, <T as FromXdr>::Error>

source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

+From<T> for U chooses to do.

§

impl<E, T, U> IntoVal<E, T> for U
where E: Env, - T: FromVal<E, U>,

§

fn into_val(&self, e: &E) -> T

source§

impl<T> Same for T

§

type Output = T

Should always be Self
source§

impl<T> ToOwned for T
where - T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
§

impl<T> ToXdr for T
where - T: IntoVal<Env, Val>,

§

fn to_xdr(self, env: &Env) -> Bytes

source§

impl<T, U> TryFrom<U> for T
where - U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where - U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<E, T, U> TryIntoVal<E, T> for U
where + T: FromVal<E, U>,

§

fn into_val(&self, e: &E) -> T

source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
§

impl<T> ToXdr for T
where + T: IntoVal<Env, Val>,

§

fn to_xdr(self, env: &Env) -> Bytes

source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<E, T, U> TryIntoVal<E, T> for U
where E: Env, - T: TryFromVal<E, U>,

§

type Error = <T as TryFromVal<E, U>>::Error

§

fn try_into_val(&self, env: &E) -> Result<T, <U as TryIntoVal<E, T>>::Error>

§

impl<V, T> VZip<V> for T
where + T: TryFromVal<E, U>,

§

type Error = <T as TryFromVal<E, U>>::Error

§

fn try_into_val(&self, env: &E) -> Result<T, <U as TryIntoVal<E, T>>::Error>

§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

\ No newline at end of file diff --git a/apps/rust_docs/defindex_strategy_core/event/struct.WithdrawEvent.html b/apps/rust_docs/defindex_strategy_core/event/struct.WithdrawEvent.html index ad96f32c..0a5c409b 100644 --- a/apps/rust_docs/defindex_strategy_core/event/struct.WithdrawEvent.html +++ b/apps/rust_docs/defindex_strategy_core/event/struct.WithdrawEvent.html @@ -1,76 +1,76 @@ -WithdrawEvent in defindex_strategy_core::event - Rust

Struct defindex_strategy_core::event::WithdrawEvent

source ·
pub struct WithdrawEvent {
-    pub amount: i128,
+WithdrawEvent in defindex_strategy_core::event - Rust

Struct defindex_strategy_core::event::WithdrawEvent

source ·
pub struct WithdrawEvent {
+    pub amount: i128,
     pub from: Address,
-}

Fields§

§amount: i128§from: Address

Implementations§

source§

impl WithdrawEvent

source

pub const fn spec_xdr() -> [u8; 72]

Trait Implementations§

source§

impl Clone for WithdrawEvent

source§

fn clone(&self) -> WithdrawEvent

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for WithdrawEvent

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl PartialEq for WithdrawEvent

source§

fn eq(&self, other: &WithdrawEvent) -> bool

This method tests for self and other values to be equal, and is used -by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason.
source§

impl TryFromVal<Env, Val> for WithdrawEvent

§

type Error = ConversionError

source§

fn try_from_val(env: &Env, val: &Val) -> Result<Self, ConversionError>

source§

impl TryFromVal<Env, WithdrawEvent> for Val

§

type Error = ConversionError

source§

fn try_from_val(env: &Env, val: &WithdrawEvent) -> Result<Self, ConversionError>

source§

impl Eq for WithdrawEvent

source§

impl StructuralPartialEq for WithdrawEvent

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where - T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where - T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where - T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T, C> Compare<&T> for C
where - C: Compare<T>,

§

type Error = <C as Compare<T>>::Error

§

fn compare(&self, a: &&T, b: &&T) -> Result<Ordering, <C as Compare<&T>>::Error>

§

impl<T, U, E, C> Compare<(T, U)> for C
where - C: Compare<T, Error = E, Error = E> + Compare<U>,

§

type Error = E

§

fn compare( +}

Fields§

§amount: i128§from: Address

Implementations§

source§

impl WithdrawEvent

source

pub const fn spec_xdr() -> [u8; 72]

Trait Implementations§

source§

impl Clone for WithdrawEvent

source§

fn clone(&self) -> WithdrawEvent

Returns a copy of the value. Read more
1.0.0 · source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
source§

impl Debug for WithdrawEvent

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl PartialEq for WithdrawEvent

source§

fn eq(&self, other: &WithdrawEvent) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, +and should not be overridden without very good reason.
source§

impl TryFromVal<Env, Val> for WithdrawEvent

source§

type Error = ConversionError

source§

fn try_from_val(env: &Env, val: &Val) -> Result<Self, ConversionError>

source§

impl TryFromVal<Env, WithdrawEvent> for Val

source§

type Error = ConversionError

source§

fn try_from_val(env: &Env, val: &WithdrawEvent) -> Result<Self, ConversionError>

source§

impl Eq for WithdrawEvent

source§

impl StructuralPartialEq for WithdrawEvent

Auto Trait Implementations§

Blanket Implementations§

source§

impl<T> Any for T
where + T: 'static + ?Sized,

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

impl<T> Borrow<T> for T
where + T: ?Sized,

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for T
where + T: ?Sized,

source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
source§

impl<T> CloneToUninit for T
where + T: Clone,

source§

unsafe fn clone_to_uninit(&self, dst: *mut T)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dst. Read more
§

impl<T, C> Compare<&T> for C
where + C: Compare<T>,

§

type Error = <C as Compare<T>>::Error

§

fn compare(&self, a: &&T, b: &&T) -> Result<Ordering, <C as Compare<&T>>::Error>

§

impl<T, U, E, C> Compare<(T, U)> for C
where + C: Compare<T, Error = E, Error = E> + Compare<U>,

§

type Error = E

§

fn compare( &self, - a: &(T, U), - b: &(T, U) -) -> Result<Ordering, <C as Compare<(T, U)>>::Error>

§

impl<T, U, V, E, C> Compare<(T, U, V)> for C
where - C: Compare<T, Error = E, Error = E, Error = E> + Compare<U> + Compare<V>,

§

type Error = E

§

fn compare( + a: &(T, U), + b: &(T, U), +) -> Result<Ordering, <C as Compare<(T, U)>>::Error>

§

impl<T, U, V, E, C> Compare<(T, U, V)> for C
where + C: Compare<T, Error = E, Error = E, Error = E> + Compare<U> + Compare<V>,

§

type Error = E

§

fn compare( &self, - a: &(T, U, V), - b: &(T, U, V) -) -> Result<Ordering, <C as Compare<(T, U, V)>>::Error>

§

impl<T, U, V, W, E, C> Compare<(T, U, V, W)> for C
where - C: Compare<T, Error = E, Error = E, Error = E, Error = E> + Compare<U> + Compare<V> + Compare<W>,

§

type Error = E

§

fn compare( + a: &(T, U, V), + b: &(T, U, V), +) -> Result<Ordering, <C as Compare<(T, U, V)>>::Error>

§

impl<T, U, V, W, E, C> Compare<(T, U, V, W)> for C
where + C: Compare<T, Error = E, Error = E, Error = E, Error = E> + Compare<U> + Compare<V> + Compare<W>,

§

type Error = E

§

fn compare( &self, - a: &(T, U, V, W), - b: &(T, U, V, W) -) -> Result<Ordering, <C as Compare<(T, U, V, W)>>::Error>

§

impl<T, U, V, W, X, E, C> Compare<(T, U, V, W, X)> for C
where - C: Compare<T, Error = E, Error = E, Error = E, Error = E, Error = E> + Compare<U> + Compare<V> + Compare<W> + Compare<X>,

§

type Error = E

§

fn compare( + a: &(T, U, V, W), + b: &(T, U, V, W), +) -> Result<Ordering, <C as Compare<(T, U, V, W)>>::Error>

§

impl<T, U, V, W, X, E, C> Compare<(T, U, V, W, X)> for C
where + C: Compare<T, Error = E, Error = E, Error = E, Error = E, Error = E> + Compare<U> + Compare<V> + Compare<W> + Compare<X>,

§

type Error = E

§

fn compare( &self, - a: &(T, U, V, W, X), - b: &(T, U, V, W, X) -) -> Result<Ordering, <C as Compare<(T, U, V, W, X)>>::Error>

§

impl<T, C> Compare<Box<T>> for C
where - C: Compare<T>,

§

type Error = <C as Compare<T>>::Error

§

fn compare( + a: &(T, U, V, W, X), + b: &(T, U, V, W, X), +) -> Result<Ordering, <C as Compare<(T, U, V, W, X)>>::Error>

§

impl<T, C> Compare<Box<T>> for C
where + C: Compare<T>,

§

type Error = <C as Compare<T>>::Error

§

fn compare( &self, - a: &Box<T>, - b: &Box<T> -) -> Result<Ordering, <C as Compare<Box<T>>>::Error>

§

impl<T, C> Compare<Option<T>> for C
where - C: Compare<T>,

§

type Error = <C as Compare<T>>::Error

§

fn compare( + a: &Box<T>, + b: &Box<T>, +) -> Result<Ordering, <C as Compare<Box<T>>>::Error>

§

impl<T, C> Compare<Option<T>> for C
where + C: Compare<T>,

§

type Error = <C as Compare<T>>::Error

§

fn compare( &self, - a: &Option<T>, - b: &Option<T> -) -> Result<Ordering, <C as Compare<Option<T>>>::Error>

§

impl<T, C> Compare<Rc<T>> for C
where - C: Compare<T>,

§

type Error = <C as Compare<T>>::Error

§

fn compare( + a: &Option<T>, + b: &Option<T>, +) -> Result<Ordering, <C as Compare<Option<T>>>::Error>

§

impl<T, C> Compare<Rc<T>> for C
where + C: Compare<T>,

§

type Error = <C as Compare<T>>::Error

§

fn compare( &self, - a: &Rc<T>, - b: &Rc<T> -) -> Result<Ordering, <C as Compare<Rc<T>>>::Error>

§

impl<T, C> Compare<Vec<T>> for C
where - C: Compare<T>,

§

type Error = <C as Compare<T>>::Error

§

fn compare( + a: &Rc<T>, + b: &Rc<T>, +) -> Result<Ordering, <C as Compare<Rc<T>>>::Error>

§

impl<T, C> Compare<Vec<T>> for C
where + C: Compare<T>,

§

type Error = <C as Compare<T>>::Error

§

fn compare( &self, - a: &Vec<T>, - b: &Vec<T> -) -> Result<Ordering, <C as Compare<Vec<T>>>::Error>

§

impl<T> Downcast for T
where - T: Any,

§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can -then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be -further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot -generate &Any’s vtable from &Trait’s.
§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot + a: &Vec<T>, + b: &Vec<T>, +) -> Result<Ordering, <C as Compare<Vec<T>>>::Error>
§

impl<T> Downcast for T
where + T: Any,

§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can +then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be +further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot +generate &Any’s vtable from &Trait’s.
§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
§

impl<Q, K> Equivalent<K> for Q
where - Q: Eq + ?Sized, - K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
§

impl<Q, K> Equivalent<K> for Q
where - Q: Eq + ?Sized, - K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

+ Q: Eq + ?Sized, + K: Borrow<Q> + ?Sized,
§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
§

impl<Q, K> Equivalent<K> for Q
where + Q: Eq + ?Sized, + K: Borrow<Q> + ?Sized,

§

fn equivalent(&self, key: &K) -> bool

Compare self to key and return true if they are equal.
source§

impl<T> From<T> for T

source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<E, T, U> FromVal<E, T> for U
where E: Env, - U: TryFromVal<E, T>,

§

fn from_val(e: &E, v: &T) -> U

§

impl<T> FromXdr for T
where - T: TryFromVal<Env, Val>,

§

type Error = <T as TryFromVal<Env, Val>>::Error

§

fn from_xdr(env: &Env, b: &Bytes) -> Result<T, <T as FromXdr>::Error>

source§

impl<T, U> Into<U> for T
where - U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

+ U: TryFromVal<E, T>,
§

fn from_val(e: &E, v: &T) -> U

§

impl<T> FromXdr for T
where + T: TryFromVal<Env, Val>,

§

type Error = <T as TryFromVal<Env, Val>>::Error

§

fn from_xdr(env: &Env, b: &Bytes) -> Result<T, <T as FromXdr>::Error>

source§

impl<T, U> Into<U> for T
where + U: From<T>,

source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

+From<T> for U chooses to do.

§

impl<E, T, U> IntoVal<E, T> for U
where E: Env, - T: FromVal<E, U>,

§

fn into_val(&self, e: &E) -> T

source§

impl<T> Same for T

§

type Output = T

Should always be Self
source§

impl<T> ToOwned for T
where - T: Clone,

§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
§

impl<T> ToXdr for T
where - T: IntoVal<Env, Val>,

§

fn to_xdr(self, env: &Env) -> Bytes

source§

impl<T, U> TryFrom<U> for T
where - U: Into<T>,

§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where - U: TryFrom<T>,

§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<E, T, U> TryIntoVal<E, T> for U
where + T: FromVal<E, U>,

§

fn into_val(&self, e: &E) -> T

source§

impl<T> Same for T

source§

type Output = T

Should always be Self
source§

impl<T> ToOwned for T
where + T: Clone,

source§

type Owned = T

The resulting type after obtaining ownership.
source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
§

impl<T> ToXdr for T
where + T: IntoVal<Env, Val>,

§

fn to_xdr(self, env: &Env) -> Bytes

source§

impl<T, U> TryFrom<U> for T
where + U: Into<T>,

source§

type Error = Infallible

The type returned in the event of a conversion error.
source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

impl<T, U> TryInto<U> for T
where + U: TryFrom<T>,

source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<E, T, U> TryIntoVal<E, T> for U
where E: Env, - T: TryFromVal<E, U>,

§

type Error = <T as TryFromVal<E, U>>::Error

§

fn try_into_val(&self, env: &E) -> Result<T, <U as TryIntoVal<E, T>>::Error>

§

impl<V, T> VZip<V> for T
where + T: TryFromVal<E, U>,

§

type Error = <T as TryFromVal<E, U>>::Error

§

fn try_into_val(&self, env: &E) -> Result<T, <U as TryIntoVal<E, T>>::Error>

§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

\ No newline at end of file diff --git a/apps/rust_docs/defindex_strategy_core/index.html b/apps/rust_docs/defindex_strategy_core/index.html index 4e7631ce..7f6a0e52 100644 --- a/apps/rust_docs/defindex_strategy_core/index.html +++ b/apps/rust_docs/defindex_strategy_core/index.html @@ -1,3 +1,3 @@ -defindex_strategy_core - Rust

Crate defindex_strategy_core

source ·

Modules§

  • This module defines the events used in the strategy. +defindex_strategy_core - Rust

    Crate defindex_strategy_core

    source ·

    Modules§

    • This module defines the events used in the strategy. These events must be emitted by the strategy implementation -to ensure compliance with the expected event interface.

    Structs§

    Enums§

    Traits§

    \ No newline at end of file +to ensure compliance with the expected event interface.

Structs§

Enums§

Traits§

\ No newline at end of file diff --git a/apps/rust_docs/defindex_strategy_core/struct.DeFindexStrategyClient.html b/apps/rust_docs/defindex_strategy_core/struct.DeFindexStrategyClient.html index cf8f273f..cb87ebb1 100644 --- a/apps/rust_docs/defindex_strategy_core/struct.DeFindexStrategyClient.html +++ b/apps/rust_docs/defindex_strategy_core/struct.DeFindexStrategyClient.html @@ -1,10 +1,10 @@ -DeFindexStrategyClient in defindex_strategy_core - Rust
pub struct DeFindexStrategyClient<'a> {
+DeFindexStrategyClient in defindex_strategy_core - Rust
pub struct DeFindexStrategyClient<'a> {
     pub env: Env,
     pub address: Address,
     /* private fields */
 }
Expand description

DeFindexStrategyClient is a client for calling the contract defined in “DeFindexStrategyTrait”.

Fields§

§env: Env§address: Address

Implementations§

source§

impl<'a> DeFindexStrategyClient<'a>

source

pub fn new(env: &Env, address: &Address) -> Self

source§

impl<'a> DeFindexStrategyClient<'a>

source

pub fn initialize(&self, asset: &Address, init_args: &Vec<Val>)

Initializes the strategy with the given parameters.

-

This function is called to initialize the strategy with the required parameters. +

This function is called to initialize the strategy with the required parameters. It sets up the strategy’s underlying asset and any additional parameters required for the strategy.

§Parameters
    @@ -20,9 +20,9 @@
    §Returns
source

pub fn try_initialize( &self, asset: &Address, - init_args: &Vec<Val> -) -> Result<Result<(), <() as TryFromVal<Env, Val>>::Error>, Result<StrategyError, InvokeError>>

Initializes the strategy with the given parameters.

-

This function is called to initialize the strategy with the required parameters. + init_args: &Vec<Val>, +) -> Result<Result<(), <() as TryFromVal<Env, Val>>::Error>, Result<StrategyError, InvokeError>>

Initializes the strategy with the given parameters.

+

This function is called to initialize the strategy with the required parameters. It sets up the strategy’s underlying asset and any additional parameters required for the strategy.

§Parameters
    @@ -36,7 +36,7 @@
    §Returns
  • Err(StrategyError) if an error occurs during initialization.
source

pub fn asset(&self) -> Address

Returns the underlying asset address managed by the strategy.

-

This function provides the address of the asset that this strategy is managing. It is used +

This function provides the address of the asset that this strategy is managing. It is used by the DeFindex vault to determine which asset is associated with this strategy.

§Parameters
    @@ -48,9 +48,9 @@
    §Returns
  • Err(StrategyError) if the asset address cannot be retrieved.
source

pub fn try_asset( - &self -) -> Result<Result<Address, <Address as TryFromVal<Env, Val>>::Error>, Result<StrategyError, InvokeError>>

Returns the underlying asset address managed by the strategy.

-

This function provides the address of the asset that this strategy is managing. It is used + &self, +) -> Result<Result<Address, <Address as TryFromVal<Env, Val>>::Error>, Result<StrategyError, InvokeError>>

Returns the underlying asset address managed by the strategy.

+

This function provides the address of the asset that this strategy is managing. It is used by the DeFindex vault to determine which asset is associated with this strategy.

§Parameters
    @@ -61,7 +61,7 @@
    §Returns
  • Ok(Address) containing the asset address.
  • Err(StrategyError) if the asset address cannot be retrieved.
-
source

pub fn deposit(&self, amount: &i128, from: &Address)

Deposits the specified amount of the asset into the strategy.

+
source

pub fn deposit(&self, amount: &i128, from: &Address)

Deposits the specified amount of the asset into the strategy.

This function allows the DeFindex vault to deposit assets into the strategy.

§Parameters
    @@ -76,9 +76,9 @@
    §Returns
source

pub fn try_deposit( &self, - amount: &i128, - from: &Address -) -> Result<Result<(), <() as TryFromVal<Env, Val>>::Error>, Result<StrategyError, InvokeError>>

Deposits the specified amount of the asset into the strategy.

+ amount: &i128, + from: &Address, +) -> Result<Result<(), <() as TryFromVal<Env, Val>>::Error>, Result<StrategyError, InvokeError>>

Deposits the specified amount of the asset into the strategy.

This function allows the DeFindex vault to deposit assets into the strategy.

§Parameters
    @@ -107,8 +107,8 @@
    §Returns
source

pub fn try_harvest( &self, - from: &Address -) -> Result<Result<(), <() as TryFromVal<Env, Val>>::Error>, Result<StrategyError, InvokeError>>

Harvests yields generated by the strategy.

+ from: &Address, +) -> Result<Result<(), <() as TryFromVal<Env, Val>>::Error>, Result<StrategyError, InvokeError>>

Harvests yields generated by the strategy.

This function triggers any necessary actions required to generate or claim yields from the underlying DeFi protocol or strategy. It can be used to reinvest rewards, claim interest, or perform other actions that maximize returns.

@@ -122,8 +122,8 @@
§Returns
  • Ok(()) if the harvest is successful.
  • Err(StrategyError) if the harvest fails.
  • -
    source

    pub fn balance(&self, from: &Address) -> i128

    Returns the current balance of the underlying asset in the strategy.

    -

    This function provides the current balance of the underlying asset that is managed by +

    source

    pub fn balance(&self, from: &Address) -> i128

    Returns the current balance of the underlying asset in the strategy.

    +

    This function provides the current balance of the underlying asset that is managed by the strategy on behalf of the specified address. It is used to track the assets held in the strategy.

    §Parameters
      @@ -137,9 +137,9 @@
      §Returns
    source

    pub fn try_balance( &self, - from: &Address -) -> Result<Result<i128, <i128 as TryFromVal<Env, Val>>::Error>, Result<StrategyError, InvokeError>>

    Returns the current balance of the underlying asset in the strategy.

    -

    This function provides the current balance of the underlying asset that is managed by + from: &Address, +) -> Result<Result<i128, <i128 as TryFromVal<Env, Val>>::Error>, Result<StrategyError, InvokeError>>

    Returns the current balance of the underlying asset in the strategy.

    +

    This function provides the current balance of the underlying asset that is managed by the strategy on behalf of the specified address. It is used to track the assets held in the strategy.

    §Parameters
      @@ -151,7 +151,7 @@
      §Returns
    • Ok(i128) containing the balance of the underlying asset.
    • Err(StrategyError) if the balance cannot be retrieved.
    -
    source

    pub fn withdraw(&self, amount: &i128, from: &Address) -> i128

    Withdraws the specified amount of the underlying asset from the strategy.

    +
    source

    pub fn withdraw(&self, amount: &i128, from: &Address) -> i128

    Withdraws the specified amount of the underlying asset from the strategy.

    This function allows the DeFindex vault to withdraw assets from the strategy.

    §Parameters
      @@ -166,9 +166,9 @@
      §Returns
    source

    pub fn try_withdraw( &self, - amount: &i128, - from: &Address -) -> Result<Result<i128, <i128 as TryFromVal<Env, Val>>::Error>, Result<StrategyError, InvokeError>>

    Withdraws the specified amount of the underlying asset from the strategy.

    + amount: &i128, + from: &Address, +) -> Result<Result<i128, <i128 as TryFromVal<Env, Val>>::Error>, Result<StrategyError, InvokeError>>

    Withdraws the specified amount of the underlying asset from the strategy.

    This function allows the DeFindex vault to withdraw assets from the strategy.

    §Parameters
      @@ -181,65 +181,65 @@
      §Returns
    • Ok(i128) containing the amount withdrawn.
    • Err(StrategyError) if the withdrawal fails (e.g., insufficient balance).
    -

    Auto Trait Implementations§

    Blanket Implementations§

    source§

    impl<T> Any for T
    where - T: 'static + ?Sized,

    source§

    fn type_id(&self) -> TypeId

    Gets the TypeId of self. Read more
    source§

    impl<T> Borrow<T> for T
    where - T: ?Sized,

    source§

    fn borrow(&self) -> &T

    Immutably borrows from an owned value. Read more
    source§

    impl<T> BorrowMut<T> for T
    where - T: ?Sized,

    source§

    fn borrow_mut(&mut self) -> &mut T

    Mutably borrows from an owned value. Read more
    §

    impl<T, C> Compare<&T> for C
    where - C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare(&self, a: &&T, b: &&T) -> Result<Ordering, <C as Compare<&T>>::Error>

    §

    impl<T, U, E, C> Compare<(T, U)> for C
    where - C: Compare<T, Error = E, Error = E> + Compare<U>,

    §

    type Error = E

    §

    fn compare( +

    Auto Trait Implementations§

    Blanket Implementations§

    source§

    impl<T> Any for T
    where + T: 'static + ?Sized,

    source§

    fn type_id(&self) -> TypeId

    Gets the TypeId of self. Read more
    source§

    impl<T> Borrow<T> for T
    where + T: ?Sized,

    source§

    fn borrow(&self) -> &T

    Immutably borrows from an owned value. Read more
    source§

    impl<T> BorrowMut<T> for T
    where + T: ?Sized,

    source§

    fn borrow_mut(&mut self) -> &mut T

    Mutably borrows from an owned value. Read more
    §

    impl<T, C> Compare<&T> for C
    where + C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare(&self, a: &&T, b: &&T) -> Result<Ordering, <C as Compare<&T>>::Error>

    §

    impl<T, U, E, C> Compare<(T, U)> for C
    where + C: Compare<T, Error = E, Error = E> + Compare<U>,

    §

    type Error = E

    §

    fn compare( &self, - a: &(T, U), - b: &(T, U) -) -> Result<Ordering, <C as Compare<(T, U)>>::Error>

    §

    impl<T, U, V, E, C> Compare<(T, U, V)> for C
    where - C: Compare<T, Error = E, Error = E, Error = E> + Compare<U> + Compare<V>,

    §

    type Error = E

    §

    fn compare( + a: &(T, U), + b: &(T, U), +) -> Result<Ordering, <C as Compare<(T, U)>>::Error>

    §

    impl<T, U, V, E, C> Compare<(T, U, V)> for C
    where + C: Compare<T, Error = E, Error = E, Error = E> + Compare<U> + Compare<V>,

    §

    type Error = E

    §

    fn compare( &self, - a: &(T, U, V), - b: &(T, U, V) -) -> Result<Ordering, <C as Compare<(T, U, V)>>::Error>

    §

    impl<T, U, V, W, E, C> Compare<(T, U, V, W)> for C
    where - C: Compare<T, Error = E, Error = E, Error = E, Error = E> + Compare<U> + Compare<V> + Compare<W>,

    §

    type Error = E

    §

    fn compare( + a: &(T, U, V), + b: &(T, U, V), +) -> Result<Ordering, <C as Compare<(T, U, V)>>::Error>

    §

    impl<T, U, V, W, E, C> Compare<(T, U, V, W)> for C
    where + C: Compare<T, Error = E, Error = E, Error = E, Error = E> + Compare<U> + Compare<V> + Compare<W>,

    §

    type Error = E

    §

    fn compare( &self, - a: &(T, U, V, W), - b: &(T, U, V, W) -) -> Result<Ordering, <C as Compare<(T, U, V, W)>>::Error>

    §

    impl<T, U, V, W, X, E, C> Compare<(T, U, V, W, X)> for C
    where - C: Compare<T, Error = E, Error = E, Error = E, Error = E, Error = E> + Compare<U> + Compare<V> + Compare<W> + Compare<X>,

    §

    type Error = E

    §

    fn compare( + a: &(T, U, V, W), + b: &(T, U, V, W), +) -> Result<Ordering, <C as Compare<(T, U, V, W)>>::Error>

    §

    impl<T, U, V, W, X, E, C> Compare<(T, U, V, W, X)> for C
    where + C: Compare<T, Error = E, Error = E, Error = E, Error = E, Error = E> + Compare<U> + Compare<V> + Compare<W> + Compare<X>,

    §

    type Error = E

    §

    fn compare( &self, - a: &(T, U, V, W, X), - b: &(T, U, V, W, X) -) -> Result<Ordering, <C as Compare<(T, U, V, W, X)>>::Error>

    §

    impl<T, C> Compare<Box<T>> for C
    where - C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare( + a: &(T, U, V, W, X), + b: &(T, U, V, W, X), +) -> Result<Ordering, <C as Compare<(T, U, V, W, X)>>::Error>

    §

    impl<T, C> Compare<Box<T>> for C
    where + C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare( &self, - a: &Box<T>, - b: &Box<T> -) -> Result<Ordering, <C as Compare<Box<T>>>::Error>

    §

    impl<T, C> Compare<Option<T>> for C
    where - C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare( + a: &Box<T>, + b: &Box<T>, +) -> Result<Ordering, <C as Compare<Box<T>>>::Error>

    §

    impl<T, C> Compare<Option<T>> for C
    where + C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare( &self, - a: &Option<T>, - b: &Option<T> -) -> Result<Ordering, <C as Compare<Option<T>>>::Error>

    §

    impl<T, C> Compare<Rc<T>> for C
    where - C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare( + a: &Option<T>, + b: &Option<T>, +) -> Result<Ordering, <C as Compare<Option<T>>>::Error>

    §

    impl<T, C> Compare<Rc<T>> for C
    where + C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare( &self, - a: &Rc<T>, - b: &Rc<T> -) -> Result<Ordering, <C as Compare<Rc<T>>>::Error>

    §

    impl<T, C> Compare<Vec<T>> for C
    where - C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare( + a: &Rc<T>, + b: &Rc<T>, +) -> Result<Ordering, <C as Compare<Rc<T>>>::Error>

    §

    impl<T, C> Compare<Vec<T>> for C
    where + C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare( &self, - a: &Vec<T>, - b: &Vec<T> -) -> Result<Ordering, <C as Compare<Vec<T>>>::Error>

    §

    impl<T> Downcast for T
    where - T: Any,

    §

    fn into_any(self: Box<T>) -> Box<dyn Any>

    Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can -then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
    §

    fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

    Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be -further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
    §

    fn as_any(&self) -> &(dyn Any + 'static)

    Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot -generate &Any’s vtable from &Trait’s.
    §

    fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

    Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot -generate &mut Any’s vtable from &mut Trait’s.
    source§

    impl<T> From<T> for T

    source§

    fn from(t: T) -> T

    Returns the argument unchanged.

    -
    source§

    impl<T, U> Into<U> for T
    where - U: From<T>,

    source§

    fn into(self) -> U

    Calls U::from(self).

    + a: &Vec<T>, + b: &Vec<T>, +) -> Result<Ordering, <C as Compare<Vec<T>>>::Error>
    §

    impl<T> Downcast for T
    where + T: Any,

    §

    fn into_any(self: Box<T>) -> Box<dyn Any>

    Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can +then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
    §

    fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

    Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be +further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
    §

    fn as_any(&self) -> &(dyn Any + 'static)

    Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot +generate &Any’s vtable from &Trait’s.
    §

    fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

    Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot +generate &mut Any’s vtable from &mut Trait’s.
    source§

    impl<T> From<T> for T

    source§

    fn from(t: T) -> T

    Returns the argument unchanged.

    +
    source§

    impl<T, U> Into<U> for T
    where + U: From<T>,

    source§

    fn into(self) -> U

    Calls U::from(self).

    That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

    +From<T> for U chooses to do.

    §

    impl<E, T, U> IntoVal<E, T> for U
    where E: Env, - T: FromVal<E, U>,

    §

    fn into_val(&self, e: &E) -> T

    source§

    impl<T> Same for T

    §

    type Output = T

    Should always be Self
    source§

    impl<T, U> TryFrom<U> for T
    where - U: Into<T>,

    §

    type Error = Infallible

    The type returned in the event of a conversion error.
    source§

    fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

    Performs the conversion.
    source§

    impl<T, U> TryInto<U> for T
    where - U: TryFrom<T>,

    §

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.
    source§

    fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

    Performs the conversion.
    §

    impl<E, T, U> TryIntoVal<E, T> for U
    where + T: FromVal<E, U>,

    §

    fn into_val(&self, e: &E) -> T

    source§

    impl<T> Same for T

    source§

    type Output = T

    Should always be Self
    source§

    impl<T, U> TryFrom<U> for T
    where + U: Into<T>,

    source§

    type Error = Infallible

    The type returned in the event of a conversion error.
    source§

    fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

    Performs the conversion.
    source§

    impl<T, U> TryInto<U> for T
    where + U: TryFrom<T>,

    source§

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.
    source§

    fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

    Performs the conversion.
    §

    impl<E, T, U> TryIntoVal<E, T> for U
    where E: Env, - T: TryFromVal<E, U>,

    §

    type Error = <T as TryFromVal<E, U>>::Error

    §

    fn try_into_val(&self, env: &E) -> Result<T, <U as TryIntoVal<E, T>>::Error>

    §

    impl<V, T> VZip<V> for T
    where + T: TryFromVal<E, U>,

    §

    type Error = <T as TryFromVal<E, U>>::Error

    §

    fn try_into_val(&self, env: &E) -> Result<T, <U as TryIntoVal<E, T>>::Error>

    §

    impl<V, T> VZip<V> for T
    where V: MultiLane<T>,

    §

    fn vzip(self) -> V

    \ No newline at end of file diff --git a/apps/rust_docs/defindex_strategy_core/struct.Spec.html b/apps/rust_docs/defindex_strategy_core/struct.Spec.html index c07fcb62..c5f63936 100644 --- a/apps/rust_docs/defindex_strategy_core/struct.Spec.html +++ b/apps/rust_docs/defindex_strategy_core/struct.Spec.html @@ -1,5 +1,5 @@ -Spec in defindex_strategy_core - Rust

    Struct defindex_strategy_core::Spec

    source ·
    pub struct Spec;

    Implementations§

    source§

    impl Spec

    source

    pub const fn spec_xdr_initialize() -> [u8; 752]

    Initializes the strategy with the given parameters.

    -

    This function is called to initialize the strategy with the required parameters. +Spec in defindex_strategy_core - Rust

    Struct defindex_strategy_core::Spec

    source ·
    pub struct Spec;

    Implementations§

    source§

    impl Spec

    source

    pub const fn spec_xdr_initialize() -> [u8; 752]

    Initializes the strategy with the given parameters.

    +

    This function is called to initialize the strategy with the required parameters. It sets up the strategy’s underlying asset and any additional parameters required for the strategy.

    §Parameters
      @@ -12,8 +12,8 @@
      §Returns
    • Ok(()) if the strategy is successfully initialized.
    • Err(StrategyError) if an error occurs during initialization.
    -
    source§

    impl Spec

    source

    pub const fn spec_xdr_asset() -> [u8; 468]

    Returns the underlying asset address managed by the strategy.

    -

    This function provides the address of the asset that this strategy is managing. It is used +

    source§

    impl Spec

    source

    pub const fn spec_xdr_asset() -> [u8; 468]

    Returns the underlying asset address managed by the strategy.

    +

    This function provides the address of the asset that this strategy is managing. It is used by the DeFindex vault to determine which asset is associated with this strategy.

    §Parameters
      @@ -24,7 +24,7 @@
      §Returns
    • Ok(Address) containing the asset address.
    • Err(StrategyError) if the asset address cannot be retrieved.
    -
    source§

    impl Spec

    source

    pub const fn spec_xdr_deposit() -> [u8; 572]

    Deposits the specified amount of the asset into the strategy.

    +
    source§

    impl Spec

    source

    pub const fn spec_xdr_deposit() -> [u8; 572]

    Deposits the specified amount of the asset into the strategy.

    This function allows the DeFindex vault to deposit assets into the strategy.

    §Parameters
      @@ -37,7 +37,7 @@
      §Returns
    • Ok(()) if the deposit is successful.
    • Err(StrategyError) if the deposit fails for any reason.
    -
    source§

    impl Spec

    source

    pub const fn spec_xdr_harvest() -> [u8; 584]

    Harvests yields generated by the strategy.

    +
    source§

    impl Spec

    source

    pub const fn spec_xdr_harvest() -> [u8; 584]

    Harvests yields generated by the strategy.

    This function triggers any necessary actions required to generate or claim yields from the underlying DeFi protocol or strategy. It can be used to reinvest rewards, claim interest, or perform other actions that maximize returns.

    @@ -51,8 +51,8 @@
    §Returns
  • Ok(()) if the harvest is successful.
  • Err(StrategyError) if the harvest fails.
  • -
    source§

    impl Spec

    source

    pub const fn spec_xdr_balance() -> [u8; 600]

    Returns the current balance of the underlying asset in the strategy.

    -

    This function provides the current balance of the underlying asset that is managed by +

    source§

    impl Spec

    source

    pub const fn spec_xdr_balance() -> [u8; 600]

    Returns the current balance of the underlying asset in the strategy.

    +

    This function provides the current balance of the underlying asset that is managed by the strategy on behalf of the specified address. It is used to track the assets held in the strategy.

    §Parameters
      @@ -64,7 +64,7 @@
      §Returns
    • Ok(i128) containing the balance of the underlying asset.
    • Err(StrategyError) if the balance cannot be retrieved.
    -
    source§

    impl Spec

    source

    pub const fn spec_xdr_withdraw() -> [u8; 580]

    Withdraws the specified amount of the underlying asset from the strategy.

    +
    source§

    impl Spec

    source

    pub const fn spec_xdr_withdraw() -> [u8; 580]

    Withdraws the specified amount of the underlying asset from the strategy.

    This function allows the DeFindex vault to withdraw assets from the strategy.

    §Parameters
      @@ -77,67 +77,67 @@
      §Returns
    • Ok(i128) containing the amount withdrawn.
    • Err(StrategyError) if the withdrawal fails (e.g., insufficient balance).
    -

    Auto Trait Implementations§

    §

    impl Freeze for Spec

    §

    impl RefUnwindSafe for Spec

    §

    impl Send for Spec

    §

    impl Sync for Spec

    §

    impl Unpin for Spec

    §

    impl UnwindSafe for Spec

    Blanket Implementations§

    source§

    impl<T> Any for T
    where - T: 'static + ?Sized,

    source§

    fn type_id(&self) -> TypeId

    Gets the TypeId of self. Read more
    source§

    impl<T> Borrow<T> for T
    where - T: ?Sized,

    source§

    fn borrow(&self) -> &T

    Immutably borrows from an owned value. Read more
    source§

    impl<T> BorrowMut<T> for T
    where - T: ?Sized,

    source§

    fn borrow_mut(&mut self) -> &mut T

    Mutably borrows from an owned value. Read more
    §

    impl<T, C> Compare<&T> for C
    where - C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare(&self, a: &&T, b: &&T) -> Result<Ordering, <C as Compare<&T>>::Error>

    §

    impl<T, U, E, C> Compare<(T, U)> for C
    where - C: Compare<T, Error = E, Error = E> + Compare<U>,

    §

    type Error = E

    §

    fn compare( +

    Auto Trait Implementations§

    §

    impl Freeze for Spec

    §

    impl RefUnwindSafe for Spec

    §

    impl Send for Spec

    §

    impl Sync for Spec

    §

    impl Unpin for Spec

    §

    impl UnwindSafe for Spec

    Blanket Implementations§

    source§

    impl<T> Any for T
    where + T: 'static + ?Sized,

    source§

    fn type_id(&self) -> TypeId

    Gets the TypeId of self. Read more
    source§

    impl<T> Borrow<T> for T
    where + T: ?Sized,

    source§

    fn borrow(&self) -> &T

    Immutably borrows from an owned value. Read more
    source§

    impl<T> BorrowMut<T> for T
    where + T: ?Sized,

    source§

    fn borrow_mut(&mut self) -> &mut T

    Mutably borrows from an owned value. Read more
    §

    impl<T, C> Compare<&T> for C
    where + C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare(&self, a: &&T, b: &&T) -> Result<Ordering, <C as Compare<&T>>::Error>

    §

    impl<T, U, E, C> Compare<(T, U)> for C
    where + C: Compare<T, Error = E, Error = E> + Compare<U>,

    §

    type Error = E

    §

    fn compare( &self, - a: &(T, U), - b: &(T, U) -) -> Result<Ordering, <C as Compare<(T, U)>>::Error>

    §

    impl<T, U, V, E, C> Compare<(T, U, V)> for C
    where - C: Compare<T, Error = E, Error = E, Error = E> + Compare<U> + Compare<V>,

    §

    type Error = E

    §

    fn compare( + a: &(T, U), + b: &(T, U), +) -> Result<Ordering, <C as Compare<(T, U)>>::Error>

    §

    impl<T, U, V, E, C> Compare<(T, U, V)> for C
    where + C: Compare<T, Error = E, Error = E, Error = E> + Compare<U> + Compare<V>,

    §

    type Error = E

    §

    fn compare( &self, - a: &(T, U, V), - b: &(T, U, V) -) -> Result<Ordering, <C as Compare<(T, U, V)>>::Error>

    §

    impl<T, U, V, W, E, C> Compare<(T, U, V, W)> for C
    where - C: Compare<T, Error = E, Error = E, Error = E, Error = E> + Compare<U> + Compare<V> + Compare<W>,

    §

    type Error = E

    §

    fn compare( + a: &(T, U, V), + b: &(T, U, V), +) -> Result<Ordering, <C as Compare<(T, U, V)>>::Error>

    §

    impl<T, U, V, W, E, C> Compare<(T, U, V, W)> for C
    where + C: Compare<T, Error = E, Error = E, Error = E, Error = E> + Compare<U> + Compare<V> + Compare<W>,

    §

    type Error = E

    §

    fn compare( &self, - a: &(T, U, V, W), - b: &(T, U, V, W) -) -> Result<Ordering, <C as Compare<(T, U, V, W)>>::Error>

    §

    impl<T, U, V, W, X, E, C> Compare<(T, U, V, W, X)> for C
    where - C: Compare<T, Error = E, Error = E, Error = E, Error = E, Error = E> + Compare<U> + Compare<V> + Compare<W> + Compare<X>,

    §

    type Error = E

    §

    fn compare( + a: &(T, U, V, W), + b: &(T, U, V, W), +) -> Result<Ordering, <C as Compare<(T, U, V, W)>>::Error>

    §

    impl<T, U, V, W, X, E, C> Compare<(T, U, V, W, X)> for C
    where + C: Compare<T, Error = E, Error = E, Error = E, Error = E, Error = E> + Compare<U> + Compare<V> + Compare<W> + Compare<X>,

    §

    type Error = E

    §

    fn compare( &self, - a: &(T, U, V, W, X), - b: &(T, U, V, W, X) -) -> Result<Ordering, <C as Compare<(T, U, V, W, X)>>::Error>

    §

    impl<T, C> Compare<Box<T>> for C
    where - C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare( + a: &(T, U, V, W, X), + b: &(T, U, V, W, X), +) -> Result<Ordering, <C as Compare<(T, U, V, W, X)>>::Error>

    §

    impl<T, C> Compare<Box<T>> for C
    where + C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare( &self, - a: &Box<T>, - b: &Box<T> -) -> Result<Ordering, <C as Compare<Box<T>>>::Error>

    §

    impl<T, C> Compare<Option<T>> for C
    where - C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare( + a: &Box<T>, + b: &Box<T>, +) -> Result<Ordering, <C as Compare<Box<T>>>::Error>

    §

    impl<T, C> Compare<Option<T>> for C
    where + C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare( &self, - a: &Option<T>, - b: &Option<T> -) -> Result<Ordering, <C as Compare<Option<T>>>::Error>

    §

    impl<T, C> Compare<Rc<T>> for C
    where - C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare( + a: &Option<T>, + b: &Option<T>, +) -> Result<Ordering, <C as Compare<Option<T>>>::Error>

    §

    impl<T, C> Compare<Rc<T>> for C
    where + C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare( &self, - a: &Rc<T>, - b: &Rc<T> -) -> Result<Ordering, <C as Compare<Rc<T>>>::Error>

    §

    impl<T, C> Compare<Vec<T>> for C
    where - C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare( + a: &Rc<T>, + b: &Rc<T>, +) -> Result<Ordering, <C as Compare<Rc<T>>>::Error>

    §

    impl<T, C> Compare<Vec<T>> for C
    where + C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare( &self, - a: &Vec<T>, - b: &Vec<T> -) -> Result<Ordering, <C as Compare<Vec<T>>>::Error>

    §

    impl<T> Downcast for T
    where - T: Any,

    §

    fn into_any(self: Box<T>) -> Box<dyn Any>

    Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can -then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
    §

    fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

    Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be -further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
    §

    fn as_any(&self) -> &(dyn Any + 'static)

    Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot -generate &Any’s vtable from &Trait’s.
    §

    fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

    Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot + a: &Vec<T>, + b: &Vec<T>, +) -> Result<Ordering, <C as Compare<Vec<T>>>::Error>
    §

    impl<T> Downcast for T
    where + T: Any,

    §

    fn into_any(self: Box<T>) -> Box<dyn Any>

    Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can +then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
    §

    fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

    Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be +further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
    §

    fn as_any(&self) -> &(dyn Any + 'static)

    Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot +generate &Any’s vtable from &Trait’s.
    §

    fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

    Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
    §

    impl<T> DowncastSync for T
    where - T: Any + Send + Sync,

    §

    fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>

    Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be -further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
    source§

    impl<T> From<T> for T

    source§

    fn from(t: T) -> T

    Returns the argument unchanged.

    -
    source§

    impl<T, U> Into<U> for T
    where - U: From<T>,

    source§

    fn into(self) -> U

    Calls U::from(self).

    + T: Any + Send + Sync,
    §

    fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>

    Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be +further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
    source§

    impl<T> From<T> for T

    source§

    fn from(t: T) -> T

    Returns the argument unchanged.

    +
    source§

    impl<T, U> Into<U> for T
    where + U: From<T>,

    source§

    fn into(self) -> U

    Calls U::from(self).

    That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

    +From<T> for U chooses to do.

    §

    impl<E, T, U> IntoVal<E, T> for U
    where E: Env, - T: FromVal<E, U>,

    §

    fn into_val(&self, e: &E) -> T

    source§

    impl<T> Same for T

    §

    type Output = T

    Should always be Self
    source§

    impl<T, U> TryFrom<U> for T
    where - U: Into<T>,

    §

    type Error = Infallible

    The type returned in the event of a conversion error.
    source§

    fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

    Performs the conversion.
    source§

    impl<T, U> TryInto<U> for T
    where - U: TryFrom<T>,

    §

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.
    source§

    fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

    Performs the conversion.
    §

    impl<E, T, U> TryIntoVal<E, T> for U
    where + T: FromVal<E, U>,

    §

    fn into_val(&self, e: &E) -> T

    source§

    impl<T> Same for T

    source§

    type Output = T

    Should always be Self
    source§

    impl<T, U> TryFrom<U> for T
    where + U: Into<T>,

    source§

    type Error = Infallible

    The type returned in the event of a conversion error.
    source§

    fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

    Performs the conversion.
    source§

    impl<T, U> TryInto<U> for T
    where + U: TryFrom<T>,

    source§

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.
    source§

    fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

    Performs the conversion.
    §

    impl<E, T, U> TryIntoVal<E, T> for U
    where E: Env, - T: TryFromVal<E, U>,

    §

    type Error = <T as TryFromVal<E, U>>::Error

    §

    fn try_into_val(&self, env: &E) -> Result<T, <U as TryIntoVal<E, T>>::Error>

    §

    impl<V, T> VZip<V> for T
    where + T: TryFromVal<E, U>,

    §

    type Error = <T as TryFromVal<E, U>>::Error

    §

    fn try_into_val(&self, env: &E) -> Result<T, <U as TryIntoVal<E, T>>::Error>

    §

    impl<V, T> VZip<V> for T
    where V: MultiLane<T>,

    §

    fn vzip(self) -> V

    \ No newline at end of file diff --git a/apps/rust_docs/defindex_strategy_core/trait.DeFindexStrategyTrait.html b/apps/rust_docs/defindex_strategy_core/trait.DeFindexStrategyTrait.html index d302352d..2fb13679 100644 --- a/apps/rust_docs/defindex_strategy_core/trait.DeFindexStrategyTrait.html +++ b/apps/rust_docs/defindex_strategy_core/trait.DeFindexStrategyTrait.html @@ -1,23 +1,23 @@ -DeFindexStrategyTrait in defindex_strategy_core - Rust
    pub trait DeFindexStrategyTrait {
    +DeFindexStrategyTrait in defindex_strategy_core - Rust
    pub trait DeFindexStrategyTrait {
         // Required methods
         fn initialize(
             env: Env,
             asset: Address,
    -        init_args: Vec<Val>
    -    ) -> Result<(), StrategyError>;
    -    fn asset(env: Env) -> Result<Address, StrategyError>;
    +        init_args: Vec<Val>,
    +    ) -> Result<(), StrategyError>;
    +    fn asset(env: Env) -> Result<Address, StrategyError>;
         fn deposit(
             env: Env,
    -        amount: i128,
    -        from: Address
    -    ) -> Result<(), StrategyError>;
    -    fn harvest(env: Env, from: Address) -> Result<(), StrategyError>;
    -    fn balance(env: Env, from: Address) -> Result<i128, StrategyError>;
    +        amount: i128,
    +        from: Address,
    +    ) -> Result<(), StrategyError>;
    +    fn harvest(env: Env, from: Address) -> Result<(), StrategyError>;
    +    fn balance(env: Env, from: Address) -> Result<i128, StrategyError>;
         fn withdraw(
             env: Env,
    -        amount: i128,
    -        from: Address
    -    ) -> Result<i128, StrategyError>;
    +        amount: i128,
    +        from: Address,
    +    ) -> Result<i128, StrategyError>;
     }
    Expand description

    Trait that defines the required methods for implementing a DeFindex strategy.

    Each strategy contract must implement this trait to ensure compatibility with the DeFindex vault. The trait defines essential functions for initialization, asset management, @@ -26,9 +26,9 @@

    Required Methods§

    source

    fn initialize( env: Env, asset: Address, - init_args: Vec<Val> -) -> Result<(), StrategyError>

    Initializes the strategy with the given parameters.

    -

    This function is called to initialize the strategy with the required parameters. + init_args: Vec<Val>, +) -> Result<(), StrategyError>

    Initializes the strategy with the given parameters.

    +

    This function is called to initialize the strategy with the required parameters. It sets up the strategy’s underlying asset and any additional parameters required for the strategy.

    §Parameters
      @@ -41,8 +41,8 @@
      §Returns
    • Ok(()) if the strategy is successfully initialized.
    • Err(StrategyError) if an error occurs during initialization.
    -
    source

    fn asset(env: Env) -> Result<Address, StrategyError>

    Returns the underlying asset address managed by the strategy.

    -

    This function provides the address of the asset that this strategy is managing. It is used +

    source

    fn asset(env: Env) -> Result<Address, StrategyError>

    Returns the underlying asset address managed by the strategy.

    +

    This function provides the address of the asset that this strategy is managing. It is used by the DeFindex vault to determine which asset is associated with this strategy.

    §Parameters
      @@ -53,7 +53,7 @@
      §Returns
    • Ok(Address) containing the asset address.
    • Err(StrategyError) if the asset address cannot be retrieved.
    -
    source

    fn deposit(env: Env, amount: i128, from: Address) -> Result<(), StrategyError>

    Deposits the specified amount of the asset into the strategy.

    +
    source

    fn deposit(env: Env, amount: i128, from: Address) -> Result<(), StrategyError>

    Deposits the specified amount of the asset into the strategy.

    This function allows the DeFindex vault to deposit assets into the strategy.

    §Parameters
      @@ -66,7 +66,7 @@
      §Returns
    • Ok(()) if the deposit is successful.
    • Err(StrategyError) if the deposit fails for any reason.
    -
    source

    fn harvest(env: Env, from: Address) -> Result<(), StrategyError>

    Harvests yields generated by the strategy.

    +
    source

    fn harvest(env: Env, from: Address) -> Result<(), StrategyError>

    Harvests yields generated by the strategy.

    This function triggers any necessary actions required to generate or claim yields from the underlying DeFi protocol or strategy. It can be used to reinvest rewards, claim interest, or perform other actions that maximize returns.

    @@ -80,8 +80,8 @@
    §Returns
  • Ok(()) if the harvest is successful.
  • Err(StrategyError) if the harvest fails.
  • -
    source

    fn balance(env: Env, from: Address) -> Result<i128, StrategyError>

    Returns the current balance of the underlying asset in the strategy.

    -

    This function provides the current balance of the underlying asset that is managed by +

    source

    fn balance(env: Env, from: Address) -> Result<i128, StrategyError>

    Returns the current balance of the underlying asset in the strategy.

    +

    This function provides the current balance of the underlying asset that is managed by the strategy on behalf of the specified address. It is used to track the assets held in the strategy.

    §Parameters
      @@ -95,9 +95,9 @@
      §Returns
    source

    fn withdraw( env: Env, - amount: i128, - from: Address -) -> Result<i128, StrategyError>

    Withdraws the specified amount of the underlying asset from the strategy.

    + amount: i128, + from: Address, +) -> Result<i128, StrategyError>

    Withdraws the specified amount of the underlying asset from the strategy.

    This function allows the DeFindex vault to withdraw assets from the strategy.

    §Parameters
      @@ -110,4 +110,4 @@
      §Returns
    • Ok(i128) containing the amount withdrawn.
    • Err(StrategyError) if the withdrawal fails (e.g., insufficient balance).
    -

    Object Safety§

    This trait is not object safe.

    Implementors§

    \ No newline at end of file +

    Object Safety§

    This trait is not object safe.

    Implementors§

    \ No newline at end of file diff --git a/apps/rust_docs/defindex_vault/all.html b/apps/rust_docs/defindex_vault/all.html index c4e96854..2684b085 100644 --- a/apps/rust_docs/defindex_vault/all.html +++ b/apps/rust_docs/defindex_vault/all.html @@ -1 +1 @@ -List of all items in this crate
    \ No newline at end of file +List of all items in this crate
    \ No newline at end of file diff --git a/apps/rust_docs/defindex_vault/enum.ContractError.html b/apps/rust_docs/defindex_vault/enum.ContractError.html index f75e3203..c96e967e 100644 --- a/apps/rust_docs/defindex_vault/enum.ContractError.html +++ b/apps/rust_docs/defindex_vault/enum.ContractError.html @@ -1,100 +1,114 @@ -ContractError in defindex_vault - Rust

    Enum defindex_vault::ContractError

    source ·
    #[repr(u32)]
    pub enum ContractError { -
    Show 17 variants NotInitialized = 100, +ContractError in defindex_vault - Rust

    Enum defindex_vault::ContractError

    source ·
    #[repr(u32)]
    pub enum ContractError { +
    Show 30 variants NotInitialized = 100, AlreadyInitialized = 101, InvalidRatio = 102, StrategyDoesNotSupportAsset = 103, + NoAssetAllocation = 104, NegativeNotAllowed = 110, InsufficientBalance = 111, - WrongAmuntsLength = 112, + WrongAmountsLength = 112, NotEnoughIdleFunds = 113, InsufficientManagedFunds = 114, + MissingInstructionData = 115, + UnsupportedAsset = 116, + InsufficientAmount = 117, + NoOptimalAmounts = 118, + WrongInvestmentLength = 119, + WrongAssetAddress = 122, + WrongStrategiesLength = 123, + AmountOverTotalSupply = 124, + NoInstructions = 125, ArithmeticError = 120, Overflow = 121, Unauthorized = 130, RoleNotFound = 131, StrategyNotFound = 140, StrategyPausedOrNotFound = 141, + StrategyWithdrawError = 142, + StrategyInvestError = 143, + StrategyPaused = 144, AssetNotFound = 150, NoAssetsProvided = 151, -
    }

    Variants§

    §

    NotInitialized = 100

    §

    AlreadyInitialized = 101

    §

    InvalidRatio = 102

    §

    StrategyDoesNotSupportAsset = 103

    §

    NegativeNotAllowed = 110

    §

    InsufficientBalance = 111

    §

    WrongAmuntsLength = 112

    §

    NotEnoughIdleFunds = 113

    §

    InsufficientManagedFunds = 114

    §

    ArithmeticError = 120

    §

    Overflow = 121

    §

    Unauthorized = 130

    §

    RoleNotFound = 131

    §

    StrategyNotFound = 140

    §

    StrategyPausedOrNotFound = 141

    §

    AssetNotFound = 150

    §

    NoAssetsProvided = 151

    Implementations§

    source§

    impl ContractError

    source

    pub const fn spec_xdr() -> [u8; 540]

    Trait Implementations§

    source§

    impl Clone for ContractError

    source§

    fn clone(&self) -> ContractError

    Returns a copy of the value. Read more
    1.0.0 · source§

    fn clone_from(&mut self, source: &Self)

    Performs copy-assignment from source. Read more
    source§

    impl Debug for ContractError

    source§

    fn fmt(&self, f: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    source§

    impl From<&ContractError> for Error

    source§

    fn from(val: &ContractError) -> Error

    Converts to this type from the input type.
    source§

    impl From<&ContractError> for InvokeError

    source§

    fn from(val: &ContractError) -> InvokeError

    Converts to this type from the input type.
    source§

    impl From<ContractError> for Error

    source§

    fn from(val: ContractError) -> Error

    Converts to this type from the input type.
    source§

    impl From<ContractError> for InvokeError

    source§

    fn from(val: ContractError) -> InvokeError

    Converts to this type from the input type.
    source§

    impl Ord for ContractError

    source§

    fn cmp(&self, other: &ContractError) -> Ordering

    This method returns an Ordering between self and other. Read more
    1.21.0 · source§

    fn max(self, other: Self) -> Self
    where - Self: Sized,

    Compares and returns the maximum of two values. Read more
    1.21.0 · source§

    fn min(self, other: Self) -> Self
    where - Self: Sized,

    Compares and returns the minimum of two values. Read more
    1.50.0 · source§

    fn clamp(self, min: Self, max: Self) -> Self
    where - Self: Sized + PartialOrd,

    Restrict a value to a certain interval. Read more
    source§

    impl PartialEq for ContractError

    source§

    fn eq(&self, other: &ContractError) -> bool

    This method tests for self and other values to be equal, and is used -by ==.
    1.0.0 · source§

    fn ne(&self, other: &Rhs) -> bool

    This method tests for !=. The default implementation is almost always -sufficient, and should not be overridden without very good reason.
    source§

    impl PartialOrd for ContractError

    source§

    fn partial_cmp(&self, other: &ContractError) -> Option<Ordering>

    This method returns an ordering between self and other values if one exists. Read more
    1.0.0 · source§

    fn lt(&self, other: &Rhs) -> bool

    This method tests less than (for self and other) and is used by the < operator. Read more
    1.0.0 · source§

    fn le(&self, other: &Rhs) -> bool

    This method tests less than or equal to (for self and other) and is used by the <= -operator. Read more
    1.0.0 · source§

    fn gt(&self, other: &Rhs) -> bool

    This method tests greater than (for self and other) and is used by the > operator. Read more
    1.0.0 · source§

    fn ge(&self, other: &Rhs) -> bool

    This method tests greater than or equal to (for self and other) and is used by the >= -operator. Read more
    source§

    impl TryFrom<&Error> for ContractError

    §

    type Error = Error

    The type returned in the event of a conversion error.
    source§

    fn try_from(error: &Error) -> Result<Self, Error>

    Performs the conversion.
    source§

    impl TryFrom<&InvokeError> for ContractError

    §

    type Error = InvokeError

    The type returned in the event of a conversion error.
    source§

    fn try_from(error: &InvokeError) -> Result<Self, InvokeError>

    Performs the conversion.
    source§

    impl TryFrom<Error> for ContractError

    §

    type Error = Error

    The type returned in the event of a conversion error.
    source§

    fn try_from(error: Error) -> Result<Self, Error>

    Performs the conversion.
    source§

    impl TryFrom<InvokeError> for ContractError

    §

    type Error = InvokeError

    The type returned in the event of a conversion error.
    source§

    fn try_from(error: InvokeError) -> Result<Self, InvokeError>

    Performs the conversion.
    source§

    impl TryFromVal<Env, ContractError> for Val

    §

    type Error = ConversionError

    source§

    fn try_from_val(env: &Env, val: &ContractError) -> Result<Self, ConversionError>

    source§

    impl TryFromVal<Env, Val> for ContractError

    §

    type Error = ConversionError

    source§

    fn try_from_val(env: &Env, val: &Val) -> Result<Self, ConversionError>

    source§

    impl Copy for ContractError

    source§

    impl Eq for ContractError

    source§

    impl StructuralPartialEq for ContractError

    Auto Trait Implementations§

    Blanket Implementations§

    source§

    impl<T> Any for T
    where - T: 'static + ?Sized,

    source§

    fn type_id(&self) -> TypeId

    Gets the TypeId of self. Read more
    source§

    impl<T> Borrow<T> for T
    where - T: ?Sized,

    source§

    fn borrow(&self) -> &T

    Immutably borrows from an owned value. Read more
    source§

    impl<T> BorrowMut<T> for T
    where - T: ?Sized,

    source§

    fn borrow_mut(&mut self) -> &mut T

    Mutably borrows from an owned value. Read more
    §

    impl<Q, K> Comparable<K> for Q
    where - Q: Ord + ?Sized, - K: Borrow<Q> + ?Sized,

    §

    fn compare(&self, key: &K) -> Ordering

    Compare self to key and return their ordering.
    §

    impl<T, C> Compare<&T> for C
    where - C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare(&self, a: &&T, b: &&T) -> Result<Ordering, <C as Compare<&T>>::Error>

    §

    impl<T, U, E, C> Compare<(T, U)> for C
    where - C: Compare<T, Error = E, Error = E> + Compare<U>,

    §

    type Error = E

    §

    fn compare( +

    }

    Variants§

    §

    NotInitialized = 100

    §

    AlreadyInitialized = 101

    §

    InvalidRatio = 102

    §

    StrategyDoesNotSupportAsset = 103

    §

    NoAssetAllocation = 104

    §

    NegativeNotAllowed = 110

    §

    InsufficientBalance = 111

    §

    WrongAmountsLength = 112

    §

    NotEnoughIdleFunds = 113

    §

    InsufficientManagedFunds = 114

    §

    MissingInstructionData = 115

    §

    UnsupportedAsset = 116

    §

    InsufficientAmount = 117

    §

    NoOptimalAmounts = 118

    §

    WrongInvestmentLength = 119

    §

    WrongAssetAddress = 122

    §

    WrongStrategiesLength = 123

    §

    AmountOverTotalSupply = 124

    §

    NoInstructions = 125

    §

    ArithmeticError = 120

    §

    Overflow = 121

    §

    Unauthorized = 130

    §

    RoleNotFound = 131

    §

    StrategyNotFound = 140

    §

    StrategyPausedOrNotFound = 141

    §

    StrategyWithdrawError = 142

    §

    StrategyInvestError = 143

    §

    StrategyPaused = 144

    §

    AssetNotFound = 150

    §

    NoAssetsProvided = 151

    Implementations§

    source§

    impl ContractError

    source

    pub const fn spec_xdr() -> [u8; 960]

    Trait Implementations§

    source§

    impl Clone for ContractError

    source§

    fn clone(&self) -> ContractError

    Returns a copy of the value. Read more
    1.0.0 · source§

    fn clone_from(&mut self, source: &Self)

    Performs copy-assignment from source. Read more
    source§

    impl Debug for ContractError

    source§

    fn fmt(&self, f: &mut Formatter<'_>) -> Result

    Formats the value using the given formatter. Read more
    source§

    impl From<&ContractError> for Error

    source§

    fn from(val: &ContractError) -> Error

    Converts to this type from the input type.
    source§

    impl From<&ContractError> for InvokeError

    source§

    fn from(val: &ContractError) -> InvokeError

    Converts to this type from the input type.
    source§

    impl From<ContractError> for Error

    source§

    fn from(val: ContractError) -> Error

    Converts to this type from the input type.
    source§

    impl From<ContractError> for InvokeError

    source§

    fn from(val: ContractError) -> InvokeError

    Converts to this type from the input type.
    source§

    impl Ord for ContractError

    source§

    fn cmp(&self, other: &ContractError) -> Ordering

    This method returns an Ordering between self and other. Read more
    1.21.0 · source§

    fn max(self, other: Self) -> Self
    where + Self: Sized,

    Compares and returns the maximum of two values. Read more
    1.21.0 · source§

    fn min(self, other: Self) -> Self
    where + Self: Sized,

    Compares and returns the minimum of two values. Read more
    1.50.0 · source§

    fn clamp(self, min: Self, max: Self) -> Self
    where + Self: Sized + PartialOrd,

    Restrict a value to a certain interval. Read more
    source§

    impl PartialEq for ContractError

    source§

    fn eq(&self, other: &ContractError) -> bool

    Tests for self and other values to be equal, and is used by ==.
    1.0.0 · source§

    fn ne(&self, other: &Rhs) -> bool

    Tests for !=. The default implementation is almost always sufficient, +and should not be overridden without very good reason.
    source§

    impl PartialOrd for ContractError

    source§

    fn partial_cmp(&self, other: &ContractError) -> Option<Ordering>

    This method returns an ordering between self and other values if one exists. Read more
    1.0.0 · source§

    fn lt(&self, other: &Rhs) -> bool

    Tests less than (for self and other) and is used by the < operator. Read more
    1.0.0 · source§

    fn le(&self, other: &Rhs) -> bool

    Tests less than or equal to (for self and other) and is used by the +<= operator. Read more
    1.0.0 · source§

    fn gt(&self, other: &Rhs) -> bool

    Tests greater than (for self and other) and is used by the > +operator. Read more
    1.0.0 · source§

    fn ge(&self, other: &Rhs) -> bool

    Tests greater than or equal to (for self and other) and is used by +the >= operator. Read more
    source§

    impl TryFrom<&Error> for ContractError

    source§

    type Error = Error

    The type returned in the event of a conversion error.
    source§

    fn try_from(error: &Error) -> Result<Self, Error>

    Performs the conversion.
    source§

    impl TryFrom<&InvokeError> for ContractError

    source§

    type Error = InvokeError

    The type returned in the event of a conversion error.
    source§

    fn try_from(error: &InvokeError) -> Result<Self, InvokeError>

    Performs the conversion.
    source§

    impl TryFrom<Error> for ContractError

    source§

    type Error = Error

    The type returned in the event of a conversion error.
    source§

    fn try_from(error: Error) -> Result<Self, Error>

    Performs the conversion.
    source§

    impl TryFrom<InvokeError> for ContractError

    source§

    type Error = InvokeError

    The type returned in the event of a conversion error.
    source§

    fn try_from(error: InvokeError) -> Result<Self, InvokeError>

    Performs the conversion.
    source§

    impl TryFromVal<Env, ContractError> for Val

    source§

    type Error = ConversionError

    source§

    fn try_from_val(env: &Env, val: &ContractError) -> Result<Self, ConversionError>

    source§

    impl TryFromVal<Env, Val> for ContractError

    source§

    type Error = ConversionError

    source§

    fn try_from_val(env: &Env, val: &Val) -> Result<Self, ConversionError>

    source§

    impl Copy for ContractError

    source§

    impl Eq for ContractError

    source§

    impl StructuralPartialEq for ContractError

    Auto Trait Implementations§

    Blanket Implementations§

    source§

    impl<T> Any for T
    where + T: 'static + ?Sized,

    source§

    fn type_id(&self) -> TypeId

    Gets the TypeId of self. Read more
    source§

    impl<T> Borrow<T> for T
    where + T: ?Sized,

    source§

    fn borrow(&self) -> &T

    Immutably borrows from an owned value. Read more
    source§

    impl<T> BorrowMut<T> for T
    where + T: ?Sized,

    source§

    fn borrow_mut(&mut self) -> &mut T

    Mutably borrows from an owned value. Read more
    source§

    impl<T> CloneToUninit for T
    where + T: Clone,

    source§

    unsafe fn clone_to_uninit(&self, dst: *mut T)

    🔬This is a nightly-only experimental API. (clone_to_uninit)
    Performs copy-assignment from self to dst. Read more
    §

    impl<Q, K> Comparable<K> for Q
    where + Q: Ord + ?Sized, + K: Borrow<Q> + ?Sized,

    §

    fn compare(&self, key: &K) -> Ordering

    Compare self to key and return their ordering.
    §

    impl<T, C> Compare<&T> for C
    where + C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare(&self, a: &&T, b: &&T) -> Result<Ordering, <C as Compare<&T>>::Error>

    §

    impl<T, U, E, C> Compare<(T, U)> for C
    where + C: Compare<T, Error = E, Error = E> + Compare<U>,

    §

    type Error = E

    §

    fn compare( &self, - a: &(T, U), - b: &(T, U) -) -> Result<Ordering, <C as Compare<(T, U)>>::Error>

    §

    impl<T, U, V, E, C> Compare<(T, U, V)> for C
    where - C: Compare<T, Error = E, Error = E, Error = E> + Compare<U> + Compare<V>,

    §

    type Error = E

    §

    fn compare( + a: &(T, U), + b: &(T, U), +) -> Result<Ordering, <C as Compare<(T, U)>>::Error>

    §

    impl<T, U, V, E, C> Compare<(T, U, V)> for C
    where + C: Compare<T, Error = E, Error = E, Error = E> + Compare<U> + Compare<V>,

    §

    type Error = E

    §

    fn compare( &self, - a: &(T, U, V), - b: &(T, U, V) -) -> Result<Ordering, <C as Compare<(T, U, V)>>::Error>

    §

    impl<T, U, V, W, E, C> Compare<(T, U, V, W)> for C
    where - C: Compare<T, Error = E, Error = E, Error = E, Error = E> + Compare<U> + Compare<V> + Compare<W>,

    §

    type Error = E

    §

    fn compare( + a: &(T, U, V), + b: &(T, U, V), +) -> Result<Ordering, <C as Compare<(T, U, V)>>::Error>

    §

    impl<T, U, V, W, E, C> Compare<(T, U, V, W)> for C
    where + C: Compare<T, Error = E, Error = E, Error = E, Error = E> + Compare<U> + Compare<V> + Compare<W>,

    §

    type Error = E

    §

    fn compare( &self, - a: &(T, U, V, W), - b: &(T, U, V, W) -) -> Result<Ordering, <C as Compare<(T, U, V, W)>>::Error>

    §

    impl<T, U, V, W, X, E, C> Compare<(T, U, V, W, X)> for C
    where - C: Compare<T, Error = E, Error = E, Error = E, Error = E, Error = E> + Compare<U> + Compare<V> + Compare<W> + Compare<X>,

    §

    type Error = E

    §

    fn compare( + a: &(T, U, V, W), + b: &(T, U, V, W), +) -> Result<Ordering, <C as Compare<(T, U, V, W)>>::Error>

    §

    impl<T, U, V, W, X, E, C> Compare<(T, U, V, W, X)> for C
    where + C: Compare<T, Error = E, Error = E, Error = E, Error = E, Error = E> + Compare<U> + Compare<V> + Compare<W> + Compare<X>,

    §

    type Error = E

    §

    fn compare( &self, - a: &(T, U, V, W, X), - b: &(T, U, V, W, X) -) -> Result<Ordering, <C as Compare<(T, U, V, W, X)>>::Error>

    §

    impl<T, C> Compare<Box<T>> for C
    where - C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare( + a: &(T, U, V, W, X), + b: &(T, U, V, W, X), +) -> Result<Ordering, <C as Compare<(T, U, V, W, X)>>::Error>

    §

    impl<T, C> Compare<Box<T>> for C
    where + C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare( &self, - a: &Box<T>, - b: &Box<T> -) -> Result<Ordering, <C as Compare<Box<T>>>::Error>

    §

    impl<T, C> Compare<Option<T>> for C
    where - C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare( + a: &Box<T>, + b: &Box<T>, +) -> Result<Ordering, <C as Compare<Box<T>>>::Error>

    §

    impl<T, C> Compare<Option<T>> for C
    where + C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare( &self, - a: &Option<T>, - b: &Option<T> -) -> Result<Ordering, <C as Compare<Option<T>>>::Error>

    §

    impl<T, C> Compare<Rc<T>> for C
    where - C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare( + a: &Option<T>, + b: &Option<T>, +) -> Result<Ordering, <C as Compare<Option<T>>>::Error>

    §

    impl<T, C> Compare<Rc<T>> for C
    where + C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare( &self, - a: &Rc<T>, - b: &Rc<T> -) -> Result<Ordering, <C as Compare<Rc<T>>>::Error>

    §

    impl<T, C> Compare<Vec<T>> for C
    where - C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare( + a: &Rc<T>, + b: &Rc<T>, +) -> Result<Ordering, <C as Compare<Rc<T>>>::Error>

    §

    impl<T, C> Compare<Vec<T>> for C
    where + C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare( &self, - a: &Vec<T>, - b: &Vec<T> -) -> Result<Ordering, <C as Compare<Vec<T>>>::Error>

    §

    impl<T> Downcast for T
    where - T: Any,

    §

    fn into_any(self: Box<T>) -> Box<dyn Any>

    Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can -then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
    §

    fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

    Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be -further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
    §

    fn as_any(&self) -> &(dyn Any + 'static)

    Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot -generate &Any’s vtable from &Trait’s.
    §

    fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

    Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot + a: &Vec<T>, + b: &Vec<T>, +) -> Result<Ordering, <C as Compare<Vec<T>>>::Error>
    §

    impl<T> Downcast for T
    where + T: Any,

    §

    fn into_any(self: Box<T>) -> Box<dyn Any>

    Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can +then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
    §

    fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

    Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be +further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
    §

    fn as_any(&self) -> &(dyn Any + 'static)

    Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot +generate &Any’s vtable from &Trait’s.
    §

    fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

    Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
    §

    impl<T> DowncastSync for T
    where - T: Any + Send + Sync,

    §

    fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>

    Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be + T: Any + Send + Sync,
    §

    fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>

    Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
    §

    impl<Q, K> Equivalent<K> for Q
    where - Q: Eq + ?Sized, - K: Borrow<Q> + ?Sized,

    §

    fn equivalent(&self, key: &K) -> bool

    Checks if this value is equivalent to the given key. Read more
    §

    impl<Q, K> Equivalent<K> for Q
    where - Q: Eq + ?Sized, - K: Borrow<Q> + ?Sized,

    §

    fn equivalent(&self, key: &K) -> bool

    Compare self to key and return true if they are equal.
    source§

    impl<T> From<T> for T

    source§

    fn from(t: T) -> T

    Returns the argument unchanged.

    + Q: Eq + ?Sized, + K: Borrow<Q> + ?Sized,
    §

    fn equivalent(&self, key: &K) -> bool

    Checks if this value is equivalent to the given key. Read more
    §

    impl<Q, K> Equivalent<K> for Q
    where + Q: Eq + ?Sized, + K: Borrow<Q> + ?Sized,

    §

    fn equivalent(&self, key: &K) -> bool

    Compare self to key and return true if they are equal.
    source§

    impl<T> From<T> for T

    source§

    fn from(t: T) -> T

    Returns the argument unchanged.

    §

    impl<E, T, U> FromVal<E, T> for U
    where E: Env, - U: TryFromVal<E, T>,

    §

    fn from_val(e: &E, v: &T) -> U

    §

    impl<T> FromXdr for T
    where - T: TryFromVal<Env, Val>,

    §

    type Error = <T as TryFromVal<Env, Val>>::Error

    §

    fn from_xdr(env: &Env, b: &Bytes) -> Result<T, <T as FromXdr>::Error>

    source§

    impl<T, U> Into<U> for T
    where - U: From<T>,

    source§

    fn into(self) -> U

    Calls U::from(self).

    + U: TryFromVal<E, T>,
    §

    fn from_val(e: &E, v: &T) -> U

    §

    impl<T> FromXdr for T
    where + T: TryFromVal<Env, Val>,

    §

    type Error = <T as TryFromVal<Env, Val>>::Error

    §

    fn from_xdr(env: &Env, b: &Bytes) -> Result<T, <T as FromXdr>::Error>

    source§

    impl<T, U> Into<U> for T
    where + U: From<T>,

    source§

    fn into(self) -> U

    Calls U::from(self).

    That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

    +From<T> for U chooses to do.

    §

    impl<E, T, U> IntoVal<E, T> for U
    where E: Env, - T: FromVal<E, U>,

    §

    fn into_val(&self, e: &E) -> T

    source§

    impl<T> Same for T

    §

    type Output = T

    Should always be Self
    source§

    impl<T> ToOwned for T
    where - T: Clone,

    §

    type Owned = T

    The resulting type after obtaining ownership.
    source§

    fn to_owned(&self) -> T

    Creates owned data from borrowed data, usually by cloning. Read more
    source§

    fn clone_into(&self, target: &mut T)

    Uses borrowed data to replace owned data, usually by cloning. Read more
    §

    impl<T> ToXdr for T
    where - T: IntoVal<Env, Val>,

    §

    fn to_xdr(self, env: &Env) -> Bytes

    source§

    impl<T, U> TryFrom<U> for T
    where - U: Into<T>,

    §

    type Error = Infallible

    The type returned in the event of a conversion error.
    source§

    fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

    Performs the conversion.
    source§

    impl<T, U> TryInto<U> for T
    where - U: TryFrom<T>,

    §

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.
    source§

    fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

    Performs the conversion.
    §

    impl<E, T, U> TryIntoVal<E, T> for U
    where + T: FromVal<E, U>,

    §

    fn into_val(&self, e: &E) -> T

    source§

    impl<T> Same for T

    source§

    type Output = T

    Should always be Self
    source§

    impl<T> ToOwned for T
    where + T: Clone,

    source§

    type Owned = T

    The resulting type after obtaining ownership.
    source§

    fn to_owned(&self) -> T

    Creates owned data from borrowed data, usually by cloning. Read more
    source§

    fn clone_into(&self, target: &mut T)

    Uses borrowed data to replace owned data, usually by cloning. Read more
    §

    impl<T> ToXdr for T
    where + T: IntoVal<Env, Val>,

    §

    fn to_xdr(self, env: &Env) -> Bytes

    source§

    impl<T, U> TryFrom<U> for T
    where + U: Into<T>,

    source§

    type Error = Infallible

    The type returned in the event of a conversion error.
    source§

    fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

    Performs the conversion.
    source§

    impl<T, U> TryInto<U> for T
    where + U: TryFrom<T>,

    source§

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.
    source§

    fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

    Performs the conversion.
    §

    impl<E, T, U> TryIntoVal<E, T> for U
    where E: Env, - T: TryFromVal<E, U>,

    §

    type Error = <T as TryFromVal<E, U>>::Error

    §

    fn try_into_val(&self, env: &E) -> Result<T, <U as TryIntoVal<E, T>>::Error>

    §

    impl<V, T> VZip<V> for T
    where + T: TryFromVal<E, U>,

    §

    type Error = <T as TryFromVal<E, U>>::Error

    §

    fn try_into_val(&self, env: &E) -> Result<T, <U as TryIntoVal<E, T>>::Error>

    §

    impl<V, T> VZip<V> for T
    where V: MultiLane<T>,

    §

    fn vzip(self) -> V

    \ No newline at end of file diff --git a/apps/rust_docs/defindex_vault/index.html b/apps/rust_docs/defindex_vault/index.html index b4fe8617..0aab010a 100644 --- a/apps/rust_docs/defindex_vault/index.html +++ b/apps/rust_docs/defindex_vault/index.html @@ -1 +1 @@ -defindex_vault - Rust

    Crate defindex_vault

    source ·

    Structs§

    Enums§

    \ No newline at end of file +defindex_vault - Rust

    Crate defindex_vault

    source ·

    Structs§

    Enums§

    \ No newline at end of file diff --git a/apps/rust_docs/defindex_vault/struct.DeFindexVault.html b/apps/rust_docs/defindex_vault/struct.DeFindexVault.html index d32baced..4b6ec15e 100644 --- a/apps/rust_docs/defindex_vault/struct.DeFindexVault.html +++ b/apps/rust_docs/defindex_vault/struct.DeFindexVault.html @@ -1,55 +1,79 @@ -DeFindexVault in defindex_vault - Rust

    Struct defindex_vault::DeFindexVault

    source ·
    pub struct DeFindexVault;

    Implementations§

    source§

    impl DeFindexVault

    source

    pub const fn spec_xdr_initialize() -> [u8; 1224]

    Initializes the DeFindex Vault contract with the required parameters.

    -

    This function sets the roles for emergency manager, fee receiver, and manager. +DeFindexVault in defindex_vault - Rust

    Struct defindex_vault::DeFindexVault

    source ·
    pub struct DeFindexVault;

    Implementations§

    source§

    impl DeFindexVault

    source

    pub const fn spec_xdr_initialize() -> [u8; 1352]

    Initializes the DeFindex Vault contract with the required parameters.

    +

    This function sets the roles for manager, emergency manager, vault fee receiver, and manager. It also stores the list of assets to be managed by the vault, including strategies for each asset.

    -
    §Arguments:
    -
      -
    • e - The environment.
    • -
    • assets - A vector of AssetAllocation structs representing the assets and their associated strategies.
    • -
    • manager - The address responsible for managing the vault.
    • -
    • emergency_manager - The address with emergency control over the vault.
    • -
    • fee_receiver - The address that will receive fees from the vault.
    • -
    • vault_share - The percentage of the vault’s fees that will be sent to the DeFindex receiver. in BPS.
    • -
    • defindex_receiver - The address that will receive fees for DeFindex from the vault.
    • -
    • factory - The address of the factory that deployed the vault.
    • +
      §Arguments
      +
        +
      • assets: List of asset allocations for the vault, including strategies associated with each asset.
      • +
      • manager: Primary vault manager with permissions for vault control.
      • +
      • emergency_manager: Address with emergency access for emergency control over the vault.
      • +
      • vault_fee_receiver: Address designated to receive the vault fee receiver’s portion of management fees.
      • +
      • vault_fee: Vault-specific fee percentage in basis points (typically set at 0-2% APR).
      • +
      • defindex_protocol_receiver: Address receiving DeFindex’s protocol-wide fee in basis points (0.5% APR).
      • +
      • factory: Factory contract address for deployment linkage.
      • +
      • vault_name: Name of the vault token to be displayed in metadata.
      • +
      • vault_symbol: Symbol representing the vault’s token.
      • +
      +
      §Returns
      +
        +
      • Result<(), ContractError>: Returns Ok(()) if initialization succeeds, or a ContractError if +any setup fails (e.g., strategy mismatch with asset).
      • +
      +
      §Errors
      +
        +
      • ContractError::AlreadyInitialized: If the vault has already been initialized.
      • +
      • ContractError::StrategyDoesNotSupportAsset: If a strategy within an asset does not support the asset’s contract.
      • +
      +
    source§

    impl DeFindexVault

    source

    pub const fn spec_xdr_deposit() -> [u8; 1196]

    Handles user deposits into the DeFindex Vault.

    +

    This function processes a deposit by transferring each specified asset amount from the user’s address to +the vault, allocating assets according to the vault’s defined strategy ratios, and minting vault shares that +represent the user’s proportional share in the vault. The amounts_desired and amounts_min vectors should +align with the vault’s asset order to ensure correct allocation.

    +
    §Parameters
    +
      +
    • e - The current environment reference (Env), for access to the contract state and utilities.
    • +
    • amounts_desired - A vector specifying the user’s intended deposit amounts for each asset.
    • +
    • amounts_min - A vector of minimum deposit amounts required for the transaction to proceed.
    • +
    • from - The address of the user making the deposit.
    -
    §Returns:
    +
    §Returns
      -
    • Result<(), ContractError> - Ok if successful, otherwise returns a ContractError.
    • +
    • Result<(Vec<i128>, i128), ContractError> - Returns the actual deposited amounts and shares_to_mint if successful, +otherwise a ContractError.
    -
    source§

    impl DeFindexVault

    source

    pub const fn spec_xdr_deposit() -> [u8; 760]

    Handles deposits into the DeFindex Vault.

    -

    This function transfers the desired amounts of each asset into the vault, distributes the assets -across the strategies according to the vault’s ratios, and mints dfTokens representing the user’s -share in the vault.

    -
    §Arguments:
    +
    §Function Flow
    +
      +
    1. Fee Collection: Collects accrued fees before processing the deposit.
    2. +
    3. Validation: Checks that the lengths of amounts_desired and amounts_min match the vault’s assets.
    4. +
    5. Share Calculation: Calculates shares_to_mint based on the vault’s total managed funds and the deposit amount.
    6. +
    7. Asset Transfer: Transfers each specified amount from the user’s address to the vault as idle funds.
    8. +
    9. Vault shares Minting: Mints vault shares for the user to represent their ownership in the vault.
    10. +
    +
    §Notes
      -
    • e - The environment.
    • -
    • amounts_desired - A vector of the amounts the user wishes to deposit for each asset.
    • -
    • amounts_min - A vector of minimum amounts required for the deposit to proceed.
    • -
    • from - The address of the user making the deposit.
    • +
    • For the first deposit, if the vault has only one asset, shares are calculated directly based on the deposit amount.
    • +
    • For multiple assets, the function delegates to calculate_deposit_amounts_and_shares_to_mint +for precise share computation.
    • +
    • An event is emitted to log the deposit, including the actual deposited amounts and minted shares.
    -
    §Returns:
    -
      -
    • Result<(), ContractError> - Ok if successful, otherwise returns a ContractError.
    • -
    -
    source§

    impl DeFindexVault

    source

    pub const fn spec_xdr_withdraw() -> [u8; 648]

    Withdraws assets from the DeFindex Vault by burning dfTokens.

    -

    This function calculates the amount of assets to withdraw based on the number of dfTokens being burned, +

    source§

    impl DeFindexVault

    source

    pub const fn spec_xdr_withdraw() -> [u8; 684]

    Withdraws assets from the DeFindex Vault by burning Vault Share tokens.

    +

    This function calculates the amount of assets to withdraw based on the number of Vault Share tokens being burned, then transfers the appropriate assets back to the user, pulling from both idle funds and strategies as needed.

    -
    §Arguments:
    +
    §Arguments:
    • e - The environment.
    • -
    • df_amount - The amount of dfTokens to burn for the withdrawal.
    • +
    • shares_amount - The amount of Vault Share tokens to burn for the withdrawal.
    • from - The address of the user requesting the withdrawal.
    §Returns:
    • Result<(), ContractError> - Ok if successful, otherwise returns a ContractError.
    -
    source§

    impl DeFindexVault

    source

    pub const fn spec_xdr_emergency_withdraw() -> [u8; 712]

    Executes an emergency withdrawal from a specific strategy.

    +
    source§

    impl DeFindexVault

    source

    pub const fn spec_xdr_emergency_withdraw() -> [u8; 712]

    Executes an emergency withdrawal from a specific strategy.

    This function allows the emergency manager or manager to withdraw all assets from a particular strategy and store them as idle funds within the vault. It also pauses the strategy to prevent further use until unpaused.

    -
    §Arguments:
    +
    §Arguments:
    • e - The environment.
    • strategy_address - The address of the strategy to withdraw from.
    • @@ -59,10 +83,10 @@
      §Returns:
      • Result<(), ContractError> - Ok if successful, otherwise returns a ContractError.
      -
    source§

    impl DeFindexVault

    source

    pub const fn spec_xdr_pause_strategy() -> [u8; 604]

    Pauses a strategy to prevent it from being used in the vault.

    +
    source§

    impl DeFindexVault

    source

    pub const fn spec_xdr_pause_strategy() -> [u8; 604]

    Pauses a strategy to prevent it from being used in the vault.

    This function pauses a strategy by setting its paused field to true. Only the manager or emergency manager can pause a strategy.

    -
    §Arguments:
    +
    §Arguments:
    • e - The environment.
    • strategy_address - The address of the strategy to pause.
    • @@ -72,10 +96,10 @@
      §Returns:
      • Result<(), ContractError> - Ok if successful, otherwise returns a ContractError.
      -
    source§

    impl DeFindexVault

    source

    pub const fn spec_xdr_unpause_strategy() -> [u8; 572]

    Unpauses a previously paused strategy.

    +
    source§

    impl DeFindexVault

    source

    pub const fn spec_xdr_unpause_strategy() -> [u8; 572]

    Unpauses a previously paused strategy.

    This function unpauses a strategy by setting its paused field to false, allowing it to be used again in the vault.

    -
    §Arguments:
    +
    §Arguments:
    • e - The environment.
    • strategy_address - The address of the strategy to unpause.
    • @@ -85,19 +109,19 @@
      §Returns:
      • Result<(), ContractError> - Ok if successful, otherwise returns a ContractError.
      -
    source§

    impl DeFindexVault

    source

    pub const fn spec_xdr_get_assets() -> [u8; 284]

    Retrieves the list of assets managed by the DeFindex Vault.

    -
    §Arguments:
    +
    source§

    impl DeFindexVault

    source

    pub const fn spec_xdr_get_assets() -> [u8; 284]

    Retrieves the list of assets managed by the DeFindex Vault.

    +
    §Arguments:
    • e - The environment.
    §Returns:
      -
    • Vec<AssetAllocation> - A vector of AssetAllocation structs representing the assets managed by the vault.
    • +
    • Vec<AssetStrategySet> - A vector of AssetStrategySet structs representing the assets managed by the vault.
    -
    source§

    impl DeFindexVault

    source

    pub const fn spec_xdr_fetch_total_managed_funds() -> [u8; 420]

    Returns the total managed funds of the vault, including both invested and idle funds.

    +
    source§

    impl DeFindexVault

    source

    pub const fn spec_xdr_fetch_total_managed_funds() -> [u8; 456]

    Returns the total managed funds of the vault, including both invested and idle funds.

    This function provides a map where the key is the asset address and the value is the total amount of that asset being managed by the vault.

    -
    §Arguments:
    +
    §Arguments:
    • e - The environment.
    @@ -105,10 +129,10 @@
    §Returns:
    • Map<Address, i128> - A map of asset addresses to their total managed amounts.
    -
    source§

    impl DeFindexVault

    source

    pub const fn spec_xdr_fetch_current_invested_funds() -> [u8; 440]

    Returns the current invested funds, representing the total assets allocated to strategies.

    +
    source§

    impl DeFindexVault

    source

    pub const fn spec_xdr_fetch_current_invested_funds() -> [u8; 440]

    Returns the current invested funds, representing the total assets allocated to strategies.

    This function provides a map where the key is the asset address and the value is the total amount of that asset currently invested in various strategies.

    -
    §Arguments:
    +
    §Arguments:
    • e - The environment.
    @@ -116,10 +140,10 @@
    §Returns:
    • Map<Address, i128> - A map of asset addresses to their total invested amounts.
    -
    source§

    impl DeFindexVault

    source

    pub const fn spec_xdr_fetch_current_idle_funds() -> [u8; 440]

    Returns the current idle funds, representing the total assets held directly by the vault (not invested).

    +
    source§

    impl DeFindexVault

    source

    pub const fn spec_xdr_fetch_current_idle_funds() -> [u8; 440]

    Returns the current idle funds, representing the total assets held directly by the vault (not invested).

    This function provides a map where the key is the asset address and the value is the total amount of that asset held as idle funds within the vault.

    -
    §Arguments:
    +
    §Arguments:
    • e - The environment.
    @@ -127,140 +151,183 @@
    §Returns:
    • Map<Address, i128> - A map of asset addresses to their total idle amounts.
    -
    source§

    impl DeFindexVault

    source

    pub const fn spec_xdr_get_asset_amounts_for_dftokens() -> [u8; 128]

    Temporary method for testing purposes.

    -
    source§

    impl DeFindexVault

    source

    pub const fn spec_xdr_set_fee_receiver() -> [u8; 444]

    Sets the fee receiver for the vault.

    +
    source§

    impl DeFindexVault

    source

    pub const fn spec_xdr_get_asset_amounts_per_shares() -> [u8; 644]

    This function extends the contract’s time-to-live and calculates how much of each asset corresponds +per the provided number of vault shares (vault_shares). It provides proportional allocations for each asset +in the vault relative to the specified shares.

    +
    §Arguments
    +
      +
    • e - The current environment reference.
    • +
    • vault_shares - The number of vault shares for which the corresponding asset amounts are calculated.
    • +
    +
    §Returns
    +
      +
    • Map<Address, i128> - A map containing each asset address and its corresponding proportional amount.
    • +
    +
    source§

    impl DeFindexVault

    source

    pub const fn spec_xdr_get_fees() -> [u8; 44]

    source§

    impl DeFindexVault

    source

    pub const fn spec_xdr_collect_fees() -> [u8; 68]

    source§

    impl DeFindexVault

    source

    pub const fn spec_xdr_set_fee_receiver() -> [u8; 448]

    Sets the fee receiver for the vault.

    This function allows the manager or emergency manager to set a new fee receiver address for the vault.

    §Arguments:
    • e - The environment.
    • caller - The address initiating the change (must be the manager or emergency manager).
    • -
    • fee_receiver - The new fee receiver address.
    • +
    • vault_fee_receiver - The new fee receiver address.
    -
    §Returns:
    +
    §Returns:
    • () - No return value.
    -
    source§

    impl DeFindexVault

    source

    pub const fn spec_xdr_get_fee_receiver() -> [u8; 288]

    Retrieves the current fee receiver address for the vault.

    +
    source§

    impl DeFindexVault

    source

    pub const fn spec_xdr_get_fee_receiver() -> [u8; 288]

    Retrieves the current fee receiver address for the vault.

    §Arguments:
    • e - The environment.
    -
    §Returns:
    +
    §Returns:
    • Result<Address, ContractError> - The fee receiver address if successful, otherwise returns a ContractError.
    -
    source§

    impl DeFindexVault

    source

    pub const fn spec_xdr_set_manager() -> [u8; 300]

    Sets the manager for the vault.

    +
    source§

    impl DeFindexVault

    source

    pub const fn spec_xdr_set_manager() -> [u8; 300]

    Sets the manager for the vault.

    This function allows the current manager or emergency manager to set a new manager for the vault.

    §Arguments:
    • e - The environment.
    • manager - The new manager address.
    -
    §Returns:
    +
    §Returns:
    • () - No return value.
    -
    source§

    impl DeFindexVault

    source

    pub const fn spec_xdr_get_manager() -> [u8; 276]

    Retrieves the current manager address for the vault.

    +
    source§

    impl DeFindexVault

    source

    pub const fn spec_xdr_get_manager() -> [u8; 276]

    Retrieves the current manager address for the vault.

    §Arguments:
    • e - The environment.
    -
    §Returns:
    +
    §Returns:
    • Result<Address, ContractError> - The manager address if successful, otherwise returns a ContractError.
    -
    source§

    impl DeFindexVault

    source

    pub const fn spec_xdr_set_emergency_manager() -> [u8; 364]

    Sets the emergency manager for the vault.

    +
    source§

    impl DeFindexVault

    source

    pub const fn spec_xdr_set_emergency_manager() -> [u8; 364]

    Sets the emergency manager for the vault.

    This function allows the current manager or emergency manager to set a new emergency manager for the vault.

    §Arguments:
    • e - The environment.
    • emergency_manager - The new emergency manager address.
    -
    §Returns:
    +
    §Returns:
    • () - No return value.
    -
    source§

    impl DeFindexVault

    source

    pub const fn spec_xdr_get_emergency_manager() -> [u8; 308]

    Retrieves the current emergency manager address for the vault.

    +
    source§

    impl DeFindexVault

    source

    pub const fn spec_xdr_get_emergency_manager() -> [u8; 308]

    Retrieves the current emergency manager address for the vault.

    §Arguments:
    • e - The environment.
    -
    §Returns:
    +
    §Returns:
    • Result<Address, ContractError> - The emergency manager address if successful, otherwise returns a ContractError.
    -
    source§

    impl DeFindexVault

    source

    pub const fn spec_xdr_invest() -> [u8; 448]

    Invests the vault’s idle funds into the specified strategies.

    -
    §Arguments:
    +
    source§

    impl DeFindexVault

    source

    pub const fn spec_xdr_invest() -> [u8; 1160]

    Executes the investment of the vault’s idle funds based on the specified asset allocations. +This function allows partial investments by providing an optional allocation for each asset, +and it ensures proper authorization and validation checks before proceeding with investments.

    +
    §Arguments
    +
      +
    • e - The current environment reference.
    • +
    • asset_investments - A vector of optional AssetInvestmentAllocation structures, where each element +represents an allocation for a specific asset. The vector must match the number of vault assets in length.
    • +
    +
    §Returns
    +
      +
    • Result<(), ContractError> - Returns Ok(()) if the investments are successful or a ContractError +if any issue occurs during validation or execution.
    • +
    +
    §Function Flow
    +
      +
    1. Extend Instance TTL: Extends the contract instance’s time-to-live to keep the instance active.
    2. +
    3. Check Initialization: Verifies that the vault is properly initialized before proceeding.
    4. +
    5. Access Control: Ensures the caller has the Manager role required to initiate investments.
    6. +
    7. Asset Count Validation: Verifies that the length of the asset_investments vector matches +the number of assets managed by the vault. If they don’t match, a WrongInvestmentLength error is returned.
    8. +
    9. Investment Execution: Calls the check_and_execute_investments function to perform the investment +after validating the inputs and ensuring correct execution flows for each asset allocation.
    10. +
    +
    §Errors
    +
      +
    • Returns ContractError::WrongInvestmentLength if the length of asset_investments does not match the vault assets.
    • +
    • Returns ContractError if access control validation fails or if investment execution encounters an issue.
    • +
    +
    §Security
    +
      +
    • Only addresses with the Manager role can call this function, ensuring restricted access to managing investments.
    • +
    +
    source§

    impl DeFindexVault

    source

    pub const fn spec_xdr_rebalance() -> [u8; 428]

    Rebalances the vault by executing a series of instructions.

    +
    §Arguments:
    • e - The environment.
    • -
    • investment - A vector of Investment structs representing the amount to invest in each strategy.
    • -
    • caller - The address of the caller.
    • +
    • instructions - A vector of Instruction structs representing actions (withdraw, invest, swap, zapper) to be taken.
    -
    §Returns:
    +
    §Returns:
    • Result<(), ContractError> - Ok if successful, otherwise returns a ContractError.
    -

    Auto Trait Implementations§

    Blanket Implementations§

    source§

    impl<T> Any for T
    where - T: 'static + ?Sized,

    source§

    fn type_id(&self) -> TypeId

    Gets the TypeId of self. Read more
    source§

    impl<T> Borrow<T> for T
    where - T: ?Sized,

    source§

    fn borrow(&self) -> &T

    Immutably borrows from an owned value. Read more
    source§

    impl<T> BorrowMut<T> for T
    where - T: ?Sized,

    source§

    fn borrow_mut(&mut self) -> &mut T

    Mutably borrows from an owned value. Read more
    §

    impl<T, C> Compare<&T> for C
    where - C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare(&self, a: &&T, b: &&T) -> Result<Ordering, <C as Compare<&T>>::Error>

    §

    impl<T, U, E, C> Compare<(T, U)> for C
    where - C: Compare<T, Error = E, Error = E> + Compare<U>,

    §

    type Error = E

    §

    fn compare( +

    Auto Trait Implementations§

    Blanket Implementations§

    source§

    impl<T> Any for T
    where + T: 'static + ?Sized,

    source§

    fn type_id(&self) -> TypeId

    Gets the TypeId of self. Read more
    source§

    impl<T> Borrow<T> for T
    where + T: ?Sized,

    source§

    fn borrow(&self) -> &T

    Immutably borrows from an owned value. Read more
    source§

    impl<T> BorrowMut<T> for T
    where + T: ?Sized,

    source§

    fn borrow_mut(&mut self) -> &mut T

    Mutably borrows from an owned value. Read more
    §

    impl<T, C> Compare<&T> for C
    where + C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare(&self, a: &&T, b: &&T) -> Result<Ordering, <C as Compare<&T>>::Error>

    §

    impl<T, U, E, C> Compare<(T, U)> for C
    where + C: Compare<T, Error = E, Error = E> + Compare<U>,

    §

    type Error = E

    §

    fn compare( &self, - a: &(T, U), - b: &(T, U) -) -> Result<Ordering, <C as Compare<(T, U)>>::Error>

    §

    impl<T, U, V, E, C> Compare<(T, U, V)> for C
    where - C: Compare<T, Error = E, Error = E, Error = E> + Compare<U> + Compare<V>,

    §

    type Error = E

    §

    fn compare( + a: &(T, U), + b: &(T, U), +) -> Result<Ordering, <C as Compare<(T, U)>>::Error>

    §

    impl<T, U, V, E, C> Compare<(T, U, V)> for C
    where + C: Compare<T, Error = E, Error = E, Error = E> + Compare<U> + Compare<V>,

    §

    type Error = E

    §

    fn compare( &self, - a: &(T, U, V), - b: &(T, U, V) -) -> Result<Ordering, <C as Compare<(T, U, V)>>::Error>

    §

    impl<T, U, V, W, E, C> Compare<(T, U, V, W)> for C
    where - C: Compare<T, Error = E, Error = E, Error = E, Error = E> + Compare<U> + Compare<V> + Compare<W>,

    §

    type Error = E

    §

    fn compare( + a: &(T, U, V), + b: &(T, U, V), +) -> Result<Ordering, <C as Compare<(T, U, V)>>::Error>

    §

    impl<T, U, V, W, E, C> Compare<(T, U, V, W)> for C
    where + C: Compare<T, Error = E, Error = E, Error = E, Error = E> + Compare<U> + Compare<V> + Compare<W>,

    §

    type Error = E

    §

    fn compare( &self, - a: &(T, U, V, W), - b: &(T, U, V, W) -) -> Result<Ordering, <C as Compare<(T, U, V, W)>>::Error>

    §

    impl<T, U, V, W, X, E, C> Compare<(T, U, V, W, X)> for C
    where - C: Compare<T, Error = E, Error = E, Error = E, Error = E, Error = E> + Compare<U> + Compare<V> + Compare<W> + Compare<X>,

    §

    type Error = E

    §

    fn compare( + a: &(T, U, V, W), + b: &(T, U, V, W), +) -> Result<Ordering, <C as Compare<(T, U, V, W)>>::Error>

    §

    impl<T, U, V, W, X, E, C> Compare<(T, U, V, W, X)> for C
    where + C: Compare<T, Error = E, Error = E, Error = E, Error = E, Error = E> + Compare<U> + Compare<V> + Compare<W> + Compare<X>,

    §

    type Error = E

    §

    fn compare( &self, - a: &(T, U, V, W, X), - b: &(T, U, V, W, X) -) -> Result<Ordering, <C as Compare<(T, U, V, W, X)>>::Error>

    §

    impl<T, C> Compare<Box<T>> for C
    where - C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare( + a: &(T, U, V, W, X), + b: &(T, U, V, W, X), +) -> Result<Ordering, <C as Compare<(T, U, V, W, X)>>::Error>

    §

    impl<T, C> Compare<Box<T>> for C
    where + C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare( &self, - a: &Box<T>, - b: &Box<T> -) -> Result<Ordering, <C as Compare<Box<T>>>::Error>

    §

    impl<T, C> Compare<Option<T>> for C
    where - C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare( + a: &Box<T>, + b: &Box<T>, +) -> Result<Ordering, <C as Compare<Box<T>>>::Error>

    §

    impl<T, C> Compare<Option<T>> for C
    where + C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare( &self, - a: &Option<T>, - b: &Option<T> -) -> Result<Ordering, <C as Compare<Option<T>>>::Error>

    §

    impl<T, C> Compare<Rc<T>> for C
    where - C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare( + a: &Option<T>, + b: &Option<T>, +) -> Result<Ordering, <C as Compare<Option<T>>>::Error>

    §

    impl<T, C> Compare<Rc<T>> for C
    where + C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare( &self, - a: &Rc<T>, - b: &Rc<T> -) -> Result<Ordering, <C as Compare<Rc<T>>>::Error>

    §

    impl<T, C> Compare<Vec<T>> for C
    where - C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare( + a: &Rc<T>, + b: &Rc<T>, +) -> Result<Ordering, <C as Compare<Rc<T>>>::Error>

    §

    impl<T, C> Compare<Vec<T>> for C
    where + C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare( &self, - a: &Vec<T>, - b: &Vec<T> -) -> Result<Ordering, <C as Compare<Vec<T>>>::Error>

    §

    impl<T> Downcast for T
    where - T: Any,

    §

    fn into_any(self: Box<T>) -> Box<dyn Any>

    Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can -then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
    §

    fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

    Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be -further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
    §

    fn as_any(&self) -> &(dyn Any + 'static)

    Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot -generate &Any’s vtable from &Trait’s.
    §

    fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

    Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot + a: &Vec<T>, + b: &Vec<T>, +) -> Result<Ordering, <C as Compare<Vec<T>>>::Error>
    §

    impl<T> Downcast for T
    where + T: Any,

    §

    fn into_any(self: Box<T>) -> Box<dyn Any>

    Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can +then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
    §

    fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

    Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be +further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
    §

    fn as_any(&self) -> &(dyn Any + 'static)

    Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot +generate &Any’s vtable from &Trait’s.
    §

    fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

    Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
    §

    impl<T> DowncastSync for T
    where - T: Any + Send + Sync,

    §

    fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>

    Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be -further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
    source§

    impl<T> From<T> for T

    source§

    fn from(t: T) -> T

    Returns the argument unchanged.

    -
    source§

    impl<T, U> Into<U> for T
    where - U: From<T>,

    source§

    fn into(self) -> U

    Calls U::from(self).

    + T: Any + Send + Sync,
    §

    fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Sync + Send>

    Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be +further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
    source§

    impl<T> From<T> for T

    source§

    fn from(t: T) -> T

    Returns the argument unchanged.

    +
    source§

    impl<T, U> Into<U> for T
    where + U: From<T>,

    source§

    fn into(self) -> U

    Calls U::from(self).

    That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

    +From<T> for U chooses to do.

    §

    impl<E, T, U> IntoVal<E, T> for U
    where E: Env, - T: FromVal<E, U>,

    §

    fn into_val(&self, e: &E) -> T

    source§

    impl<T> Same for T

    §

    type Output = T

    Should always be Self
    source§

    impl<T, U> TryFrom<U> for T
    where - U: Into<T>,

    §

    type Error = Infallible

    The type returned in the event of a conversion error.
    source§

    fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

    Performs the conversion.
    source§

    impl<T, U> TryInto<U> for T
    where - U: TryFrom<T>,

    §

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.
    source§

    fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

    Performs the conversion.
    §

    impl<E, T, U> TryIntoVal<E, T> for U
    where + T: FromVal<E, U>,

    §

    fn into_val(&self, e: &E) -> T

    source§

    impl<T> Same for T

    source§

    type Output = T

    Should always be Self
    source§

    impl<T, U> TryFrom<U> for T
    where + U: Into<T>,

    source§

    type Error = Infallible

    The type returned in the event of a conversion error.
    source§

    fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

    Performs the conversion.
    source§

    impl<T, U> TryInto<U> for T
    where + U: TryFrom<T>,

    source§

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.
    source§

    fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

    Performs the conversion.
    §

    impl<E, T, U> TryIntoVal<E, T> for U
    where E: Env, - T: TryFromVal<E, U>,

    §

    type Error = <T as TryFromVal<E, U>>::Error

    §

    fn try_into_val(&self, env: &E) -> Result<T, <U as TryIntoVal<E, T>>::Error>

    §

    impl<V, T> VZip<V> for T
    where + T: TryFromVal<E, U>,

    §

    type Error = <T as TryFromVal<E, U>>::Error

    §

    fn try_into_val(&self, env: &E) -> Result<T, <U as TryIntoVal<E, T>>::Error>

    §

    impl<V, T> VZip<V> for T
    where V: MultiLane<T>,

    §

    fn vzip(self) -> V

    \ No newline at end of file diff --git a/apps/rust_docs/defindex_vault/struct.DeFindexVaultClient.html b/apps/rust_docs/defindex_vault/struct.DeFindexVaultClient.html index 8293e0f0..bdb7187f 100644 --- a/apps/rust_docs/defindex_vault/struct.DeFindexVaultClient.html +++ b/apps/rust_docs/defindex_vault/struct.DeFindexVaultClient.html @@ -1,139 +1,193 @@ -DeFindexVaultClient in defindex_vault - Rust

    Struct defindex_vault::DeFindexVaultClient

    source ·
    pub struct DeFindexVaultClient<'a> {
    +DeFindexVaultClient in defindex_vault - Rust

    Struct defindex_vault::DeFindexVaultClient

    source ·
    pub struct DeFindexVaultClient<'a> {
         pub env: Env,
         pub address: Address,
         /* private fields */
     }
    Expand description

    DeFindexVaultClient is a client for calling the contract defined in “DeFindexVault”.

    -

    Fields§

    §env: Env§address: Address

    Implementations§

    source§

    impl<'a> DeFindexVaultClient<'a>

    source

    pub fn new(env: &Env, address: &Address) -> Self

    source§

    impl<'a> DeFindexVaultClient<'a>

    Fields§

    §env: Env§address: Address

    Implementations§

    source§

    impl<'a> DeFindexVaultClient<'a>

    source

    pub fn new(env: &Env, address: &Address) -> Self

    source§

    impl<'a> DeFindexVaultClient<'a>

    source

    pub fn initialize( &self, - assets: &Vec<AssetAllocation>, + assets: &Vec<AssetStrategySet>, manager: &Address, emergency_manager: &Address, - fee_receiver: &Address, - vault_share: &u32, - defindex_receiver: &Address, - factory: &Address + vault_fee_receiver: &Address, + vault_fee: &u32, + defindex_protocol_receiver: &Address, + factory: &Address, + vault_name: &String, + vault_symbol: &String, )

    Initializes the DeFindex Vault contract with the required parameters.

    -

    This function sets the roles for emergency manager, fee receiver, and manager. +

    This function sets the roles for manager, emergency manager, vault fee receiver, and manager. It also stores the list of assets to be managed by the vault, including strategies for each asset.

    -
    §Arguments:
    +
    §Arguments
      -
    • e - The environment.
    • -
    • assets - A vector of AssetAllocation structs representing the assets and their associated strategies.
    • -
    • manager - The address responsible for managing the vault.
    • -
    • emergency_manager - The address with emergency control over the vault.
    • -
    • fee_receiver - The address that will receive fees from the vault.
    • -
    • vault_share - The percentage of the vault’s fees that will be sent to the DeFindex receiver. in BPS.
    • -
    • defindex_receiver - The address that will receive fees for DeFindex from the vault.
    • -
    • factory - The address of the factory that deployed the vault.
    • +
    • assets: List of asset allocations for the vault, including strategies associated with each asset.
    • +
    • manager: Primary vault manager with permissions for vault control.
    • +
    • emergency_manager: Address with emergency access for emergency control over the vault.
    • +
    • vault_fee_receiver: Address designated to receive the vault fee receiver’s portion of management fees.
    • +
    • vault_fee: Vault-specific fee percentage in basis points (typically set at 0-2% APR).
    • +
    • defindex_protocol_receiver: Address receiving DeFindex’s protocol-wide fee in basis points (0.5% APR).
    • +
    • factory: Factory contract address for deployment linkage.
    • +
    • vault_name: Name of the vault token to be displayed in metadata.
    • +
    • vault_symbol: Symbol representing the vault’s token.
    -
    §Returns:
    +
    §Returns
      -
    • Result<(), ContractError> - Ok if successful, otherwise returns a ContractError.
    • +
    • Result<(), ContractError>: Returns Ok(()) if initialization succeeds, or a ContractError if +any setup fails (e.g., strategy mismatch with asset).
    • +
    +
    §Errors
    +
      +
    • ContractError::AlreadyInitialized: If the vault has already been initialized.
    • +
    • ContractError::StrategyDoesNotSupportAsset: If a strategy within an asset does not support the asset’s contract.
    -
    source

    pub fn try_initialize( +

    source

    pub fn try_initialize( &self, - assets: &Vec<AssetAllocation>, + assets: &Vec<AssetStrategySet>, manager: &Address, emergency_manager: &Address, - fee_receiver: &Address, - vault_share: &u32, - defindex_receiver: &Address, - factory: &Address -) -> Result<Result<(), <() as TryFromVal<Env, Val>>::Error>, Result<ContractError, InvokeError>>

    Initializes the DeFindex Vault contract with the required parameters.

    -

    This function sets the roles for emergency manager, fee receiver, and manager. + vault_fee_receiver: &Address, + vault_fee: &u32, + defindex_protocol_receiver: &Address, + factory: &Address, + vault_name: &String, + vault_symbol: &String, +) -> Result<Result<(), <() as TryFromVal<Env, Val>>::Error>, Result<ContractError, InvokeError>>

    Initializes the DeFindex Vault contract with the required parameters.

    +

    This function sets the roles for manager, emergency manager, vault fee receiver, and manager. It also stores the list of assets to be managed by the vault, including strategies for each asset.

    -
    §Arguments:
    +
    §Arguments
      -
    • e - The environment.
    • -
    • assets - A vector of AssetAllocation structs representing the assets and their associated strategies.
    • -
    • manager - The address responsible for managing the vault.
    • -
    • emergency_manager - The address with emergency control over the vault.
    • -
    • fee_receiver - The address that will receive fees from the vault.
    • -
    • vault_share - The percentage of the vault’s fees that will be sent to the DeFindex receiver. in BPS.
    • -
    • defindex_receiver - The address that will receive fees for DeFindex from the vault.
    • -
    • factory - The address of the factory that deployed the vault.
    • +
    • assets: List of asset allocations for the vault, including strategies associated with each asset.
    • +
    • manager: Primary vault manager with permissions for vault control.
    • +
    • emergency_manager: Address with emergency access for emergency control over the vault.
    • +
    • vault_fee_receiver: Address designated to receive the vault fee receiver’s portion of management fees.
    • +
    • vault_fee: Vault-specific fee percentage in basis points (typically set at 0-2% APR).
    • +
    • defindex_protocol_receiver: Address receiving DeFindex’s protocol-wide fee in basis points (0.5% APR).
    • +
    • factory: Factory contract address for deployment linkage.
    • +
    • vault_name: Name of the vault token to be displayed in metadata.
    • +
    • vault_symbol: Symbol representing the vault’s token.
    -
    §Returns:
    +
    §Returns
      -
    • Result<(), ContractError> - Ok if successful, otherwise returns a ContractError.
    • +
    • Result<(), ContractError>: Returns Ok(()) if initialization succeeds, or a ContractError if +any setup fails (e.g., strategy mismatch with asset).
    -
    source

    pub fn deposit( - &self, - amounts_desired: &Vec<i128>, - amounts_min: &Vec<i128>, - from: &Address -)

    Handles deposits into the DeFindex Vault.

    -

    This function transfers the desired amounts of each asset into the vault, distributes the assets -across the strategies according to the vault’s ratios, and mints dfTokens representing the user’s -share in the vault.

    -
    §Arguments:
    +
    §Errors
      -
    • e - The environment.
    • -
    • amounts_desired - A vector of the amounts the user wishes to deposit for each asset.
    • -
    • amounts_min - A vector of minimum amounts required for the deposit to proceed.
    • +
    • ContractError::AlreadyInitialized: If the vault has already been initialized.
    • +
    • ContractError::StrategyDoesNotSupportAsset: If a strategy within an asset does not support the asset’s contract.
    • +
    +
    source

    pub fn deposit( + &self, + amounts_desired: &Vec<i128>, + amounts_min: &Vec<i128>, + from: &Address, + invest: &bool, +) -> (Vec<i128>, i128)

    Handles user deposits into the DeFindex Vault.

    +

    This function processes a deposit by transferring each specified asset amount from the user’s address to +the vault, allocating assets according to the vault’s defined strategy ratios, and minting vault shares that +represent the user’s proportional share in the vault. The amounts_desired and amounts_min vectors should +align with the vault’s asset order to ensure correct allocation.

    +
    §Parameters
    +
      +
    • e - The current environment reference (Env), for access to the contract state and utilities.
    • +
    • amounts_desired - A vector specifying the user’s intended deposit amounts for each asset.
    • +
    • amounts_min - A vector of minimum deposit amounts required for the transaction to proceed.
    • from - The address of the user making the deposit.
    -
    §Returns:
    +
    §Returns
      -
    • Result<(), ContractError> - Ok if successful, otherwise returns a ContractError.
    • +
    • Result<(Vec<i128>, i128), ContractError> - Returns the actual deposited amounts and shares_to_mint if successful, +otherwise a ContractError.
    -
    source

    pub fn try_deposit( - &self, - amounts_desired: &Vec<i128>, - amounts_min: &Vec<i128>, - from: &Address -) -> Result<Result<(), <() as TryFromVal<Env, Val>>::Error>, Result<ContractError, InvokeError>>

    Handles deposits into the DeFindex Vault.

    -

    This function transfers the desired amounts of each asset into the vault, distributes the assets -across the strategies according to the vault’s ratios, and mints dfTokens representing the user’s -share in the vault.

    -
    §Arguments:
    +
    §Function Flow
    +
      +
    1. Fee Collection: Collects accrued fees before processing the deposit.
    2. +
    3. Validation: Checks that the lengths of amounts_desired and amounts_min match the vault’s assets.
    4. +
    5. Share Calculation: Calculates shares_to_mint based on the vault’s total managed funds and the deposit amount.
    6. +
    7. Asset Transfer: Transfers each specified amount from the user’s address to the vault as idle funds.
    8. +
    9. Vault shares Minting: Mints vault shares for the user to represent their ownership in the vault.
    10. +
    +
    §Notes
      -
    • e - The environment.
    • -
    • amounts_desired - A vector of the amounts the user wishes to deposit for each asset.
    • -
    • amounts_min - A vector of minimum amounts required for the deposit to proceed.
    • +
    • For the first deposit, if the vault has only one asset, shares are calculated directly based on the deposit amount.
    • +
    • For multiple assets, the function delegates to calculate_deposit_amounts_and_shares_to_mint +for precise share computation.
    • +
    • An event is emitted to log the deposit, including the actual deposited amounts and minted shares.
    • +
    +
    source

    pub fn try_deposit( + &self, + amounts_desired: &Vec<i128>, + amounts_min: &Vec<i128>, + from: &Address, + invest: &bool, +) -> Result<Result<(Vec<i128>, i128), <(Vec<i128>, i128) as TryFromVal<Env, Val>>::Error>, Result<ContractError, InvokeError>>

    Handles user deposits into the DeFindex Vault.

    +

    This function processes a deposit by transferring each specified asset amount from the user’s address to +the vault, allocating assets according to the vault’s defined strategy ratios, and minting vault shares that +represent the user’s proportional share in the vault. The amounts_desired and amounts_min vectors should +align with the vault’s asset order to ensure correct allocation.

    +
    §Parameters
    +
      +
    • e - The current environment reference (Env), for access to the contract state and utilities.
    • +
    • amounts_desired - A vector specifying the user’s intended deposit amounts for each asset.
    • +
    • amounts_min - A vector of minimum deposit amounts required for the transaction to proceed.
    • from - The address of the user making the deposit.
    -
    §Returns:
    +
    §Returns
      -
    • Result<(), ContractError> - Ok if successful, otherwise returns a ContractError.
    • +
    • Result<(Vec<i128>, i128), ContractError> - Returns the actual deposited amounts and shares_to_mint if successful, +otherwise a ContractError.
    • +
    +
    §Function Flow
    +
      +
    1. Fee Collection: Collects accrued fees before processing the deposit.
    2. +
    3. Validation: Checks that the lengths of amounts_desired and amounts_min match the vault’s assets.
    4. +
    5. Share Calculation: Calculates shares_to_mint based on the vault’s total managed funds and the deposit amount.
    6. +
    7. Asset Transfer: Transfers each specified amount from the user’s address to the vault as idle funds.
    8. +
    9. Vault shares Minting: Mints vault shares for the user to represent their ownership in the vault.
    10. +
    +
    §Notes
    +
      +
    • For the first deposit, if the vault has only one asset, shares are calculated directly based on the deposit amount.
    • +
    • For multiple assets, the function delegates to calculate_deposit_amounts_and_shares_to_mint +for precise share computation.
    • +
    • An event is emitted to log the deposit, including the actual deposited amounts and minted shares.
    -
    source

    pub fn withdraw(&self, df_amount: &i128, from: &Address) -> Vec<i128>

    Withdraws assets from the DeFindex Vault by burning dfTokens.

    -

    This function calculates the amount of assets to withdraw based on the number of dfTokens being burned, +

    source

    pub fn withdraw(&self, withdraw_shares: &i128, from: &Address) -> Vec<i128>

    Withdraws assets from the DeFindex Vault by burning Vault Share tokens.

    +

    This function calculates the amount of assets to withdraw based on the number of Vault Share tokens being burned, then transfers the appropriate assets back to the user, pulling from both idle funds and strategies as needed.

    -
    §Arguments:
    +
    §Arguments:
    • e - The environment.
    • -
    • df_amount - The amount of dfTokens to burn for the withdrawal.
    • +
    • shares_amount - The amount of Vault Share tokens to burn for the withdrawal.
    • from - The address of the user requesting the withdrawal.
    §Returns:
    • Result<(), ContractError> - Ok if successful, otherwise returns a ContractError.
    -
    source

    pub fn try_withdraw( +

    source

    pub fn try_withdraw( &self, - df_amount: &i128, - from: &Address -) -> Result<Result<Vec<i128>, <Vec<i128> as TryFromVal<Env, Val>>::Error>, Result<ContractError, InvokeError>>

    Withdraws assets from the DeFindex Vault by burning dfTokens.

    -

    This function calculates the amount of assets to withdraw based on the number of dfTokens being burned, + withdraw_shares: &i128, + from: &Address, +) -> Result<Result<Vec<i128>, <Vec<i128> as TryFromVal<Env, Val>>::Error>, Result<ContractError, InvokeError>>

    Withdraws assets from the DeFindex Vault by burning Vault Share tokens.

    +

    This function calculates the amount of assets to withdraw based on the number of Vault Share tokens being burned, then transfers the appropriate assets back to the user, pulling from both idle funds and strategies as needed.

    -
    §Arguments:
    +
    §Arguments:
    • e - The environment.
    • -
    • df_amount - The amount of dfTokens to burn for the withdrawal.
    • +
    • shares_amount - The amount of Vault Share tokens to burn for the withdrawal.
    • from - The address of the user requesting the withdrawal.
    §Returns:
    • Result<(), ContractError> - Ok if successful, otherwise returns a ContractError.
    -
    source

    pub fn emergency_withdraw(&self, strategy_address: &Address, caller: &Address)

    Executes an emergency withdrawal from a specific strategy.

    +
    source

    pub fn emergency_withdraw(&self, strategy_address: &Address, caller: &Address)

    Executes an emergency withdrawal from a specific strategy.

    This function allows the emergency manager or manager to withdraw all assets from a particular strategy and store them as idle funds within the vault. It also pauses the strategy to prevent further use until unpaused.

    -
    §Arguments:
    +
    §Arguments:
    • e - The environment.
    • strategy_address - The address of the strategy to withdraw from.
    • @@ -143,15 +197,15 @@
      §Returns:
      • Result<(), ContractError> - Ok if successful, otherwise returns a ContractError.
      -
    source

    pub fn try_emergency_withdraw( +

    source

    pub fn try_emergency_withdraw( &self, strategy_address: &Address, - caller: &Address -) -> Result<Result<(), <() as TryFromVal<Env, Val>>::Error>, Result<ContractError, InvokeError>>

    Executes an emergency withdrawal from a specific strategy.

    + caller: &Address, +) -> Result<Result<(), <() as TryFromVal<Env, Val>>::Error>, Result<ContractError, InvokeError>>

    Executes an emergency withdrawal from a specific strategy.

    This function allows the emergency manager or manager to withdraw all assets from a particular strategy and store them as idle funds within the vault. It also pauses the strategy to prevent further use until unpaused.

    -
    §Arguments:
    +
    §Arguments:
    • e - The environment.
    • strategy_address - The address of the strategy to withdraw from.
    • @@ -161,10 +215,10 @@
      §Returns:
      • Result<(), ContractError> - Ok if successful, otherwise returns a ContractError.
      -
    source

    pub fn pause_strategy(&self, strategy_address: &Address, caller: &Address)

    Pauses a strategy to prevent it from being used in the vault.

    +
    source

    pub fn pause_strategy(&self, strategy_address: &Address, caller: &Address)

    Pauses a strategy to prevent it from being used in the vault.

    This function pauses a strategy by setting its paused field to true. Only the manager or emergency manager can pause a strategy.

    -
    §Arguments:
    +
    §Arguments:
    • e - The environment.
    • strategy_address - The address of the strategy to pause.
    • @@ -174,14 +228,14 @@
      §Returns:
      • Result<(), ContractError> - Ok if successful, otherwise returns a ContractError.
      -
    source

    pub fn try_pause_strategy( +

    source

    pub fn try_pause_strategy( &self, strategy_address: &Address, - caller: &Address -) -> Result<Result<(), <() as TryFromVal<Env, Val>>::Error>, Result<ContractError, InvokeError>>

    Pauses a strategy to prevent it from being used in the vault.

    + caller: &Address, +) -> Result<Result<(), <() as TryFromVal<Env, Val>>::Error>, Result<ContractError, InvokeError>>

    Pauses a strategy to prevent it from being used in the vault.

    This function pauses a strategy by setting its paused field to true. Only the manager or emergency manager can pause a strategy.

    -
    §Arguments:
    +
    §Arguments:
    • e - The environment.
    • strategy_address - The address of the strategy to pause.
    • @@ -191,10 +245,10 @@
      §Returns:
      • Result<(), ContractError> - Ok if successful, otherwise returns a ContractError.
      -
    source

    pub fn unpause_strategy(&self, strategy_address: &Address, caller: &Address)

    Unpauses a previously paused strategy.

    +
    source

    pub fn unpause_strategy(&self, strategy_address: &Address, caller: &Address)

    Unpauses a previously paused strategy.

    This function unpauses a strategy by setting its paused field to false, allowing it to be used again in the vault.

    -
    §Arguments:
    +
    §Arguments:
    • e - The environment.
    • strategy_address - The address of the strategy to unpause.
    • @@ -204,14 +258,14 @@
      §Returns:
      • Result<(), ContractError> - Ok if successful, otherwise returns a ContractError.
      -
    source

    pub fn try_unpause_strategy( +

    source

    pub fn try_unpause_strategy( &self, strategy_address: &Address, - caller: &Address -) -> Result<Result<(), <() as TryFromVal<Env, Val>>::Error>, Result<ContractError, InvokeError>>

    Unpauses a previously paused strategy.

    + caller: &Address, +) -> Result<Result<(), <() as TryFromVal<Env, Val>>::Error>, Result<ContractError, InvokeError>>

    Unpauses a previously paused strategy.

    This function unpauses a strategy by setting its paused field to false, allowing it to be used again in the vault.

    -
    §Arguments:
    +
    §Arguments:
    • e - The environment.
    • strategy_address - The address of the strategy to unpause.
    • @@ -221,30 +275,32 @@
      §Returns:
      • Result<(), ContractError> - Ok if successful, otherwise returns a ContractError.
      -
    source

    pub fn get_assets(&self) -> Vec<AssetAllocation>

    Retrieves the list of assets managed by the DeFindex Vault.

    -
    §Arguments:
    +
    source

    pub fn get_assets(&self) -> Vec<AssetStrategySet>

    Retrieves the list of assets managed by the DeFindex Vault.

    +
    §Arguments:
    • e - The environment.
    §Returns:
      -
    • Vec<AssetAllocation> - A vector of AssetAllocation structs representing the assets managed by the vault.
    • +
    • Vec<AssetStrategySet> - A vector of AssetStrategySet structs representing the assets managed by the vault.
    -
    source

    pub fn try_get_assets( - &self -) -> Result<Result<Vec<AssetAllocation>, <Vec<AssetAllocation> as TryFromVal<Env, Val>>::Error>, Result<Error, InvokeError>>

    Retrieves the list of assets managed by the DeFindex Vault.

    -
    §Arguments:
    +
    source

    pub fn try_get_assets( + &self, +) -> Result<Result<Vec<AssetStrategySet>, <Vec<AssetStrategySet> as TryFromVal<Env, Val>>::Error>, Result<Error, InvokeError>>

    Retrieves the list of assets managed by the DeFindex Vault.

    +
    §Arguments:
    • e - The environment.
    §Returns:
      -
    • Vec<AssetAllocation> - A vector of AssetAllocation structs representing the assets managed by the vault.
    • +
    • Vec<AssetStrategySet> - A vector of AssetStrategySet structs representing the assets managed by the vault.
    -
    source

    pub fn fetch_total_managed_funds(&self) -> Map<Address, i128>

    Returns the total managed funds of the vault, including both invested and idle funds.

    +
    source

    pub fn fetch_total_managed_funds( + &self, +) -> Map<Address, CurrentAssetInvestmentAllocation>

    Returns the total managed funds of the vault, including both invested and idle funds.

    This function provides a map where the key is the asset address and the value is the total amount of that asset being managed by the vault.

    -
    §Arguments:
    +
    §Arguments:
    • e - The environment.
    @@ -252,12 +308,12 @@
    §Returns:
    • Map<Address, i128> - A map of asset addresses to their total managed amounts.
    -
    source

    pub fn try_fetch_total_managed_funds( - &self -) -> Result<Result<Map<Address, i128>, <Map<Address, i128> as TryFromVal<Env, Val>>::Error>, Result<Error, InvokeError>>

    Returns the total managed funds of the vault, including both invested and idle funds.

    +
    source

    pub fn try_fetch_total_managed_funds( + &self, +) -> Result<Result<Map<Address, CurrentAssetInvestmentAllocation>, <Map<Address, CurrentAssetInvestmentAllocation> as TryFromVal<Env, Val>>::Error>, Result<Error, InvokeError>>

    Returns the total managed funds of the vault, including both invested and idle funds.

    This function provides a map where the key is the asset address and the value is the total amount of that asset being managed by the vault.

    -
    §Arguments:
    +
    §Arguments:
    • e - The environment.
    @@ -265,10 +321,10 @@
    §Returns:
    • Map<Address, i128> - A map of asset addresses to their total managed amounts.
    -
    source

    pub fn fetch_current_invested_funds(&self) -> Map<Address, i128>

    Returns the current invested funds, representing the total assets allocated to strategies.

    +
    source

    pub fn fetch_current_invested_funds(&self) -> Map<Address, i128>

    Returns the current invested funds, representing the total assets allocated to strategies.

    This function provides a map where the key is the asset address and the value is the total amount of that asset currently invested in various strategies.

    -
    §Arguments:
    +
    §Arguments:
    • e - The environment.
    @@ -276,12 +332,12 @@
    §Returns:
    • Map<Address, i128> - A map of asset addresses to their total invested amounts.
    -
    source

    pub fn try_fetch_current_invested_funds( - &self -) -> Result<Result<Map<Address, i128>, <Map<Address, i128> as TryFromVal<Env, Val>>::Error>, Result<Error, InvokeError>>

    Returns the current invested funds, representing the total assets allocated to strategies.

    +
    source

    pub fn try_fetch_current_invested_funds( + &self, +) -> Result<Result<Map<Address, i128>, <Map<Address, i128> as TryFromVal<Env, Val>>::Error>, Result<Error, InvokeError>>

    Returns the current invested funds, representing the total assets allocated to strategies.

    This function provides a map where the key is the asset address and the value is the total amount of that asset currently invested in various strategies.

    -
    §Arguments:
    +
    §Arguments:
    • e - The environment.
    @@ -289,10 +345,10 @@
    §Returns:
    • Map<Address, i128> - A map of asset addresses to their total invested amounts.
    -
    source

    pub fn fetch_current_idle_funds(&self) -> Map<Address, i128>

    Returns the current idle funds, representing the total assets held directly by the vault (not invested).

    +
    source

    pub fn fetch_current_idle_funds(&self) -> Map<Address, i128>

    Returns the current idle funds, representing the total assets held directly by the vault (not invested).

    This function provides a map where the key is the asset address and the value is the total amount of that asset held as idle funds within the vault.

    -
    §Arguments:
    +
    §Arguments:
    • e - The environment.
    @@ -300,12 +356,12 @@
    §Returns:
    • Map<Address, i128> - A map of asset addresses to their total idle amounts.
    -
    source

    pub fn try_fetch_current_idle_funds( - &self -) -> Result<Result<Map<Address, i128>, <Map<Address, i128> as TryFromVal<Env, Val>>::Error>, Result<Error, InvokeError>>

    Returns the current idle funds, representing the total assets held directly by the vault (not invested).

    +
    source

    pub fn try_fetch_current_idle_funds( + &self, +) -> Result<Result<Map<Address, i128>, <Map<Address, i128> as TryFromVal<Env, Val>>::Error>, Result<Error, InvokeError>>

    Returns the current idle funds, representing the total assets held directly by the vault (not invested).

    This function provides a map where the key is the asset address and the value is the total amount of that asset held as idle funds within the vault.

    -
    §Arguments:
    +
    §Arguments:
    • e - The environment.
    @@ -313,236 +369,329 @@
    §Returns:
    • Map<Address, i128> - A map of asset addresses to their total idle amounts.
    -
    source

    pub fn get_asset_amounts_for_dftokens( +

    source

    pub fn get_asset_amounts_per_shares( + &self, + vault_shares: &i128, +) -> Map<Address, i128>

    This function extends the contract’s time-to-live and calculates how much of each asset corresponds +per the provided number of vault shares (vault_shares). It provides proportional allocations for each asset +in the vault relative to the specified shares.

    +
    §Arguments
    +
      +
    • e - The current environment reference.
    • +
    • vault_shares - The number of vault shares for which the corresponding asset amounts are calculated.
    • +
    +
    §Returns
    +
      +
    • Map<Address, i128> - A map containing each asset address and its corresponding proportional amount.
    • +
    +
    source

    pub fn try_get_asset_amounts_per_shares( + &self, + vault_shares: &i128, +) -> Result<Result<Map<Address, i128>, <Map<Address, i128> as TryFromVal<Env, Val>>::Error>, Result<ContractError, InvokeError>>

    This function extends the contract’s time-to-live and calculates how much of each asset corresponds +per the provided number of vault shares (vault_shares). It provides proportional allocations for each asset +in the vault relative to the specified shares.

    +
    §Arguments
    +
      +
    • e - The current environment reference.
    • +
    • vault_shares - The number of vault shares for which the corresponding asset amounts are calculated.
    • +
    +
    §Returns
    +
      +
    • Map<Address, i128> - A map containing each asset address and its corresponding proportional amount.
    • +
    +
    source

    pub fn get_fees(&self) -> (u32, u32)

    source

    pub fn try_get_fees( &self, - df_tokens: &i128 -) -> Map<Address, i128>

    Temporary method for testing purposes.

    -
    source

    pub fn try_get_asset_amounts_for_dftokens( +) -> Result<Result<(u32, u32), <(u32, u32) as TryFromVal<Env, Val>>::Error>, Result<Error, InvokeError>>

    source

    pub fn collect_fees(&self)

    source

    pub fn try_collect_fees( &self, - df_tokens: &i128 -) -> Result<Result<Map<Address, i128>, <Map<Address, i128> as TryFromVal<Env, Val>>::Error>, Result<Error, InvokeError>>

    Temporary method for testing purposes.

    -
    source§

    impl<'a> DeFindexVaultClient<'a>

    source

    pub fn set_fee_receiver(&self, caller: &Address, new_fee_receiver: &Address)

    Sets the fee receiver for the vault.

    +) -> Result<Result<(), <() as TryFromVal<Env, Val>>::Error>, Result<ContractError, InvokeError>>
    source§

    impl<'a> DeFindexVaultClient<'a>

    source

    pub fn set_fee_receiver(&self, caller: &Address, new_fee_receiver: &Address)

    Sets the fee receiver for the vault.

    This function allows the manager or emergency manager to set a new fee receiver address for the vault.

    §Arguments:
    • e - The environment.
    • caller - The address initiating the change (must be the manager or emergency manager).
    • -
    • fee_receiver - The new fee receiver address.
    • +
    • vault_fee_receiver - The new fee receiver address.
    -
    §Returns:
    +
    §Returns:
    • () - No return value.
    -
    source

    pub fn try_set_fee_receiver( +

    source

    pub fn try_set_fee_receiver( &self, caller: &Address, - new_fee_receiver: &Address -) -> Result<Result<(), <() as TryFromVal<Env, Val>>::Error>, Result<Error, InvokeError>>

    Sets the fee receiver for the vault.

    + new_fee_receiver: &Address, +) -> Result<Result<(), <() as TryFromVal<Env, Val>>::Error>, Result<Error, InvokeError>>

    Sets the fee receiver for the vault.

    This function allows the manager or emergency manager to set a new fee receiver address for the vault.

    §Arguments:
    • e - The environment.
    • caller - The address initiating the change (must be the manager or emergency manager).
    • -
    • fee_receiver - The new fee receiver address.
    • +
    • vault_fee_receiver - The new fee receiver address.
    -
    §Returns:
    +
    §Returns:
    • () - No return value.
    -
    source

    pub fn get_fee_receiver(&self) -> Address

    Retrieves the current fee receiver address for the vault.

    +
    source

    pub fn get_fee_receiver(&self) -> Address

    Retrieves the current fee receiver address for the vault.

    §Arguments:
    • e - The environment.
    -
    §Returns:
    +
    §Returns:
    • Result<Address, ContractError> - The fee receiver address if successful, otherwise returns a ContractError.
    -
    source

    pub fn try_get_fee_receiver( - &self -) -> Result<Result<Address, <Address as TryFromVal<Env, Val>>::Error>, Result<ContractError, InvokeError>>

    Retrieves the current fee receiver address for the vault.

    +
    source

    pub fn try_get_fee_receiver( + &self, +) -> Result<Result<Address, <Address as TryFromVal<Env, Val>>::Error>, Result<ContractError, InvokeError>>

    Retrieves the current fee receiver address for the vault.

    §Arguments:
    • e - The environment.
    -
    §Returns:
    +
    §Returns:
    • Result<Address, ContractError> - The fee receiver address if successful, otherwise returns a ContractError.
    -
    source

    pub fn set_manager(&self, manager: &Address)

    Sets the manager for the vault.

    +
    source

    pub fn set_manager(&self, manager: &Address)

    Sets the manager for the vault.

    This function allows the current manager or emergency manager to set a new manager for the vault.

    §Arguments:
    • e - The environment.
    • manager - The new manager address.
    -
    §Returns:
    +
    §Returns:
    • () - No return value.
    -
    source

    pub fn try_set_manager( +

    source

    pub fn try_set_manager( &self, - manager: &Address -) -> Result<Result<(), <() as TryFromVal<Env, Val>>::Error>, Result<Error, InvokeError>>

    Sets the manager for the vault.

    + manager: &Address, +) -> Result<Result<(), <() as TryFromVal<Env, Val>>::Error>, Result<Error, InvokeError>>

    Sets the manager for the vault.

    This function allows the current manager or emergency manager to set a new manager for the vault.

    §Arguments:
    • e - The environment.
    • manager - The new manager address.
    -
    §Returns:
    +
    §Returns:
    • () - No return value.
    -
    source

    pub fn get_manager(&self) -> Address

    Retrieves the current manager address for the vault.

    +
    source

    pub fn get_manager(&self) -> Address

    Retrieves the current manager address for the vault.

    §Arguments:
    • e - The environment.
    -
    §Returns:
    +
    §Returns:
    • Result<Address, ContractError> - The manager address if successful, otherwise returns a ContractError.
    -
    source

    pub fn try_get_manager( - &self -) -> Result<Result<Address, <Address as TryFromVal<Env, Val>>::Error>, Result<ContractError, InvokeError>>

    Retrieves the current manager address for the vault.

    +
    source

    pub fn try_get_manager( + &self, +) -> Result<Result<Address, <Address as TryFromVal<Env, Val>>::Error>, Result<ContractError, InvokeError>>

    Retrieves the current manager address for the vault.

    §Arguments:
    • e - The environment.
    -
    §Returns:
    +
    §Returns:
    • Result<Address, ContractError> - The manager address if successful, otherwise returns a ContractError.
    -
    source

    pub fn set_emergency_manager(&self, emergency_manager: &Address)

    Sets the emergency manager for the vault.

    +
    source

    pub fn set_emergency_manager(&self, emergency_manager: &Address)

    Sets the emergency manager for the vault.

    This function allows the current manager or emergency manager to set a new emergency manager for the vault.

    §Arguments:
    • e - The environment.
    • emergency_manager - The new emergency manager address.
    -
    §Returns:
    +
    §Returns:
    • () - No return value.
    -
    source

    pub fn try_set_emergency_manager( +

    source

    pub fn try_set_emergency_manager( &self, - emergency_manager: &Address -) -> Result<Result<(), <() as TryFromVal<Env, Val>>::Error>, Result<Error, InvokeError>>

    Sets the emergency manager for the vault.

    + emergency_manager: &Address, +) -> Result<Result<(), <() as TryFromVal<Env, Val>>::Error>, Result<Error, InvokeError>>

    Sets the emergency manager for the vault.

    This function allows the current manager or emergency manager to set a new emergency manager for the vault.

    §Arguments:
    • e - The environment.
    • emergency_manager - The new emergency manager address.
    -
    §Returns:
    +
    §Returns:
    • () - No return value.
    -
    source

    pub fn get_emergency_manager(&self) -> Address

    Retrieves the current emergency manager address for the vault.

    +
    source

    pub fn get_emergency_manager(&self) -> Address

    Retrieves the current emergency manager address for the vault.

    §Arguments:
    • e - The environment.
    -
    §Returns:
    +
    §Returns:
    • Result<Address, ContractError> - The emergency manager address if successful, otherwise returns a ContractError.
    -
    source

    pub fn try_get_emergency_manager( - &self -) -> Result<Result<Address, <Address as TryFromVal<Env, Val>>::Error>, Result<ContractError, InvokeError>>

    Retrieves the current emergency manager address for the vault.

    +
    source

    pub fn try_get_emergency_manager( + &self, +) -> Result<Result<Address, <Address as TryFromVal<Env, Val>>::Error>, Result<ContractError, InvokeError>>

    Retrieves the current emergency manager address for the vault.

    §Arguments:
    • e - The environment.
    -
    §Returns:
    +
    §Returns:
    • Result<Address, ContractError> - The emergency manager address if successful, otherwise returns a ContractError.
    -
    source§

    impl<'a> DeFindexVaultClient<'a>

    source

    pub fn invest(&self, investments: &Vec<Investment>)

    Invests the vault’s idle funds into the specified strategies.

    -
    §Arguments:
    +
    source§

    impl<'a> DeFindexVaultClient<'a>

    source

    pub fn invest(&self, asset_investments: &Vec<Option<AssetInvestmentAllocation>>)

    Executes the investment of the vault’s idle funds based on the specified asset allocations. +This function allows partial investments by providing an optional allocation for each asset, +and it ensures proper authorization and validation checks before proceeding with investments.

    +
    §Arguments
    +
      +
    • e - The current environment reference.
    • +
    • asset_investments - A vector of optional AssetInvestmentAllocation structures, where each element +represents an allocation for a specific asset. The vector must match the number of vault assets in length.
    • +
    +
    §Returns
    +
      +
    • Result<(), ContractError> - Returns Ok(()) if the investments are successful or a ContractError +if any issue occurs during validation or execution.
    • +
    +
    §Function Flow
    +
      +
    1. Extend Instance TTL: Extends the contract instance’s time-to-live to keep the instance active.
    2. +
    3. Check Initialization: Verifies that the vault is properly initialized before proceeding.
    4. +
    5. Access Control: Ensures the caller has the Manager role required to initiate investments.
    6. +
    7. Asset Count Validation: Verifies that the length of the asset_investments vector matches +the number of assets managed by the vault. If they don’t match, a WrongInvestmentLength error is returned.
    8. +
    9. Investment Execution: Calls the check_and_execute_investments function to perform the investment +after validating the inputs and ensuring correct execution flows for each asset allocation.
    10. +
    +
    §Errors
    +
      +
    • Returns ContractError::WrongInvestmentLength if the length of asset_investments does not match the vault assets.
    • +
    • Returns ContractError if access control validation fails or if investment execution encounters an issue.
    • +
    +
    §Security
    +
      +
    • Only addresses with the Manager role can call this function, ensuring restricted access to managing investments.
    • +
    +
    source

    pub fn try_invest( + &self, + asset_investments: &Vec<Option<AssetInvestmentAllocation>>, +) -> Result<Result<(), <() as TryFromVal<Env, Val>>::Error>, Result<ContractError, InvokeError>>

    Executes the investment of the vault’s idle funds based on the specified asset allocations. +This function allows partial investments by providing an optional allocation for each asset, +and it ensures proper authorization and validation checks before proceeding with investments.

    +
    §Arguments
    +
      +
    • e - The current environment reference.
    • +
    • asset_investments - A vector of optional AssetInvestmentAllocation structures, where each element +represents an allocation for a specific asset. The vector must match the number of vault assets in length.
    • +
    +
    §Returns
    +
      +
    • Result<(), ContractError> - Returns Ok(()) if the investments are successful or a ContractError +if any issue occurs during validation or execution.
    • +
    +
    §Function Flow
    +
      +
    1. Extend Instance TTL: Extends the contract instance’s time-to-live to keep the instance active.
    2. +
    3. Check Initialization: Verifies that the vault is properly initialized before proceeding.
    4. +
    5. Access Control: Ensures the caller has the Manager role required to initiate investments.
    6. +
    7. Asset Count Validation: Verifies that the length of the asset_investments vector matches +the number of assets managed by the vault. If they don’t match, a WrongInvestmentLength error is returned.
    8. +
    9. Investment Execution: Calls the check_and_execute_investments function to perform the investment +after validating the inputs and ensuring correct execution flows for each asset allocation.
    10. +
    +
    §Errors
    +
      +
    • Returns ContractError::WrongInvestmentLength if the length of asset_investments does not match the vault assets.
    • +
    • Returns ContractError if access control validation fails or if investment execution encounters an issue.
    • +
    +
    §Security
    +
      +
    • Only addresses with the Manager role can call this function, ensuring restricted access to managing investments.
    • +
    +
    source

    pub fn rebalance(&self, instructions: &Vec<Instruction>)

    Rebalances the vault by executing a series of instructions.

    +
    §Arguments:
    • e - The environment.
    • -
    • investment - A vector of Investment structs representing the amount to invest in each strategy.
    • -
    • caller - The address of the caller.
    • +
    • instructions - A vector of Instruction structs representing actions (withdraw, invest, swap, zapper) to be taken.
    -
    §Returns:
    +
    §Returns:
    • Result<(), ContractError> - Ok if successful, otherwise returns a ContractError.
    -
    source

    pub fn try_invest( +

    source

    pub fn try_rebalance( &self, - investments: &Vec<Investment> -) -> Result<Result<(), <() as TryFromVal<Env, Val>>::Error>, Result<ContractError, InvokeError>>

    Invests the vault’s idle funds into the specified strategies.

    -
    §Arguments:
    + instructions: &Vec<Instruction>, +) -> Result<Result<(), <() as TryFromVal<Env, Val>>::Error>, Result<ContractError, InvokeError>>

    Rebalances the vault by executing a series of instructions.

    +
    §Arguments:
    • e - The environment.
    • -
    • investment - A vector of Investment structs representing the amount to invest in each strategy.
    • -
    • caller - The address of the caller.
    • +
    • instructions - A vector of Instruction structs representing actions (withdraw, invest, swap, zapper) to be taken.
    -
    §Returns:
    +
    §Returns:
    • Result<(), ContractError> - Ok if successful, otherwise returns a ContractError.
    -

    Auto Trait Implementations§

    §

    impl<'a> Freeze for DeFindexVaultClient<'a>

    §

    impl<'a> !RefUnwindSafe for DeFindexVaultClient<'a>

    §

    impl<'a> !Send for DeFindexVaultClient<'a>

    §

    impl<'a> !Sync for DeFindexVaultClient<'a>

    §

    impl<'a> Unpin for DeFindexVaultClient<'a>

    §

    impl<'a> !UnwindSafe for DeFindexVaultClient<'a>

    Blanket Implementations§

    source§

    impl<T> Any for T
    where - T: 'static + ?Sized,

    source§

    fn type_id(&self) -> TypeId

    Gets the TypeId of self. Read more
    source§

    impl<T> Borrow<T> for T
    where - T: ?Sized,

    source§

    fn borrow(&self) -> &T

    Immutably borrows from an owned value. Read more
    source§

    impl<T> BorrowMut<T> for T
    where - T: ?Sized,

    source§

    fn borrow_mut(&mut self) -> &mut T

    Mutably borrows from an owned value. Read more
    §

    impl<T, C> Compare<&T> for C
    where - C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare(&self, a: &&T, b: &&T) -> Result<Ordering, <C as Compare<&T>>::Error>

    §

    impl<T, U, E, C> Compare<(T, U)> for C
    where - C: Compare<T, Error = E, Error = E> + Compare<U>,

    §

    type Error = E

    §

    fn compare( - &self, - a: &(T, U), - b: &(T, U) -) -> Result<Ordering, <C as Compare<(T, U)>>::Error>

    §

    impl<T, U, V, E, C> Compare<(T, U, V)> for C
    where - C: Compare<T, Error = E, Error = E, Error = E> + Compare<U> + Compare<V>,

    §

    type Error = E

    §

    fn compare( - &self, - a: &(T, U, V), - b: &(T, U, V) -) -> Result<Ordering, <C as Compare<(T, U, V)>>::Error>

    §

    impl<T, U, V, W, E, C> Compare<(T, U, V, W)> for C
    where - C: Compare<T, Error = E, Error = E, Error = E, Error = E> + Compare<U> + Compare<V> + Compare<W>,

    §

    type Error = E

    §

    fn compare( - &self, - a: &(T, U, V, W), - b: &(T, U, V, W) -) -> Result<Ordering, <C as Compare<(T, U, V, W)>>::Error>

    §

    impl<T, U, V, W, X, E, C> Compare<(T, U, V, W, X)> for C
    where - C: Compare<T, Error = E, Error = E, Error = E, Error = E, Error = E> + Compare<U> + Compare<V> + Compare<W> + Compare<X>,

    §

    type Error = E

    §

    fn compare( - &self, - a: &(T, U, V, W, X), - b: &(T, U, V, W, X) -) -> Result<Ordering, <C as Compare<(T, U, V, W, X)>>::Error>

    §

    impl<T, C> Compare<Box<T>> for C
    where - C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare( - &self, - a: &Box<T>, - b: &Box<T> -) -> Result<Ordering, <C as Compare<Box<T>>>::Error>

    §

    impl<T, C> Compare<Option<T>> for C
    where - C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare( - &self, - a: &Option<T>, - b: &Option<T> -) -> Result<Ordering, <C as Compare<Option<T>>>::Error>

    §

    impl<T, C> Compare<Rc<T>> for C
    where - C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare( - &self, - a: &Rc<T>, - b: &Rc<T> -) -> Result<Ordering, <C as Compare<Rc<T>>>::Error>

    §

    impl<T, C> Compare<Vec<T>> for C
    where - C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare( - &self, - a: &Vec<T>, - b: &Vec<T> -) -> Result<Ordering, <C as Compare<Vec<T>>>::Error>

    §

    impl<T> Downcast for T
    where - T: Any,

    §

    fn into_any(self: Box<T>) -> Box<dyn Any>

    Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can -then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
    §

    fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

    Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be -further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
    §

    fn as_any(&self) -> &(dyn Any + 'static)

    Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot -generate &Any’s vtable from &Trait’s.
    §

    fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

    Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot -generate &mut Any’s vtable from &mut Trait’s.
    source§

    impl<T> From<T> for T

    source§

    fn from(t: T) -> T

    Returns the argument unchanged.

    -
    source§

    impl<T, U> Into<U> for T
    where - U: From<T>,

    source§

    fn into(self) -> U

    Calls U::from(self).

    +

    Auto Trait Implementations§

    §

    impl<'a> Freeze for DeFindexVaultClient<'a>

    §

    impl<'a> !RefUnwindSafe for DeFindexVaultClient<'a>

    §

    impl<'a> !Send for DeFindexVaultClient<'a>

    §

    impl<'a> !Sync for DeFindexVaultClient<'a>

    §

    impl<'a> Unpin for DeFindexVaultClient<'a>

    §

    impl<'a> !UnwindSafe for DeFindexVaultClient<'a>

    Blanket Implementations§

    source§

    impl<T> Any for T
    where + T: 'static + ?Sized,

    source§

    fn type_id(&self) -> TypeId

    Gets the TypeId of self. Read more
    source§

    impl<T> Borrow<T> for T
    where + T: ?Sized,

    source§

    fn borrow(&self) -> &T

    Immutably borrows from an owned value. Read more
    source§

    impl<T> BorrowMut<T> for T
    where + T: ?Sized,

    source§

    fn borrow_mut(&mut self) -> &mut T

    Mutably borrows from an owned value. Read more
    §

    impl<T, C> Compare<&T> for C
    where + C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare(&self, a: &&T, b: &&T) -> Result<Ordering, <C as Compare<&T>>::Error>

    §

    impl<T, U, E, C> Compare<(T, U)> for C
    where + C: Compare<T, Error = E, Error = E> + Compare<U>,

    §

    type Error = E

    §

    fn compare( + &self, + a: &(T, U), + b: &(T, U), +) -> Result<Ordering, <C as Compare<(T, U)>>::Error>

    §

    impl<T, U, V, E, C> Compare<(T, U, V)> for C
    where + C: Compare<T, Error = E, Error = E, Error = E> + Compare<U> + Compare<V>,

    §

    type Error = E

    §

    fn compare( + &self, + a: &(T, U, V), + b: &(T, U, V), +) -> Result<Ordering, <C as Compare<(T, U, V)>>::Error>

    §

    impl<T, U, V, W, E, C> Compare<(T, U, V, W)> for C
    where + C: Compare<T, Error = E, Error = E, Error = E, Error = E> + Compare<U> + Compare<V> + Compare<W>,

    §

    type Error = E

    §

    fn compare( + &self, + a: &(T, U, V, W), + b: &(T, U, V, W), +) -> Result<Ordering, <C as Compare<(T, U, V, W)>>::Error>

    §

    impl<T, U, V, W, X, E, C> Compare<(T, U, V, W, X)> for C
    where + C: Compare<T, Error = E, Error = E, Error = E, Error = E, Error = E> + Compare<U> + Compare<V> + Compare<W> + Compare<X>,

    §

    type Error = E

    §

    fn compare( + &self, + a: &(T, U, V, W, X), + b: &(T, U, V, W, X), +) -> Result<Ordering, <C as Compare<(T, U, V, W, X)>>::Error>

    §

    impl<T, C> Compare<Box<T>> for C
    where + C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare( + &self, + a: &Box<T>, + b: &Box<T>, +) -> Result<Ordering, <C as Compare<Box<T>>>::Error>

    §

    impl<T, C> Compare<Option<T>> for C
    where + C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare( + &self, + a: &Option<T>, + b: &Option<T>, +) -> Result<Ordering, <C as Compare<Option<T>>>::Error>

    §

    impl<T, C> Compare<Rc<T>> for C
    where + C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare( + &self, + a: &Rc<T>, + b: &Rc<T>, +) -> Result<Ordering, <C as Compare<Rc<T>>>::Error>

    §

    impl<T, C> Compare<Vec<T>> for C
    where + C: Compare<T>,

    §

    type Error = <C as Compare<T>>::Error

    §

    fn compare( + &self, + a: &Vec<T>, + b: &Vec<T>, +) -> Result<Ordering, <C as Compare<Vec<T>>>::Error>

    §

    impl<T> Downcast for T
    where + T: Any,

    §

    fn into_any(self: Box<T>) -> Box<dyn Any>

    Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can +then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
    §

    fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

    Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be +further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
    §

    fn as_any(&self) -> &(dyn Any + 'static)

    Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot +generate &Any’s vtable from &Trait’s.
    §

    fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

    Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot +generate &mut Any’s vtable from &mut Trait’s.
    source§

    impl<T> From<T> for T

    source§

    fn from(t: T) -> T

    Returns the argument unchanged.

    +
    source§

    impl<T, U> Into<U> for T
    where + U: From<T>,

    source§

    fn into(self) -> U

    Calls U::from(self).

    That is, this conversion is whatever the implementation of -From<T> for U chooses to do.

    +From<T> for U chooses to do.

    §

    impl<E, T, U> IntoVal<E, T> for U
    where E: Env, - T: FromVal<E, U>,

    §

    fn into_val(&self, e: &E) -> T

    source§

    impl<T> Same for T

    §

    type Output = T

    Should always be Self
    source§

    impl<T, U> TryFrom<U> for T
    where - U: Into<T>,

    §

    type Error = Infallible

    The type returned in the event of a conversion error.
    source§

    fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

    Performs the conversion.
    source§

    impl<T, U> TryInto<U> for T
    where - U: TryFrom<T>,

    §

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.
    source§

    fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

    Performs the conversion.
    §

    impl<E, T, U> TryIntoVal<E, T> for U
    where + T: FromVal<E, U>,

    §

    fn into_val(&self, e: &E) -> T

    source§

    impl<T> Same for T

    source§

    type Output = T

    Should always be Self
    source§

    impl<T, U> TryFrom<U> for T
    where + U: Into<T>,

    source§

    type Error = Infallible

    The type returned in the event of a conversion error.
    source§

    fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

    Performs the conversion.
    source§

    impl<T, U> TryInto<U> for T
    where + U: TryFrom<T>,

    source§

    type Error = <U as TryFrom<T>>::Error

    The type returned in the event of a conversion error.
    source§

    fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

    Performs the conversion.
    §

    impl<E, T, U> TryIntoVal<E, T> for U
    where E: Env, - T: TryFromVal<E, U>,

    §

    type Error = <T as TryFromVal<E, U>>::Error

    §

    fn try_into_val(&self, env: &E) -> Result<T, <U as TryIntoVal<E, T>>::Error>

    §

    impl<V, T> VZip<V> for T
    where + T: TryFromVal<E, U>,

    §

    type Error = <T as TryFromVal<E, U>>::Error

    §

    fn try_into_val(&self, env: &E) -> Result<T, <U as TryIntoVal<E, T>>::Error>

    §

    impl<V, T> VZip<V> for T
    where V: MultiLane<T>,

    §

    fn vzip(self) -> V

    \ No newline at end of file diff --git a/apps/rust_docs/help.html b/apps/rust_docs/help.html index d7ab01a5..9b404d2f 100644 --- a/apps/rust_docs/help.html +++ b/apps/rust_docs/help.html @@ -1 +1 @@ -Help

    Rustdoc help

    Back
    \ No newline at end of file +Help

    Rustdoc help

    Back
    \ No newline at end of file diff --git a/apps/rust_docs/search-index.js b/apps/rust_docs/search-index.js index b018c62c..c3f12732 100644 --- a/apps/rust_docs/search-index.js +++ b/apps/rust_docs/search-index.js @@ -1,7 +1,4 @@ -var searchIndex = new Map(JSON.parse('[\ -["defindex_factory",{"t":"FKOMNNNNNNNNNNNNNNMNMNMNOMNNMNNNNNNMNMNMNNNNNNNNNNNNNNN","n":["DeFindexFactoryClient","FactoryTrait","address","admin","admin","as_any","as_any_mut","borrow","borrow_mut","compare","compare","compare","compare","compare","compare","compare","compare","compare","create_defindex_vault","create_defindex_vault","defindex_receiver","defindex_receiver","deployed_defindexes","deployed_defindexes","env","fee_rate","fee_rate","from","initialize","initialize","into","into_any","into_any_rc","into_val","new","set_defindex_receiver","set_defindex_receiver","set_fee_rate","set_fee_rate","set_new_admin","set_new_admin","try_admin","try_create_defindex_vault","try_defindex_receiver","try_deployed_defindexes","try_fee_rate","try_from","try_initialize","try_into","try_into_val","try_set_defindex_receiver","try_set_fee_rate","try_set_new_admin","type_id","vzip"],"q":[[0,"defindex_factory"],[55,"soroban_sdk::env"],[56,"soroban_sdk::address"],[57,"core::result"],[58,"core::any"],[59,"core::cmp"],[60,"alloc::rc"],[61,"core::option"],[62,"alloc::vec"],[63,"alloc::boxed"],[64,"soroban_sdk::vec"],[65,"soroban_sdk::bytes"],[66,"soroban_sdk::map"],[67,"soroban_sdk::error"]],"i":[0,0,4,19,4,4,4,4,4,4,4,4,4,4,4,4,4,4,19,4,19,4,19,4,4,19,4,4,19,4,4,4,4,4,4,19,4,19,4,19,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4],"f":"```{b{{f{d`}}}}{hd}{cj{}}0{ce{}{}}0{{c{l{egikm}}{l{egikm}}}{{f{n}}}{}{}{}{}{}{}}{{cee}{{f{n}}}{}{}}{{c{l{egi}}{l{egi}}}{{f{n}}}{}{}{}{}}{{c{l{eg}}{l{eg}}}{{f{n}}}{}{}{}}{{c{l{egik}}{l{egik}}}{{f{n}}}{}{}{}{}{}}{{c{A`{e}}{A`{e}}}{{f{n}}}{}{}}{{c{Ab{e}}{Ab{e}}}{{f{n}}}{}{}}{{c{Ad{e}}{Ad{e}}}{{f{n}}}{}{}}{{c{Af{e}}{Af{e}}}{{f{n}}}{}{}}{{bddAhd{Aj{`}}Al}{{f{d`}}}}{{hddAhd{Aj{`}}Al}d}>={b{{f{{An{Ahd}}`}}}}{h{{An{Ahd}}}}`{b{{f{Ah`}}}}{hAh}{cc{}}{{bddAhAl}{{f{B``}}}}{{hddAhAl}B`}{ce{}{}}{{{Af{c}}}{{Af{j}}}{}}{{{A`{c}}}{{A`{j}}}{}}{{ce}g{}{}{}}{{bd}h}{{bd}{{f{B``}}}}{{hd}B`}{{bAh}{{f{B``}}}}{{hAh}B`}32{h{{f{{f{d}}{f{`Bb}}}}}}{{hddAhd{Aj{`}}Al}{{f{{f{d}}{f{`Bb}}}}}}1{h{{f{{f{{An{Ahd}}}}{f{`Bb}}}}}}{h{{f{{f{Ah}}{f{`Bb}}}}}}{c{{f{e}}}{}{}}{{hddAhAl}{{f{{f{B`}}{f{`Bb}}}}}}1{{ce}{{f{g}}}{}{}{}}{{hd}{{f{{f{B`}}{f{`Bb}}}}}}{{hAh}{{f{{f{B`}}{f{`Bb}}}}}}1{cBd{}}{ce{}{}}","D":"Cl","p":[[5,"Env",55],[5,"Address",56],[6,"Result",57],[5,"DeFindexFactoryClient",0],[10,"Any",58],[1,"tuple"],[6,"Ordering",59],[5,"Rc",60],[6,"Option",61],[5,"Vec",62],[5,"Box",63],[1,"u32"],[5,"Vec",64],[5,"BytesN",65],[5,"Map",66],[1,"unit"],[6,"InvokeError",67],[5,"TypeId",58],[10,"FactoryTrait",0]],"r":[],"b":[],"c":"OjAAAAAAAAA=","e":"OzAAAAEAABkACAAAAAAAAgABAAYADAAZAAAAIAADAC8AAAAxAAEANgABAA=="}],\ -["defindex_strategy_core",{"t":"PFKPPPPPPFGONNNNNNMNMNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNMNONNNNCNNNNNNMNMNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNMNFFFFJJJJOOONNNNNNNNONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNHHHHNNNNNNNNNNNNNNNNNNNNNNNNOOONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN","n":["AlreadyInitialized","DeFindexStrategyClient","DeFindexStrategyTrait","DeadlineExpired","ExternalError","InvalidArgument","NegativeNotAllowed","NotInitialized","ProtocolAddressNotFound","Spec","StrategyError","address","as_any","as_any","as_any","as_any_mut","as_any_mut","as_any_mut","asset","asset","balance","balance","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","clone","clone_into","cmp","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","deposit","deposit","env","eq","equivalent","equivalent","equivalent","event","fmt","from","from","from","from_val","from_xdr","harvest","harvest","initialize","initialize","into","into","into","into_any","into_any","into_any","into_any_arc","into_any_arc","into_any_rc","into_any_rc","into_any_rc","into_val","into_val","into_val","new","partial_cmp","spec_xdr","spec_xdr_asset","spec_xdr_balance","spec_xdr_deposit","spec_xdr_harvest","spec_xdr_initialize","spec_xdr_withdraw","to_owned","to_xdr","try_asset","try_balance","try_deposit","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from_val","try_harvest","try_initialize","try_into","try_into","try_into","try_into_val","try_into_val","try_into_val","try_withdraw","type_id","type_id","type_id","vzip","vzip","vzip","withdraw","withdraw","DepositEvent","HarvestEvent","InitializedEvent","WithdrawEvent","__SPEC_XDR_TYPE_DEPOSITEVENT","__SPEC_XDR_TYPE_HARVESTEVENT","__SPEC_XDR_TYPE_INITIALIZEDEVENT","__SPEC_XDR_TYPE_WITHDRAWEVENT","amount","amount","amount","as_any","as_any","as_any","as_any","as_any_mut","as_any_mut","as_any_mut","as_any_mut","asset","borrow","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","borrow_mut","clone","clone","clone","clone","clone_into","clone_into","clone_into","clone_into","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","emit_deposit","emit_harvest","emit_initialize","emit_withdraw","eq","eq","eq","eq","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","equivalent","fmt","fmt","fmt","fmt","from","from","from","from","from","from","from","from_val","from_val","from_val","from_val","from_xdr","from_xdr","from_xdr","from_xdr","into","into","into","into","into_any","into_any","into_any","into_any","into_any_rc","into_any_rc","into_any_rc","into_any_rc","into_val","into_val","into_val","into_val","spec_xdr","spec_xdr","spec_xdr","spec_xdr","to_owned","to_owned","to_owned","to_owned","to_xdr","to_xdr","to_xdr","to_xdr","try_from","try_from","try_from","try_from","try_from_val","try_from_val","try_from_val","try_from_val","try_into","try_into","try_into","try_into","try_into_val","try_into_val","try_into_val","try_into_val","type_id","type_id","type_id","type_id","vzip","vzip","vzip","vzip"],"q":[[0,"defindex_strategy_core"],[130,"defindex_strategy_core::event"],[293,"core::any"],[294,"soroban_sdk::env"],[295,"soroban_sdk::address"],[296,"defindex_strategy_core::error"],[297,"core::result"],[298,"core::cmp"],[299,"core::option"],[300,"alloc::rc"],[301,"alloc::boxed"],[302,"alloc::vec"],[303,"core::fmt"],[304,"soroban_sdk::bytes"],[305,"soroban_env_common::val"],[306,"soroban_sdk::vec"],[307,"alloc::sync"],[308,"soroban_sdk::error"],[309,"soroban_env_common::error"],[310,"soroban_sdk::string"]],"i":[4,0,0,4,4,4,4,4,4,0,0,6,33,4,6,33,4,6,34,6,34,6,33,4,6,33,4,6,4,4,4,33,33,33,33,33,33,33,33,33,4,4,4,4,4,4,4,4,4,4,6,6,6,6,6,6,6,6,6,34,6,6,4,4,4,4,0,4,33,4,6,4,4,34,6,34,6,33,4,6,33,4,6,33,4,33,4,6,33,4,6,6,4,4,33,33,33,33,33,33,4,4,6,6,6,33,4,4,4,4,4,6,4,6,6,33,4,6,33,4,6,6,33,4,6,33,4,6,34,6,0,0,0,0,0,0,0,0,29,30,31,28,29,30,31,28,29,30,31,28,28,29,30,31,28,29,30,31,28,29,30,31,28,29,30,31,28,28,28,28,28,28,28,28,28,29,29,29,29,29,29,29,29,29,30,30,30,30,30,30,30,30,30,31,31,31,31,31,31,31,31,31,0,0,0,0,28,29,30,31,28,28,28,29,29,29,30,30,30,31,31,31,28,29,30,31,28,29,30,31,29,30,31,28,29,30,31,28,29,30,31,28,29,30,31,28,29,30,31,28,29,30,31,28,29,30,31,28,29,30,31,28,29,30,31,28,29,30,31,28,29,30,31,28,29,30,31,28,29,30,31,28,29,30,31,28,29,30,31,28,29,30,31],"f":"````````````{cb{}}00000{d{{j{fh}}}}{lf}{{df}{{j{nh}}}}{{lf}n}{ce{}{}}00000{hh}{{ce}A`{}{}}{{hh}Ab}{{cee}{{j{Ab}}}{}{}}{{c{Ad{egi}}{Ad{egi}}}{{j{Ab}}}{}{}{}{}}{{c{Ad{egik}}{Ad{egik}}}{{j{Ab}}}{}{}{}{}{}}{{c{Af{e}}{Af{e}}}{{j{Ab}}}{}{}}{{c{Ad{eg}}{Ad{eg}}}{{j{Ab}}}{}{}{}}{{c{Ah{e}}{Ah{e}}}{{j{Ab}}}{}{}}{{c{Ad{egikm}}{Ad{egikm}}}{{j{Ab}}}{}{}{}{}{}{}}{{c{Aj{e}}{Aj{e}}}{{j{Ab}}}{}{}}{{c{Al{e}}{Al{e}}}{{j{Ab}}}{}{}}{{ce}Ab{}{}}561298347132675489{{dnf}{{j{A`h}}}}{{lnf}A`}`{{hh}An}{{ce}An{}{}}00`{{hB`}Bb}{cc{}}00{{ce}g{}{}{}}{{dBd}{{j{c}}}{}}{{df}{{j{A`h}}}}{{lf}A`}{{df{Bh{Bf}}}{{j{A`h}}}}{{lf{Bh{Bf}}}A`}{ce{}{}}00{{{Aj{c}}}{{Aj{b}}}{}}00{{{Bj{c}}}{{Bj{b}}}{}}0{{{Ah{c}}}{{Ah{b}}}{}}00999{{df}l}{{hh}{{Af{Ab}}}}{{}{{Bn{Bl}}}}0000006{{cd}Bd{}}{l{{j{{j{f}}{j{hC`}}}}}}{{lf}{{j{{j{n}}{j{hC`}}}}}}{{lnf}{{j{{j{A`}}{j{hC`}}}}}}{c{{j{e}}}{}{}}{C`{{j{hC`}}}}{Cb{{j{hCb}}}}1202{{dBf}{{j{hCd}}}}{{lf}{{j{{j{A`}}{j{hC`}}}}}}{{lf{Bh{Bf}}}{{j{{j{A`}}{j{hC`}}}}}}555{{ce}{{j{g}}}{}{}{}}00{{lnf}{{j{{j{n}}{j{hC`}}}}}}{cCf{}}00{ce{}{}}00{{dnf}{{j{nh}}}}{{lnf}n}```````````{cb{}}0000000`33333333{ChCh}{CjCj}{ClCl}{CnCn}{{ce}A`{}{}}000{{c{Af{e}}{Af{e}}}{{j{Ab}}}{}{}}{{c{Ah{e}}{Ah{e}}}{{j{Ab}}}{}{}}{{c{Ad{egikm}}{Ad{egikm}}}{{j{Ab}}}{}{}{}{}{}{}}{{c{Aj{e}}{Aj{e}}}{{j{Ab}}}{}{}}{{c{Al{e}}{Al{e}}}{{j{Ab}}}{}{}}{{c{Ad{egik}}{Ad{egik}}}{{j{Ab}}}{}{}{}{}{}}{{c{Ad{eg}}{Ad{eg}}}{{j{Ab}}}{}{}{}}{{c{Ad{egi}}{Ad{egi}}}{{j{Ab}}}{}{}{}{}}{{cee}{{j{Ab}}}{}{}}701238456061583472283410765{{dD`nf}A`}0{{dD`f}A`}1{{ChCh}An}{{CjCj}An}{{ClCl}An}{{CnCn}An}{{ce}An{}{}}00000000000{{ChB`}Bb}{{CjB`}Bb}{{ClB`}Bb}{{CnB`}Bb}{cc{}}000```{{ce}g{}{}{}}000{{dBd}{{j{c}}}{}}000{ce{}{}}000{{{Aj{c}}}{{Aj{b}}}{}}000{{{Ah{c}}}{{Ah{b}}}{}}0004444{{}{{Bn{Bl}}}}0003333{{cd}Bd{}}000{c{{j{e}}}{}{}}000{{dBf}{{j{ChCd}}}}{{dBf}{{j{CjCd}}}}{{dBf}{{j{ClCd}}}}{{dBf}{{j{CnCd}}}}4444{{ce}{{j{g}}}{}{}{}}000{cCf{}}000;;;;","D":"Ej","p":[[10,"Any",293],[5,"Env",294],[5,"Address",295],[6,"StrategyError",0,296],[6,"Result",297],[5,"DeFindexStrategyClient",0],[1,"i128"],[1,"unit"],[6,"Ordering",298],[1,"tuple"],[6,"Option",299],[5,"Rc",300],[5,"Box",301],[5,"Vec",302],[1,"bool"],[5,"Formatter",303],[8,"Result",303],[5,"Bytes",304],[5,"Val",305],[5,"Vec",306],[5,"Arc",307],[1,"u8"],[1,"array"],[6,"InvokeError",308],[5,"Error",309],[5,"ConversionError",305],[5,"TypeId",293],[5,"InitializedEvent",130],[5,"DepositEvent",130],[5,"HarvestEvent",130],[5,"WithdrawEvent",130],[5,"String",310],[5,"Spec",0],[10,"DeFindexStrategyTrait",0]],"r":[[10,296]],"b":[[106,"impl-TryFrom%3CInvokeError%3E-for-StrategyError"],[107,"impl-TryFrom%3CError%3E-for-StrategyError"],[108,"impl-TryFrom%3C%26InvokeError%3E-for-StrategyError"],[110,"impl-TryFrom%3C%26Error%3E-for-StrategyError"]],"c":"OjAAAAAAAAA=","e":"OzAAAAEAAPgADwAAAAEABAAOABcAJAA+AAQARAAAAEgAAQBRAA0AZQABAGoABwB0AAUAewAFAIMARwDPABMA5wAKAPYALwA="}],\ -["defindex_vault",{"t":"PPPGFFPPPPPPPPPPPPPPONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN","n":["AlreadyInitialized","ArithmeticError","AssetNotFound","ContractError","DeFindexVault","DeFindexVaultClient","InsufficientBalance","InsufficientManagedFunds","InvalidRatio","NegativeNotAllowed","NoAssetsProvided","NotEnoughIdleFunds","NotInitialized","Overflow","RoleNotFound","StrategyDoesNotSupportAsset","StrategyNotFound","StrategyPausedOrNotFound","Unauthorized","WrongAmuntsLength","address","as_any","as_any","as_any","as_any_mut","as_any_mut","as_any_mut","borrow","borrow","borrow","borrow_mut","borrow_mut","borrow_mut","clone","clone_into","cmp","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","compare","deposit","emergency_withdraw","env","eq","equivalent","equivalent","equivalent","fetch_current_idle_funds","fetch_current_invested_funds","fetch_total_managed_funds","fmt","from","from","from","from_val","from_xdr","get_asset_amounts_for_dftokens","get_assets","get_emergency_manager","get_fee_receiver","get_manager","initialize","into","into","into","into_any","into_any","into_any","into_any_arc","into_any_arc","into_any_rc","into_any_rc","into_any_rc","into_val","into_val","into_val","invest","new","partial_cmp","pause_strategy","set_emergency_manager","set_fee_receiver","set_manager","spec_xdr","spec_xdr_deposit","spec_xdr_emergency_withdraw","spec_xdr_fetch_current_idle_funds","spec_xdr_fetch_current_invested_funds","spec_xdr_fetch_total_managed_funds","spec_xdr_get_asset_amounts_for_dftokens","spec_xdr_get_assets","spec_xdr_get_emergency_manager","spec_xdr_get_fee_receiver","spec_xdr_get_manager","spec_xdr_initialize","spec_xdr_invest","spec_xdr_pause_strategy","spec_xdr_set_emergency_manager","spec_xdr_set_fee_receiver","spec_xdr_set_manager","spec_xdr_unpause_strategy","spec_xdr_withdraw","to_owned","to_xdr","try_deposit","try_emergency_withdraw","try_fetch_current_idle_funds","try_fetch_current_invested_funds","try_fetch_total_managed_funds","try_from","try_from","try_from","try_from","try_from","try_from","try_from","try_from_val","try_get_asset_amounts_for_dftokens","try_get_assets","try_get_emergency_manager","try_get_fee_receiver","try_get_manager","try_initialize","try_into","try_into","try_into","try_into_val","try_into_val","try_into_val","try_invest","try_pause_strategy","try_set_emergency_manager","try_set_fee_receiver","try_set_manager","try_unpause_strategy","try_withdraw","type_id","type_id","type_id","unpause_strategy","vzip","vzip","vzip","withdraw"],"q":[[0,"defindex_vault"],[168,"core::any"],[169,"defindex_vault::error"],[170,"core::cmp"],[171,"core::result"],[172,"alloc::rc"],[173,"alloc::boxed"],[174,"alloc::vec"],[175,"core::option"],[176,"soroban_sdk::vec"],[177,"soroban_sdk::address"],[178,"soroban_sdk::map"],[179,"core::fmt"],[180,"soroban_sdk::env"],[181,"soroban_sdk::bytes"],[182,"alloc::sync"],[183,"soroban_sdk::error"],[184,"soroban_env_common::error"],[185,"soroban_env_common::val"]],"i":[2,2,2,0,0,0,2,2,2,2,2,2,2,2,2,2,2,2,2,2,11,2,30,11,2,30,11,2,30,11,2,30,11,2,2,2,2,2,2,2,2,2,2,2,2,2,30,30,30,30,30,30,30,30,30,11,11,11,11,11,11,11,11,11,11,11,11,2,2,2,2,11,11,11,2,2,30,11,2,2,11,11,11,11,11,11,2,30,11,2,30,11,2,30,2,30,11,2,30,11,11,11,2,11,11,11,11,2,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,30,2,2,11,11,11,11,11,2,2,2,2,2,30,11,2,11,11,11,11,11,11,2,30,11,2,30,11,11,11,11,11,11,11,11,2,30,11,11,2,30,11,11],"f":"`````````````````````{cb{}}00000{ce{}{}}00000{dd}{{ce}f{}{}}{{dd}h}{{cee}{{j{h}}}{}{}}{{c{l{eg}}{l{eg}}}{{j{h}}}{}{}{}}{{c{l{egi}}{l{egi}}}{{j{h}}}{}{}{}{}}{{c{l{egik}}{l{egik}}}{{j{h}}}{}{}{}{}{}}{{c{n{e}}{n{e}}}{{j{h}}}{}{}}{{c{l{egikm}}{l{egikm}}}{{j{h}}}{}{}{}{}{}{}}{{ce}h{}{}}{{c{A`{e}}{A`{e}}}{{j{h}}}{}{}}{{c{Ab{e}}{Ab{e}}}{{j{h}}}{}{}}{{c{Ad{e}}{Ad{e}}}{{j{h}}}{}{}}054782196978601245{{Af{Aj{Ah}}{Aj{Ah}}Al}f}{{AfAlAl}f}`{{dd}An}{{ce}An{}{}}00{Af{{B`{AlAh}}}}00{{dBb}Bd}{cc{}}00{{ce}g{}{}{}}{{BfBh}{{j{c}}}{}}{{AfAh}{{B`{AlAh}}}}{Af{{Aj{`}}}}{AfAl}00{{Af{Aj{`}}AlAlAlBjAlAl}f}{ce{}{}}00{{{A`{c}}}{{A`{b}}}{}}00{{{Bl{c}}}{{Bl{b}}}{}}0{{{n{c}}}{{n{b}}}{}}00999{{Af{Aj{`}}}f}{{BfAl}Af}{{dd}{{Ad{h}}}}{{AfAlAl}f}{{AfAl}f}10{{}{{C`{Bn}}}}0000000000000000009{{cBf}Bh{}}{{Af{Aj{Ah}}{Aj{Ah}}Al}{{j{{j{f}}{j{dCb}}}}}}{{AfAlAl}{{j{{j{f}}{j{dCb}}}}}}{Af{{j{{j{{B`{AlAh}}}}{j{CdCb}}}}}}00{Cb{{j{dCb}}}}0{Cd{{j{dCd}}}}{c{{j{e}}}{}{}}100{{BfCf}{{j{dCh}}}}{{AfAh}{{j{{j{{B`{AlAh}}}}{j{CdCb}}}}}}{Af{{j{{j{{Aj{`}}}}{j{CdCb}}}}}}{Af{{j{{j{Al}}{j{dCb}}}}}}00{{Af{Aj{`}}AlAlAlBjAlAl}{{j{{j{f}}{j{dCb}}}}}}555{{ce}{{j{g}}}{}{}{}}00{{Af{Aj{`}}}{{j{{j{f}}{j{dCb}}}}}};{{AfAl}{{j{{j{f}}{j{CdCb}}}}}}{{AfAlAl}{{j{{j{f}}{j{CdCb}}}}}}1={{AfAhAl}{{j{{j{{Aj{Ah}}}}{j{dCb}}}}}}{cCj{}}00{{AfAlAl}f}{ce{}{}}00{{AfAhAl}{{Aj{Ah}}}}","D":"Gj","p":[[10,"Any",168],[6,"ContractError",0,169],[1,"unit"],[6,"Ordering",170],[6,"Result",171],[1,"tuple"],[5,"Rc",172],[5,"Box",173],[5,"Vec",174],[6,"Option",175],[5,"DeFindexVaultClient",0],[1,"i128"],[5,"Vec",176],[5,"Address",177],[1,"bool"],[5,"Map",178],[5,"Formatter",179],[8,"Result",179],[5,"Env",180],[5,"Bytes",181],[1,"u32"],[5,"Arc",182],[1,"u8"],[1,"array"],[6,"InvokeError",183],[5,"Error",184],[5,"Val",185],[5,"ConversionError",185],[5,"TypeId",168],[5,"DeFindexVault",0]],"r":[[3,169]],"b":[[133,"impl-TryFrom%3C%26InvokeError%3E-for-ContractError"],[134,"impl-TryFrom%3CInvokeError%3E-for-ContractError"],[135,"impl-TryFrom%3C%26Error%3E-for-ContractError"],[137,"impl-TryFrom%3CError%3E-for-ContractError"]],"c":"OjAAAAAAAAA=","e":"OzAAAAEAAGsADQAAAAUABwA5AEMABABLAAAATwABAFoACgBmAAEAbAAAAH8AAQCGAAcAlAAFAKEAAgClAAIA"}]\ -]')); +var searchIndex = new Map(JSON.parse('[["defindex_factory",{"t":"FKOMNNNNNNNNNNNNNNHMNMNMNMNMNONMNNNNNNMNMNMNNNNNNNNNNNNNNNN","n":["DeFindexFactoryClient","FactoryTrait","address","admin","","as_any","as_any_mut","borrow","borrow_mut","compare","","","","","","","","","create_contract","create_defindex_vault","","create_defindex_vault_deposit","","defindex_fee","","defindex_receiver","","deployed_defindexes","","env","from","initialize","","into","into_any","into_any_rc","into_val","new","set_defindex_fee","","set_defindex_receiver","","set_new_admin","","try_admin","try_create_defindex_vault","try_create_defindex_vault_deposit","try_defindex_fee","try_defindex_receiver","try_deployed_defindexes","try_from","try_initialize","try_into","try_into_val","try_set_defindex_fee","try_set_defindex_receiver","try_set_new_admin","type_id","vzip"],"q":[[0,"defindex_factory"],[59,"soroban_sdk::env"],[60,"soroban_sdk::address"],[61,"core::result"],[62,"core::any"],[63,"core::option"],[64,"core::cmp"],[65,"alloc::rc"],[66,"alloc::boxed"],[67,"alloc::vec"],[68,"soroban_sdk::bytes"],[69,"soroban_sdk::string"],[70,"common::models"],[71,"soroban_sdk::vec"],[72,"soroban_sdk::map"],[73,"soroban_sdk::error"],[74,"defindex_factory::vault"]],"i":"``hC`11111111111111`0101010101110111111010101111111111111111","f":"```{b{{f{d`}}}}{{{j{h}}}d}{j{{j{l}}}}{{{j{n}}}{{j{nl}}}}{j{{j{c}}}{}}{{{j{n}}}{{j{nc}}}{}}{{j{j{{A`{c}}}}{j{{A`{c}}}}}{{f{Ab}}}{}}{{j{j{{Ad{c}}}}{j{{Ad{c}}}}}{{f{Ab}}}{}}{{j{j{{Af{c}}}}{j{{Af{c}}}}}{{f{Ab}}}{}}{{j{j{{Ah{c}}}}{j{{Ah{c}}}}}{{f{Ab}}}{}}{{j{j{{Aj{cegik}}}}{j{{Aj{cegik}}}}}{{f{Ab}}}{}{}{}{}{}}{{j{j{{Aj{cegi}}}}{j{{Aj{cegi}}}}}{{f{Ab}}}{}{}{}{}}{{j{j{{Aj{ceg}}}}{j{{Aj{ceg}}}}}{{f{Ab}}}{}{}{}}{{j{j{{Aj{ce}}}}{j{{Aj{ce}}}}}{{f{Ab}}}{}{}}{{j{j{{j{c}}}}{j{{j{c}}}}}{{f{Ab}}}{}}{{{j{b}}AlAl}d}{{bddAnB`B`d{Bd{Bb}}Al}{{f{d`}}}}{{{j{h}}{j{d}}{j{d}}{j{An}}{j{B`}}{j{B`}}{j{d}}{j{{Bd{Bb}}}}{j{Al}}}d}{{bdddAnB`B`d{Bd{Bb}}{Bd{Bf}}Al}{{f{d`}}}}{{{j{h}}{j{d}}{j{d}}{j{d}}{j{An}}{j{B`}}{j{B`}}{j{d}}{j{{Bd{Bb}}}}{j{{Bd{Bf}}}}{j{Al}}}d}{b{{f{An`}}}}{{{j{h}}}An}{b{{f{d`}}}}{{{j{h}}}d}{b{{f{{Bh{And}}`}}}}{{{j{h}}}{{Bh{And}}}}`{cc{}}{{bddAnAl}{{f{Bj`}}}}{{{j{h}}{j{d}}{j{d}}{j{An}}{j{Al}}}Bj}{{}c{}}{{{Af{c}}}{{Af{l}}}{}}{{{Ad{c}}}{{Ad{l}}}{}}{{j{j{c}}}e{}{}}{{{j{b}}{j{d}}}h}{{bAn}{{f{Bj`}}}}{{{j{h}}{j{An}}}Bj}{{bd}{{f{Bj`}}}}{{{j{h}}{j{d}}}Bj}10{{{j{h}}}{{f{{f{d}}{f{`Bl}}}}}}{{{j{h}}{j{d}}{j{d}}{j{An}}{j{B`}}{j{B`}}{j{d}}{j{{Bd{Bb}}}}{j{Al}}}{{f{{f{d}}{f{`Bl}}}}}}{{{j{h}}{j{d}}{j{d}}{j{d}}{j{An}}{j{B`}}{j{B`}}{j{d}}{j{{Bd{Bb}}}}{j{{Bd{Bf}}}}{j{Al}}}{{f{{f{d}}{f{`Bl}}}}}}{{{j{h}}}{{f{{f{An}}{f{`Bl}}}}}}3{{{j{h}}}{{f{{f{{Bh{And}}}}{f{`Bl}}}}}}{c{{f{e}}}{}{}}{{{j{h}}{j{d}}{j{d}}{j{An}}{j{Al}}}{{f{{f{Bj}}{f{`Bl}}}}}}{{}{{f{c}}}{}}{{j{j{c}}}{{f{e}}}{}{}}{{{j{h}}{j{An}}}{{f{{f{Bj}}{f{`Bl}}}}}}{{{j{h}}{j{d}}}{{f{{f{Bj}}{f{`Bl}}}}}}0{jBn}{{}c{}}","D":"Db","p":[[5,"Env",59],[5,"Address",60],[6,"Result",61],[5,"DeFindexFactoryClient",0],[1,"reference"],[10,"Any",62],[0,"mut"],[6,"Option",63],[6,"Ordering",64],[5,"Rc",65],[5,"Box",66],[5,"Vec",67],[1,"tuple"],[5,"BytesN",68],[1,"u32"],[5,"String",69],[5,"AssetStrategySet",70],[5,"Vec",71],[1,"i128"],[5,"Map",72],[1,"unit"],[6,"InvokeError",73],[5,"TypeId",62],[10,"FactoryTrait",0]],"r":[[18,74]],"b":[],"c":"OjAAAAAAAAA=","e":"OzAAAAEAABoACAAAAAAAAgABAAYADQAeAAAAIwADADMAAAA1AAEAOgABAA=="}],["defindex_strategy_core",{"t":"PFKPPPPPPPFGONNNNNNMNMNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNMNONNNNCNNNNNNMNMNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNMNFFFFJJJJOOONNNNNNNNONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNHHHHNNNNNNNNNNNNNNNNNNNNNNNNOOONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN","n":["AlreadyInitialized","DeFindexStrategyClient","DeFindexStrategyTrait","DeadlineExpired","ExternalError","InsufficientBalance","InvalidArgument","NegativeNotAllowed","NotInitialized","ProtocolAddressNotFound","Spec","StrategyError","address","as_any","","","as_any_mut","","","asset","","balance","","borrow","","","borrow_mut","","","clone","clone_into","clone_to_uninit","cmp","compare","","","","","","","","","","","","","","","","","","","","","","","","","","","","deposit","","env","eq","equivalent","","","event","fmt","from","","","from_val","from_xdr","harvest","","initialize","","into","","","into_any","","","into_any_arc","","into_any_rc","","","into_val","","","new","partial_cmp","spec_xdr","spec_xdr_asset","spec_xdr_balance","spec_xdr_deposit","spec_xdr_harvest","spec_xdr_initialize","spec_xdr_withdraw","to_owned","to_xdr","try_asset","try_balance","try_deposit","try_from","","","","","","","try_from_val","try_harvest","try_initialize","try_into","","","try_into_val","","","try_withdraw","type_id","","","vzip","","","withdraw","","DepositEvent","HarvestEvent","InitializedEvent","WithdrawEvent","__SPEC_XDR_TYPE_DEPOSITEVENT","__SPEC_XDR_TYPE_HARVESTEVENT","__SPEC_XDR_TYPE_INITIALIZEDEVENT","__SPEC_XDR_TYPE_WITHDRAWEVENT","amount","","","as_any","","","","as_any_mut","","","","asset","borrow","","","","borrow_mut","","","","clone","","","","clone_into","","","","clone_to_uninit","","","","compare","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","","emit_deposit","emit_harvest","emit_initialize","emit_withdraw","eq","","","","equivalent","","","","","","","","","","","","fmt","","","","from","","","","","","","from_val","","","","from_xdr","","","","into","","","","into_any","","","","into_any_rc","","","","into_val","","","","spec_xdr","","","","to_owned","","","","to_xdr","","","","try_from","","","","try_from_val","","","","try_into","","","","try_into_val","","","","type_id","","","","vzip","","",""],"q":[[0,"defindex_strategy_core"],[132,"defindex_strategy_core::event"],[299,"core::any"],[300,"soroban_sdk::env"],[301,"soroban_sdk::address"],[302,"defindex_strategy_core::error"],[303,"core::result"],[304,"core::cmp"],[305,"core::option"],[306,"alloc::vec"],[307,"alloc::boxed"],[308,"alloc::rc"],[309,"core::fmt"],[310,"soroban_sdk::bytes"],[311,"soroban_env_common::val"],[312,"soroban_sdk::vec"],[313,"alloc::sync"],[314,"soroban_sdk::error"],[315,"soroban_env_common::error"],[316,"soroban_sdk::string"]],"i":"l``0000000``A`Df21021Dh202132132333311111111133333333332222222220223333`313233020213213213132132233111111332221333332322132132213213202````````CnD`DbCl3210321003210321032103210321000000000333333333222222222111111111````032100033322211103210321321032103210321032103210321032103210321032103210321032103210321","f":"`````````````{b{{b{d}}}}00{{{b{f}}}{{b{fd}}}}00{h{{n{jl}}}}{{{b{A`}}}j}{{hj}{{n{Abl}}}}{{{b{A`}}{b{j}}}Ab}{b{{b{c}}}{}}00{{{b{f}}}{{b{fc}}}{}}00{{{b{l}}}l}{{b{b{fc}}}Ad{}}{bAd}{{{b{l}}{b{l}}}Af}{{b{b{{Ah{cegi}}}}{b{{Ah{cegi}}}}}{{n{Af}}}{}{}{}{}}{{b{b{{Aj{c}}}}{b{{Aj{c}}}}}{{n{Af}}}{}}{{b{b{{Ah{cegik}}}}{b{{Ah{cegik}}}}}{{n{Af}}}{}{}{}{}{}}{{b{b{{Ah{ceg}}}}{b{{Ah{ceg}}}}}{{n{Af}}}{}{}{}}{{b{b{{Al{c}}}}{b{{Al{c}}}}}{{n{Af}}}{}}{{b{b{{Ah{ce}}}}{b{{Ah{ce}}}}}{{n{Af}}}{}{}}{{b{b{{An{c}}}}{b{{An{c}}}}}{{n{Af}}}{}}{{b{b{{B`{c}}}}{b{{B`{c}}}}}{{n{Af}}}{}}{{b{b{{b{c}}}}{b{{b{c}}}}}{{n{Af}}}{}}5306417{{b{b{c}}}Af{}}39512379648{{hAbj}{{n{Adl}}}}{{{b{A`}}{b{Ab}}{b{j}}}Ad}`{{{b{l}}{b{l}}}Bb}{{b{b{c}}}Bb{}}00`{{{b{l}}{b{fBd}}}Bf}{cc{}}00{{{b{c}}{b{e}}}g{}{}{}}{{{b{h}}{b{Bh}}}{{n{c}}}{}}{{hj}{{n{Adl}}}}{{{b{A`}}{b{j}}}Ad}{{hj{Bl{Bj}}}{{n{Adl}}}}{{{b{A`}}{b{j}}{b{{Bl{Bj}}}}}Ad}{{}c{}}00{{{An{c}}}{{An{d}}}{}}00{{{Bn{c}}}{{Bn{d}}}{}}0{{{B`{c}}}{{B`{d}}}{}}00{{b{b{c}}}e{}{}}00{{{b{h}}{b{j}}}A`}{{{b{l}}{b{l}}}{{Aj{Af}}}}{{}{{Cb{C`}}}}000000{bc{}}{{{b{h}}}Bh}{{{b{A`}}}{{n{{n{j}}{n{lCd}}}}}}{{{b{A`}}{b{j}}}{{n{{n{Ab}}{n{lCd}}}}}}{{{b{A`}}{b{Ab}}{b{j}}}{{n{{n{Ad}}{n{lCd}}}}}}{c{{n{e}}}{}{}}{{{b{Cd}}}{{n{lCd}}}}{Cd{{n{lCd}}}}{{{b{Cf}}}{{n{lCf}}}}{Cf{{n{lCf}}}}44{{{b{h}}{b{Bj}}}{{n{lCh}}}}{{{b{A`}}{b{j}}}{{n{{n{Ad}}{n{lCd}}}}}}{{{b{A`}}{b{j}}{b{{Bl{Bj}}}}}{{n{{n{Ad}}{n{lCd}}}}}}{{}{{n{c}}}{}}00{{b{b{c}}}{{n{e}}}{}{}}00{{{b{A`}}{b{Ab}}{b{j}}}{{n{{n{Ab}}{n{lCd}}}}}}{bCj}00{{}c{}}00{{hAbj}{{n{Abl}}}}{{{b{A`}}{b{Ab}}{b{j}}}Ab}```````````{b{{b{d}}}}000{{{b{f}}}{{b{fd}}}}000`{b{{b{c}}}{}}000{{{b{f}}}{{b{fc}}}{}}000{{{b{Cl}}}Cl}{{{b{Cn}}}Cn}{{{b{D`}}}D`}{{{b{Db}}}Db}{{b{b{fc}}}Ad{}}000{bAd}000{{b{b{{b{c}}}}{b{{b{c}}}}}{{n{Af}}}{}}{{b{b{{Ah{cegi}}}}{b{{Ah{cegi}}}}}{{n{Af}}}{}{}{}{}}{{b{b{{Aj{c}}}}{b{{Aj{c}}}}}{{n{Af}}}{}}{{b{b{{B`{c}}}}{b{{B`{c}}}}}{{n{Af}}}{}}{{b{b{{An{c}}}}{b{{An{c}}}}}{{n{Af}}}{}}{{b{b{{Al{c}}}}{b{{Al{c}}}}}{{n{Af}}}{}}{{b{b{{Ah{ce}}}}{b{{Ah{ce}}}}}{{n{Af}}}{}{}}{{b{b{{Ah{cegik}}}}{b{{Ah{cegik}}}}}{{n{Af}}}{}{}{}{}{}}{{b{b{{Ah{ceg}}}}{b{{Ah{ceg}}}}}{{n{Af}}}{}{}{}}865431702268543170854317026{{{b{h}}DdAbj}Ad}0{{{b{h}}Ddj}Ad}1{{{b{Cl}}{b{Cl}}}Bb}{{{b{Cn}}{b{Cn}}}Bb}{{{b{D`}}{b{D`}}}Bb}{{{b{Db}}{b{Db}}}Bb}{{b{b{c}}}Bb{}}00000000000{{{b{Cl}}{b{fBd}}}Bf}{{{b{Cn}}{b{fBd}}}Bf}{{{b{D`}}{b{fBd}}}Bf}{{{b{Db}}{b{fBd}}}Bf}{cc{}}000```{{{b{c}}{b{e}}}g{}{}{}}000{{{b{h}}{b{Bh}}}{{n{c}}}{}}000{{}c{}}000{{{An{c}}}{{An{d}}}{}}000{{{B`{c}}}{{B`{d}}}{}}000{{b{b{c}}}e{}{}}000{{}{{Cb{C`}}}}000{bc{}}000{{{b{h}}}Bh}000{c{{n{e}}}{}{}}000{{{b{h}}{b{Bj}}}{{n{ClCh}}}}{{{b{h}}{b{Bj}}}{{n{CnCh}}}}{{{b{h}}{b{Bj}}}{{n{D`Ch}}}}{{{b{h}}{b{Bj}}}{{n{DbCh}}}}{{}{{n{c}}}{}}000{{b{b{c}}}{{n{e}}}{}{}}000{bCj}000>>>>","D":"Ej","p":[[1,"reference"],[10,"Any",299],[0,"mut"],[5,"Env",300],[5,"Address",301],[6,"StrategyError",0,302],[6,"Result",303],[5,"DeFindexStrategyClient",0],[1,"i128"],[1,"unit"],[6,"Ordering",304],[1,"tuple"],[6,"Option",305],[5,"Vec",306],[5,"Box",307],[5,"Rc",308],[1,"bool"],[5,"Formatter",309],[8,"Result",309],[5,"Bytes",310],[5,"Val",311],[5,"Vec",312],[5,"Arc",313],[1,"u8"],[1,"array"],[6,"InvokeError",314],[5,"Error",315],[5,"ConversionError",311],[5,"TypeId",299],[5,"InitializedEvent",132],[5,"DepositEvent",132],[5,"HarvestEvent",132],[5,"WithdrawEvent",132],[5,"String",316],[5,"Spec",0],[10,"DeFindexStrategyTrait",0]],"r":[[11,302]],"b":[[108,"impl-TryFrom%3C%26InvokeError%3E-for-StrategyError"],[109,"impl-TryFrom%3CInvokeError%3E-for-StrategyError"],[110,"impl-TryFrom%3C%26Error%3E-for-StrategyError"],[111,"impl-TryFrom%3CError%3E-for-StrategyError"]],"c":"OjAAAAAAAAA=","e":"OzAAAAEAAP4ADwAAAAEABAAPABgAJQBAAAQARgAAAEoAAQBTAA0AZwABAGwABwB2AAUAfQAFAIUASwDVABMA7QAKAPwALwA="}],["defindex_vault",{"t":"PPPPGFFPPPPPPPPPPPPPPPPPPPPPPPPPPONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNONNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN","n":["AlreadyInitialized","AmountOverTotalSupply","ArithmeticError","AssetNotFound","ContractError","DeFindexVault","DeFindexVaultClient","InsufficientAmount","InsufficientBalance","InsufficientManagedFunds","InvalidRatio","MissingInstructionData","NegativeNotAllowed","NoAssetAllocation","NoAssetsProvided","NoInstructions","NoOptimalAmounts","NotEnoughIdleFunds","NotInitialized","Overflow","RoleNotFound","StrategyDoesNotSupportAsset","StrategyInvestError","StrategyNotFound","StrategyPaused","StrategyPausedOrNotFound","StrategyWithdrawError","Unauthorized","UnsupportedAsset","WrongAmountsLength","WrongAssetAddress","WrongInvestmentLength","WrongStrategiesLength","address","as_any","","","as_any_mut","","","borrow","","","borrow_mut","","","clone","clone_into","clone_to_uninit","cmp","collect_fees","compare","","","","","","","","","","","","","","","","","","","","","","","","","","","","deposit","emergency_withdraw","env","eq","equivalent","","","fetch_current_idle_funds","fetch_current_invested_funds","fetch_total_managed_funds","fmt","from","","","from_val","from_xdr","get_asset_amounts_per_shares","get_assets","get_emergency_manager","get_fee_receiver","get_fees","get_manager","initialize","into","","","into_any","","","into_any_arc","","into_any_rc","","","into_val","","","invest","new","partial_cmp","pause_strategy","rebalance","set_emergency_manager","set_fee_receiver","set_manager","spec_xdr","spec_xdr_collect_fees","spec_xdr_deposit","spec_xdr_emergency_withdraw","spec_xdr_fetch_current_idle_funds","spec_xdr_fetch_current_invested_funds","spec_xdr_fetch_total_managed_funds","spec_xdr_get_asset_amounts_per_shares","spec_xdr_get_assets","spec_xdr_get_emergency_manager","spec_xdr_get_fee_receiver","spec_xdr_get_fees","spec_xdr_get_manager","spec_xdr_initialize","spec_xdr_invest","spec_xdr_pause_strategy","spec_xdr_rebalance","spec_xdr_set_emergency_manager","spec_xdr_set_fee_receiver","spec_xdr_set_manager","spec_xdr_unpause_strategy","spec_xdr_withdraw","to_owned","to_xdr","try_collect_fees","try_deposit","try_emergency_withdraw","try_fetch_current_idle_funds","try_fetch_current_invested_funds","try_fetch_total_managed_funds","try_from","","","","","","","try_from_val","try_get_asset_amounts_per_shares","try_get_assets","try_get_emergency_manager","try_get_fee_receiver","try_get_fees","try_get_manager","try_initialize","try_into","","","try_into_val","","","try_invest","try_pause_strategy","try_rebalance","try_set_emergency_manager","try_set_fee_receiver","try_set_manager","try_unpause_strategy","try_withdraw","type_id","","","unpause_strategy","vzip","","","withdraw"],"q":[[0,"defindex_vault"],[191,"core::any"],[192,"defindex_vault::error"],[193,"core::cmp"],[194,"core::result"],[195,"core::option"],[196,"alloc::rc"],[197,"alloc::boxed"],[198,"alloc::vec"],[199,"soroban_sdk::vec"],[200,"soroban_sdk::address"],[201,"soroban_sdk::map"],[202,"core::fmt"],[203,"soroban_sdk::env"],[204,"soroban_sdk::bytes"],[205,"common::models"],[206,"soroban_sdk::string"],[207,"alloc::sync"],[208,"soroban_sdk::error"],[209,"soroban_env_common::error"],[210,"soroban_env_common::val"]],"i":"h000```00000000000000000000000000n1Dd12012012012222122222222220000000001111111111112222111220122111111120120120201201112111112000000000000000000000221111112222201211111112012011111111120112011","f":"``````````````````````````````````{b{{b{d}}}}00{{{b{f}}}{{b{fd}}}}00{b{{b{c}}}{}}00{{{b{f}}}{{b{fc}}}{}}00{{{b{h}}}h}{{b{b{fc}}}j{}}{bj}{{{b{h}}{b{h}}}l}{{{b{n}}}j}{{b{b{{A`{ce}}}}{b{{A`{ce}}}}}{{Ab{l}}}{}{}}{{b{b{{b{c}}}}{b{{b{c}}}}}{{Ab{l}}}{}}{{b{b{{Ad{c}}}}{b{{Ad{c}}}}}{{Ab{l}}}{}}{{b{b{c}}}l{}}{{b{b{{Af{c}}}}{b{{Af{c}}}}}{{Ab{l}}}{}}{{b{b{{Ah{c}}}}{b{{Ah{c}}}}}{{Ab{l}}}{}}{{b{b{{Aj{c}}}}{b{{Aj{c}}}}}{{Ab{l}}}{}}{{b{b{{A`{cegik}}}}{b{{A`{cegik}}}}}{{Ab{l}}}{}{}{}{}{}}{{b{b{{A`{cegi}}}}{b{{A`{cegi}}}}}{{Ab{l}}}{}{}{}{}}{{b{b{{A`{ceg}}}}{b{{A`{ceg}}}}}{{Ab{l}}}{}{}{}}087951234897543210{{{b{n}}{b{{An{Al}}}}{b{{An{Al}}}}{b{B`}}{b{Bb}}}{{A`{{An{Al}}Al}}}}{{{b{n}}{b{B`}}{b{B`}}}j}`{{{b{h}}{b{h}}}Bb}{{b{b{c}}}Bb{}}00{{{b{n}}}{{Bd{B`Al}}}}0{{{b{n}}}{{Bd{B``}}}}{{{b{h}}{b{fBf}}}Bh}{cc{}}00{{{b{c}}{b{e}}}g{}{}{}}{{{b{Bj}}{b{Bl}}}{{Ab{c}}}{}}{{{b{n}}{b{Al}}}{{Bd{B`Al}}}}{{{b{n}}}{{An{Bn}}}}{{{b{n}}}B`}0{{{b{n}}}{{A`{C`C`}}}}1{{{b{n}}{b{{An{Bn}}}}{b{B`}}{b{B`}}{b{B`}}{b{C`}}{b{B`}}{b{B`}}{b{Cb}}{b{Cb}}}j}{{}c{}}00{{{Ah{c}}}{{Ah{d}}}{}}00{{{Cd{c}}}{{Cd{d}}}{}}0{{{Af{c}}}{{Af{d}}}{}}00{{b{b{c}}}e{}{}}00{{{b{n}}{b{{An{{Ad{`}}}}}}}j}{{{b{Bj}}{b{B`}}}n}{{{b{h}}{b{h}}}{{Ad{l}}}}{{{b{n}}{b{B`}}{b{B`}}}j}{{{b{n}}{b{{An{`}}}}}j}{{{b{n}}{b{B`}}}j}20{{}{{Ch{Cf}}}}000000000000000000000{bc{}}{{{b{Bj}}}Bl}{{{b{n}}}{{Ab{{Ab{j}}{Ab{hCj}}}}}}{{{b{n}}{b{{An{Al}}}}{b{{An{Al}}}}{b{B`}}{b{Bb}}}{{Ab{{Ab{{A`{{An{Al}}Al}}}}{Ab{hCj}}}}}}{{{b{n}}{b{B`}}{b{B`}}}{{Ab{{Ab{j}}{Ab{hCj}}}}}}{{{b{n}}}{{Ab{{Ab{{Bd{B`Al}}}}{Ab{ClCj}}}}}}0{{{b{n}}}{{Ab{{Ab{{Bd{B``}}}}{Ab{ClCj}}}}}}{{{b{Cl}}}{{Ab{hCl}}}}{{{b{Cj}}}{{Ab{hCj}}}}{c{{Ab{e}}}{}{}}{Cl{{Ab{hCl}}}}{Cj{{Ab{hCj}}}}22{{{b{Bj}}{b{Cn}}}{{Ab{hD`}}}}{{{b{n}}{b{Al}}}{{Ab{{Ab{{Bd{B`Al}}}}{Ab{hCj}}}}}}{{{b{n}}}{{Ab{{Ab{{An{Bn}}}}{Ab{ClCj}}}}}}{{{b{n}}}{{Ab{{Ab{B`}}{Ab{hCj}}}}}}0{{{b{n}}}{{Ab{{Ab{{A`{C`C`}}}}{Ab{ClCj}}}}}}1{{{b{n}}{b{{An{Bn}}}}{b{B`}}{b{B`}}{b{B`}}{b{C`}}{b{B`}}{b{B`}}{b{Cb}}{b{Cb}}}{{Ab{{Ab{j}}{Ab{hCj}}}}}}{{}{{Ab{c}}}{}}00{{b{b{c}}}{{Ab{e}}}{}{}}00{{{b{n}}{b{{An{{Ad{`}}}}}}}{{Ab{{Ab{j}}{Ab{hCj}}}}}}{{{b{n}}{b{B`}}{b{B`}}}{{Ab{{Ab{j}}{Ab{hCj}}}}}}{{{b{n}}{b{{An{`}}}}}{{Ab{{Ab{j}}{Ab{hCj}}}}}}{{{b{n}}{b{B`}}}{{Ab{{Ab{j}}{Ab{ClCj}}}}}}{{{b{n}}{b{B`}}{b{B`}}}{{Ab{{Ab{j}}{Ab{ClCj}}}}}}13{{{b{n}}{b{Al}}{b{B`}}}{{Ab{{Ab{{An{Al}}}}{Ab{hCj}}}}}}{bDb}00{{{b{n}}{b{B`}}{b{B`}}}j}{{}c{}}00{{{b{n}}{b{Al}}{b{B`}}}{{An{Al}}}}","D":"H`","p":[[1,"reference"],[10,"Any",191],[0,"mut"],[6,"ContractError",0,192],[1,"unit"],[6,"Ordering",193],[5,"DeFindexVaultClient",0],[1,"tuple"],[6,"Result",194],[6,"Option",195],[5,"Rc",196],[5,"Box",197],[5,"Vec",198],[1,"i128"],[5,"Vec",199],[5,"Address",200],[1,"bool"],[5,"Map",201],[5,"Formatter",202],[8,"Result",202],[5,"Env",203],[5,"Bytes",204],[5,"AssetStrategySet",205],[1,"u32"],[5,"String",206],[5,"Arc",207],[1,"u8"],[1,"array"],[6,"InvokeError",208],[5,"Error",209],[5,"Val",210],[5,"ConversionError",210],[5,"TypeId",191],[5,"DeFindexVault",0]],"r":[[4,192]],"b":[[154,"impl-TryFrom%3C%26Error%3E-for-ContractError"],[155,"impl-TryFrom%3C%26InvokeError%3E-for-ContractError"],[157,"impl-TryFrom%3CError%3E-for-ContractError"],[158,"impl-TryFrom%3CInvokeError%3E-for-ContractError"]],"c":"OjAAAAAAAAA=","e":"OzAAAAEAAH8AEAAAAAYACABHAFIABABaAAAAXgABAGQAAABqAAoAdgABAH0AAQCIAAAAkwACAJsABwCnAAAAqgAFALgAAgC8AAIA"}]]')); if (typeof exports !== 'undefined') exports.searchIndex = searchIndex; else if (window.initSearch) window.initSearch(searchIndex); +//{"start":39,"fragment_lengths":[3322,6881,6858]} \ No newline at end of file diff --git a/apps/rust_docs/search.desc/defindex_factory/defindex_factory-desc-0-.js b/apps/rust_docs/search.desc/defindex_factory/defindex_factory-desc-0-.js index 596a59cb..2edc6ea0 100644 --- a/apps/rust_docs/search.desc/defindex_factory/defindex_factory-desc-0-.js +++ b/apps/rust_docs/search.desc/defindex_factory/defindex_factory-desc-0-.js @@ -1 +1 @@ -searchState.loadedDescShard("defindex_factory", 0, "DeFindexFactoryClient is a client for calling the contract …\nRetrieves the current admin’s address.\nRetrieves the current admin’s address.\nCreates a new DeFindex Vault with specified parameters.\nCreates a new DeFindex Vault with specified parameters.\nRetrieves the current DeFindex receiver’s address.\nRetrieves the current DeFindex receiver’s address.\nRetrieves a map of all deployed DeFindex vaults.\nRetrieves a map of all deployed DeFindex vaults.\nRetrieves the current fee rate.\nRetrieves the current fee rate.\nReturns the argument unchanged.\nInitializes the factory contract with the given parameters.\nInitializes the factory contract with the given parameters.\nCalls U::from(self).\nUpdates the default receiver address for the DeFindex …\nUpdates the default receiver address for the DeFindex …\nUpdates the default fee rate for new vaults.\nUpdates the default fee rate for new vaults.\nSets a new admin address.\nSets a new admin address.\nRetrieves the current admin’s address.\nCreates a new DeFindex Vault with specified parameters.\nRetrieves the current DeFindex receiver’s address.\nRetrieves a map of all deployed DeFindex vaults.\nRetrieves the current fee rate.\nInitializes the factory contract with the given parameters.\nUpdates the default receiver address for the DeFindex …\nUpdates the default fee rate for new vaults.\nSets a new admin address.") \ No newline at end of file +searchState.loadedDescShard("defindex_factory", 0, "DeFindexFactoryClient is a client for calling the contract …\nRetrieves the current admin’s address.\nRetrieves the current admin’s address.\nCreates a new DeFindex Vault with specified parameters.\nCreates a new DeFindex Vault with specified parameters.\nCreates a new DeFindex Vault with specified parameters and …\nCreates a new DeFindex Vault with specified parameters and …\nRetrieves the current fee rate.\nRetrieves the current fee rate.\nRetrieves the current DeFindex receiver’s address.\nRetrieves the current DeFindex receiver’s address.\nRetrieves a map of all deployed DeFindex vaults.\nRetrieves a map of all deployed DeFindex vaults.\nReturns the argument unchanged.\nInitializes the factory contract with the given parameters.\nInitializes the factory contract with the given parameters.\nCalls U::from(self).\nUpdates the default fee rate for new vaults.\nUpdates the default fee rate for new vaults.\nUpdates the default receiver address for the DeFindex …\nUpdates the default receiver address for the DeFindex …\nSets a new admin address.\nSets a new admin address.\nRetrieves the current admin’s address.\nCreates a new DeFindex Vault with specified parameters.\nCreates a new DeFindex Vault with specified parameters and …\nRetrieves the current fee rate.\nRetrieves the current DeFindex receiver’s address.\nRetrieves a map of all deployed DeFindex vaults.\nInitializes the factory contract with the given parameters.\nUpdates the default fee rate for new vaults.\nUpdates the default receiver address for the DeFindex …\nSets a new admin address.") \ No newline at end of file diff --git a/apps/rust_docs/search.desc/defindex_vault/defindex_vault-desc-0-.js b/apps/rust_docs/search.desc/defindex_vault/defindex_vault-desc-0-.js index 1f2ede1d..6f60559a 100644 --- a/apps/rust_docs/search.desc/defindex_vault/defindex_vault-desc-0-.js +++ b/apps/rust_docs/search.desc/defindex_vault/defindex_vault-desc-0-.js @@ -1 +1 @@ -searchState.loadedDescShard("defindex_vault", 0, "DeFindexVaultClient is a client for calling the contract …\nHandles deposits into the DeFindex Vault.\nExecutes an emergency withdrawal from a specific strategy.\nReturns the current idle funds, representing the total …\nReturns the current invested funds, representing the total …\nReturns the total managed funds of the vault, including …\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nTemporary method for testing purposes.\nRetrieves the list of assets managed by the DeFindex Vault.\nRetrieves the current emergency manager address for the …\nRetrieves the current fee receiver address for the vault.\nRetrieves the current manager address for the vault.\nInitializes the DeFindex Vault contract with the required …\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nInvests the vault’s idle funds into the specified …\nPauses a strategy to prevent it from being used in the …\nSets the emergency manager for the vault.\nSets the fee receiver for the vault.\nSets the manager for the vault.\nHandles deposits into the DeFindex Vault.\nExecutes an emergency withdrawal from a specific strategy.\nReturns the current idle funds, representing the total …\nReturns the current invested funds, representing the total …\nReturns the total managed funds of the vault, including …\nTemporary method for testing purposes.\nRetrieves the list of assets managed by the DeFindex Vault.\nRetrieves the current emergency manager address for the …\nRetrieves the current fee receiver address for the vault.\nRetrieves the current manager address for the vault.\nInitializes the DeFindex Vault contract with the required …\nInvests the vault’s idle funds into the specified …\nPauses a strategy to prevent it from being used in the …\nSets the emergency manager for the vault.\nSets the fee receiver for the vault.\nSets the manager for the vault.\nUnpauses a previously paused strategy.\nWithdraws assets from the DeFindex Vault by burning …\nHandles deposits into the DeFindex Vault.\nExecutes an emergency withdrawal from a specific strategy.\nReturns the current idle funds, representing the total …\nReturns the current invested funds, representing the total …\nReturns the total managed funds of the vault, including …\nTemporary method for testing purposes.\nRetrieves the list of assets managed by the DeFindex Vault.\nRetrieves the current emergency manager address for the …\nRetrieves the current fee receiver address for the vault.\nRetrieves the current manager address for the vault.\nInitializes the DeFindex Vault contract with the required …\nInvests the vault’s idle funds into the specified …\nPauses a strategy to prevent it from being used in the …\nSets the emergency manager for the vault.\nSets the fee receiver for the vault.\nSets the manager for the vault.\nUnpauses a previously paused strategy.\nWithdraws assets from the DeFindex Vault by burning …\nUnpauses a previously paused strategy.\nWithdraws assets from the DeFindex Vault by burning …") \ No newline at end of file +searchState.loadedDescShard("defindex_vault", 0, "DeFindexVaultClient is a client for calling the contract …\nHandles user deposits into the DeFindex Vault.\nExecutes an emergency withdrawal from a specific strategy.\nReturns the current idle funds, representing the total …\nReturns the current invested funds, representing the total …\nReturns the total managed funds of the vault, including …\nReturns the argument unchanged.\nReturns the argument unchanged.\nReturns the argument unchanged.\nThis function extends the contract’s time-to-live and …\nRetrieves the list of assets managed by the DeFindex Vault.\nRetrieves the current emergency manager address for the …\nRetrieves the current fee receiver address for the vault.\nRetrieves the current manager address for the vault.\nInitializes the DeFindex Vault contract with the required …\nCalls U::from(self).\nCalls U::from(self).\nCalls U::from(self).\nExecutes the investment of the vault’s idle funds based …\nPauses a strategy to prevent it from being used in the …\nRebalances the vault by executing a series of instructions.\nSets the emergency manager for the vault.\nSets the fee receiver for the vault.\nSets the manager for the vault.\nHandles user deposits into the DeFindex Vault.\nExecutes an emergency withdrawal from a specific strategy.\nReturns the current idle funds, representing the total …\nReturns the current invested funds, representing the total …\nReturns the total managed funds of the vault, including …\nThis function extends the contract’s time-to-live and …\nRetrieves the list of assets managed by the DeFindex Vault.\nRetrieves the current emergency manager address for the …\nRetrieves the current fee receiver address for the vault.\nRetrieves the current manager address for the vault.\nInitializes the DeFindex Vault contract with the required …\nExecutes the investment of the vault’s idle funds based …\nPauses a strategy to prevent it from being used in the …\nRebalances the vault by executing a series of instructions.\nSets the emergency manager for the vault.\nSets the fee receiver for the vault.\nSets the manager for the vault.\nUnpauses a previously paused strategy.\nWithdraws assets from the DeFindex Vault by burning Vault …\nHandles user deposits into the DeFindex Vault.\nExecutes an emergency withdrawal from a specific strategy.\nReturns the current idle funds, representing the total …\nReturns the current invested funds, representing the total …\nReturns the total managed funds of the vault, including …\nThis function extends the contract’s time-to-live and …\nRetrieves the list of assets managed by the DeFindex Vault.\nRetrieves the current emergency manager address for the …\nRetrieves the current fee receiver address for the vault.\nRetrieves the current manager address for the vault.\nInitializes the DeFindex Vault contract with the required …\nExecutes the investment of the vault’s idle funds based …\nPauses a strategy to prevent it from being used in the …\nRebalances the vault by executing a series of instructions.\nSets the emergency manager for the vault.\nSets the fee receiver for the vault.\nSets the manager for the vault.\nUnpauses a previously paused strategy.\nWithdraws assets from the DeFindex Vault by burning Vault …\nUnpauses a previously paused strategy.\nWithdraws assets from the DeFindex Vault by burning Vault …") \ No newline at end of file diff --git a/apps/rust_docs/settings.html b/apps/rust_docs/settings.html index d0321248..75feabc3 100644 --- a/apps/rust_docs/settings.html +++ b/apps/rust_docs/settings.html @@ -1 +1 @@ -Settings

    Rustdoc settings

    Back
    \ No newline at end of file +Settings

    Rustdoc settings

    Back
    \ No newline at end of file diff --git a/apps/rust_docs/src-files.js b/apps/rust_docs/src-files.js index b1e942f9..6c0d4cdc 100644 --- a/apps/rust_docs/src-files.js +++ b/apps/rust_docs/src-files.js @@ -1,6 +1,3 @@ -var srcIndex = new Map(JSON.parse('[\ -["defindex_factory",["",[],["defindex.rs","error.rs","events.rs","lib.rs","storage.rs"]]],\ -["defindex_strategy_core",["",[],["error.rs","event.rs","lib.rs"]]],\ -["defindex_vault",["",[["token",[],["allowance.rs","balance.rs","contract.rs","metadata.rs","mod.rs","storage_types.rs","total_supply.rs"]]],["access.rs","constants.rs","error.rs","events.rs","fee.rs","funds.rs","interface.rs","investment.rs","lib.rs","models.rs","storage.rs","strategies.rs","utils.rs"]]]\ -]')); +var srcIndex = new Map(JSON.parse('[["defindex_factory",["",[],["error.rs","events.rs","lib.rs","storage.rs","vault.rs"]]],["defindex_strategy_core",["",[],["error.rs","event.rs","lib.rs"]]],["defindex_vault",["",[["token",[],["allowance.rs","balance.rs","contract.rs","metadata.rs","mod.rs","storage_types.rs","total_supply.rs"]]],["access.rs","aggregator.rs","constants.rs","deposit.rs","error.rs","events.rs","fee.rs","funds.rs","interface.rs","investment.rs","lib.rs","models.rs","storage.rs","strategies.rs","utils.rs"]]]]')); createSrcSidebar(); +//{"start":36,"fragment_lengths":[86,68,336]} \ No newline at end of file diff --git a/apps/rust_docs/src/defindex_factory/error.rs.html b/apps/rust_docs/src/defindex_factory/error.rs.html index 7ad16ad1..f0bcdb46 100644 --- a/apps/rust_docs/src/defindex_factory/error.rs.html +++ b/apps/rust_docs/src/defindex_factory/error.rs.html @@ -1,4 +1,4 @@ -error.rs - source
    1
    +error.rs - source
    1
     2
     3
     4
    @@ -8,6 +8,7 @@
     8
     9
     10
    +11
     
    use soroban_sdk::{self, contracterror};
     
     #[contracterror]
    @@ -17,5 +18,6 @@
         NotInitialized = 401,
         AlreadyInitialized = 402,
         EmptyMap = 403,
    +    AssetLengthMismatch = 404,
     }
     
    \ No newline at end of file diff --git a/apps/rust_docs/src/defindex_factory/events.rs.html b/apps/rust_docs/src/defindex_factory/events.rs.html index 7221f9bb..d7e453ac 100644 --- a/apps/rust_docs/src/defindex_factory/events.rs.html +++ b/apps/rust_docs/src/defindex_factory/events.rs.html @@ -1,4 +1,4 @@ -events.rs - source
    1
    +events.rs - source
    1
     2
     3
     4
    @@ -95,8 +95,8 @@
     95
     96
     
    //! Definition of the Events used in the contract
    -use soroban_sdk::{contracttype, symbol_short, Address, Env, Vec};
    -use crate::defindex::AssetAllocation;
    +use common::models::AssetStrategySet;
    +use soroban_sdk::{contracttype, symbol_short, Address, Env, Vec};
     
     // INITIALIZED
     #[contracttype]
    @@ -104,14 +104,14 @@
     pub struct InitializedEvent {
         pub admin: Address,
         pub defindex_receiver: Address,
    -    pub fee_rate: u32,
    +    pub defindex_fee: u32,
     }
     
    -pub(crate) fn emit_initialized(e: &Env, admin: Address, defindex_receiver: Address, fee_rate: u32) {
    +pub(crate) fn emit_initialized(e: &Env, admin: Address, defindex_receiver: Address, defindex_fee: u32) {
         let event: InitializedEvent = InitializedEvent {
             admin,
             defindex_receiver,
    -        fee_rate,
    +        defindex_fee,
         };
         e.events()
             .publish(("DeFindexFactory", symbol_short!("init")), event);
    @@ -124,8 +124,8 @@
         pub emergency_manager: Address, 
         pub fee_receiver: Address, 
         pub manager: Address,
    -    pub vault_share: u32,
    -    pub assets: Vec<AssetAllocation>
    +    pub vault_fee: u32,
    +    pub assets: Vec<AssetStrategySet>
     }
     
     /// Publishes an `CreateDeFindexEvent` to the event stream.
    @@ -134,14 +134,14 @@
         emergency_manager: Address, 
         fee_receiver: Address, 
         manager: Address,
    -    vault_share: u32,
    -    assets: Vec<AssetAllocation>,
    +    vault_fee: u32,
    +    assets: Vec<AssetStrategySet>,
     ) {
         let event = CreateDeFindexEvent { 
           emergency_manager,
           fee_receiver,
           manager,
    -      vault_share,
    +      vault_fee,
           assets,
         };
     
    @@ -177,16 +177,16 @@
             .publish(("DeFindexFactory", symbol_short!("nreceiver")), event);
     }
     
    -// NEW FEE RATE EVENT
    +// NEW DEFINDEX FEE EVENT
     #[contracttype]
     #[derive(Clone, Debug, Eq, PartialEq)]
     pub struct NewFeeRateEvent {
    -    pub new_fee_rate: u32,
    +    pub new_defindex_fee: u32,
     }
     
    -pub(crate) fn emit_new_fee_rate(e: &Env, new_fee_rate: u32) {
    -    let event = NewFeeRateEvent { new_fee_rate };
    +pub(crate) fn emit_new_defindex_fee(e: &Env, new_defindex_fee: u32) {
    +    let event = NewFeeRateEvent { new_defindex_fee };
     
         e.events()
    -        .publish(("DeFindexFactory", symbol_short!("nfee_rate")), event);
    +        .publish(("DeFindexFactory", symbol_short!("n_fee")), event);
     }
    \ No newline at end of file diff --git a/apps/rust_docs/src/defindex_factory/lib.rs.html b/apps/rust_docs/src/defindex_factory/lib.rs.html index cc49220c..a6367c7b 100644 --- a/apps/rust_docs/src/defindex_factory/lib.rs.html +++ b/apps/rust_docs/src/defindex_factory/lib.rs.html @@ -1,4 +1,4 @@ -lib.rs - source
    1
    +lib.rs - source
    1
     2
     3
     4
    @@ -332,19 +332,134 @@
     332
     333
     334
    +335
    +336
    +337
    +338
    +339
    +340
    +341
    +342
    +343
    +344
    +345
    +346
    +347
    +348
    +349
    +350
    +351
    +352
    +353
    +354
    +355
    +356
    +357
    +358
    +359
    +360
    +361
    +362
    +363
    +364
    +365
    +366
    +367
    +368
    +369
    +370
    +371
    +372
    +373
    +374
    +375
    +376
    +377
    +378
    +379
    +380
    +381
    +382
    +383
    +384
    +385
    +386
    +387
    +388
    +389
    +390
    +391
    +392
    +393
    +394
    +395
    +396
    +397
    +398
    +399
    +400
    +401
    +402
    +403
    +404
    +405
    +406
    +407
    +408
    +409
    +410
    +411
    +412
    +413
    +414
    +415
    +416
    +417
    +418
    +419
    +420
    +421
    +422
    +423
    +424
    +425
    +426
    +427
    +428
    +429
    +430
    +431
    +432
    +433
    +434
    +435
    +436
    +437
    +438
    +439
    +440
    +441
    +442
    +443
    +444
    +445
    +446
    +447
    +448
     
    #![no_std]
     
    -mod defindex;
    +mod vault;
     mod events;
     mod storage;
     mod error;
     
    +use common::models::AssetStrategySet;
     use soroban_sdk::{
    -    contract, contractimpl, Address, BytesN, Env, Map, Vec
    +    contract, contractimpl, vec, Address, BytesN, Env, Map, String, Symbol, Val, Vec, IntoVal
     };
     use error::FactoryError;
    -use defindex::{create_contract, AssetAllocation};
    -use storage::{ add_new_defindex, extend_instance_ttl, get_admin, get_defi_wasm_hash, get_defindex_receiver, get_deployed_defindexes, get_fee_rate, has_admin, put_admin, put_defi_wasm_hash, put_defindex_receiver, put_fee_rate };
    +pub use vault::create_contract;
    +use storage::{ add_new_defindex, extend_instance_ttl, get_admin, get_vault_wasm_hash, get_defindex_receiver, get_deployed_defindexes, get_fee_rate, has_admin, put_admin, put_vault_wasm_hash, put_defindex_receiver, put_defindex_fee };
     
     fn check_initialized(e: &Env) -> Result<(), FactoryError> {
         if !has_admin(e) {
    @@ -360,8 +475,8 @@
         /// * `e` - The environment in which the contract is running.
         /// * `admin` - The address of the contract administrator, who can manage settings.
         /// * `defindex_receiver` - The default address designated to receive a portion of fees.
    -    /// * `fee_rate` - The initial annual fee rate (in basis points).
    -    /// * `defindex_wasm_hash` - The hash of the DeFindex Vault's WASM file for deploying new vaults.
    +    /// * `defindex_fee` - The initial annual fee rate (in basis points).
    +    /// * `vault_wasm_hash` - The hash of the DeFindex Vault's WASM file for deploying new vaults.
         /// 
         /// # Returns
         /// * `Result<(), FactoryError>` - Returns Ok(()) if successful, otherwise an error.
    @@ -369,8 +484,8 @@
             e: Env, 
             admin: Address,
             defindex_receiver: Address,
    -        fee_rate: u32,
    -        defindex_wasm_hash: BytesN<32>
    +        defindex_fee: u32,
    +        vault_wasm_hash: BytesN<32>
         ) -> Result<(), FactoryError>;
     
         /// Creates a new DeFindex Vault with specified parameters.
    @@ -379,9 +494,11 @@
         /// * `e` - The environment in which the contract is running.
         /// * `emergency_manager` - The address assigned emergency control over the vault.
         /// * `fee_receiver` - The address designated to receive fees from the vault.
    -    /// * `vault_share` - The percentage share of fees allocated to the vault's fee receiver.
    +    /// * `vault_fee` - The percentage share of fees allocated to the vault's fee receiver.
    +    /// * `vault_name` - The name of the vault.
    +    /// * `vault_symbol` - The symbol of the vault.
         /// * `manager` - The address assigned as the vault manager.
    -    /// * `assets` - A vector of `AssetAllocation` structs that define the assets managed by the vault.
    +    /// * `assets` - A vector of `AssetStrategySet` structs that define the assets managed by the vault.
         /// * `salt` - A salt used for ensuring unique addresses for each deployed vault.
         ///
         /// # Returns
    @@ -390,9 +507,41 @@
             e: Env, 
             emergency_manager: Address, 
             fee_receiver: Address, 
    -        vault_share: u32,
    +        vault_fee: u32,
    +        vault_name: String,
    +        vault_symbol: String,
             manager: Address,
    -        assets: Vec<AssetAllocation>,
    +        assets: Vec<AssetStrategySet>,
    +        salt: BytesN<32>
    +    ) -> Result<Address, FactoryError>;
    +
    +    /// Creates a new DeFindex Vault with specified parameters and makes the first deposit to set ratios.
    +    ///
    +    /// # Arguments
    +    /// * `e` - The environment in which the contract is running.
    +    /// * `emergency_manager` - The address assigned emergency control over the vault.
    +    /// * `fee_receiver` - The address designated to receive fees from the vault.
    +    /// * `vault_fee` - The percentage share of fees allocated to the vault's fee receiver.
    +    /// * `vault_name` - The name of the vault.
    +    /// * `vault_symbol` - The symbol of the vault.
    +    /// * `manager` - The address assigned as the vault manager.
    +    /// * `assets` - A vector of `AssetStrategySet` structs that define the assets managed by the vault.
    +    /// * `amounts` - A vector of `AssetAmounts` structs that define the initial deposit amounts.
    +    /// * `salt` - A salt used for ensuring unique addresses for each deployed vault.
    +    ///
    +    /// # Returns
    +    /// * `Result<Address, FactoryError>` - Returns the address of the new vault, or an error if unsuccessful.
    +    fn create_defindex_vault_deposit(
    +        e: Env, 
    +        caller: Address,
    +        emergency_manager: Address, 
    +        fee_receiver: Address, 
    +        vault_fee: u32,
    +        vault_name: String,
    +        vault_symbol: String,
    +        manager: Address,
    +        assets: Vec<AssetStrategySet>,
    +        amounts: Vec<i128>,
             salt: BytesN<32>
         ) -> Result<Address, FactoryError>;
     
    @@ -426,7 +575,7 @@
         ///
         /// # Returns
         /// * `Result<(), FactoryError>` - Returns Ok(()) if successful, or an error if not authorized.
    -    fn set_fee_rate(e: Env, new_fee_rate: u32) -> Result<(), FactoryError>;
    +    fn set_defindex_fee(e: Env, new_fee_rate: u32) -> Result<(), FactoryError>;
         
         // --- Read Methods ---
     
    @@ -464,7 +613,7 @@
         ///
         /// # Returns
         /// * `Result<u32, FactoryError>` - Returns the fee rate in basis points or an error if not found.
    -    fn fee_rate(e: Env) -> Result<u32, FactoryError>;
    +    fn defindex_fee(e: Env) -> Result<u32, FactoryError>;
     }
     
     #[contract]
    @@ -479,8 +628,8 @@
         /// * `e` - The environment in which the contract is running.
         /// * `admin` - The address of the contract administrator, who can manage settings.
         /// * `defindex_receiver` - The default address designated to receive a portion of fees.
    -    /// * `fee_rate` - The initial annual fee rate (in basis points).
    -    /// * `defindex_wasm_hash` - The hash of the DeFindex Vault's WASM file for deploying new vaults.
    +    /// * `defindex_fee` - The initial annual fee rate (in basis points).
    +    /// * `vault_wasm_hash` - The hash of the DeFindex Vault's WASM file for deploying new vaults.
         /// 
         /// # Returns
         /// * `Result<(), FactoryError>` - Returns Ok(()) if successful, otherwise an error.
    @@ -488,8 +637,8 @@
             e: Env, 
             admin: Address, 
             defindex_receiver: Address,
    -        fee_rate: u32,
    -        defi_wasm_hash: BytesN<32>
    +        defindex_fee: u32,
    +        vault_wasm_hash: BytesN<32>
         ) -> Result<(), FactoryError> {
             if has_admin(&e) {
                 return Err(FactoryError::AlreadyInitialized);
    @@ -497,10 +646,10 @@
     
             put_admin(&e, &admin);
             put_defindex_receiver(&e, &defindex_receiver);
    -        put_defi_wasm_hash(&e, defi_wasm_hash);
    -        put_fee_rate(&e, &fee_rate);
    +        put_vault_wasm_hash(&e, vault_wasm_hash);
    +        put_defindex_fee(&e, &defindex_fee);
     
    -        events::emit_initialized(&e, admin, defindex_receiver, fee_rate);
    +        events::emit_initialized(&e, admin, defindex_receiver, defindex_fee);
             extend_instance_ttl(&e);
             Ok(())
         }
    @@ -511,9 +660,9 @@
         /// * `e` - The environment in which the contract is running.
         /// * `emergency_manager` - The address assigned emergency control over the vault.
         /// * `fee_receiver` - The address designated to receive fees from the vault.
    -    /// * `vault_share` - The percentage share of fees allocated to the vault's fee receiver.
    +    /// * `vault_fee` - The percentage share of fees allocated to the vault's fee receiver.
         /// * `manager` - The address assigned as the vault manager.
    -    /// * `assets` - A vector of `AssetAllocation` structs that define the assets managed by the vault.
    +    /// * `assets` - A vector of `AssetStrategySet` structs that define the assets managed by the vault.
         /// * `salt` - A salt used for ensuring unique addresses for each deployed vault.
         ///
         /// # Returns
    @@ -522,32 +671,111 @@
             e: Env, 
             emergency_manager: Address, 
             fee_receiver: Address, 
    -        vault_share: u32,
    +        vault_fee: u32,
    +        vault_name: String,
    +        vault_symbol: String,
    +        manager: Address,
    +        assets: Vec<AssetStrategySet>,
    +        salt: BytesN<32>
    +    ) -> Result<Address, FactoryError> {
    +        extend_instance_ttl(&e);
    +
    +        let current_contract = e.current_contract_address();
    +
    +        let vault_wasm_hash = get_vault_wasm_hash(&e)?;
    +        let defindex_address = create_contract(&e, vault_wasm_hash, salt);
    +
    +        let defindex_receiver = get_defindex_receiver(&e);
    +
    +        let mut init_args: Vec<Val> = vec![&e];
    +        init_args.push_back(assets.to_val());
    +        init_args.push_back(manager.to_val());
    +        init_args.push_back(emergency_manager.to_val());
    +        init_args.push_back(fee_receiver.to_val());
    +        init_args.push_back(vault_fee.into_val(&e));
    +        init_args.push_back(defindex_receiver.to_val());
    +        init_args.push_back(current_contract.to_val());
    +        init_args.push_back(vault_name.to_val());
    +        init_args.push_back(vault_symbol.to_val());
    +
    +        e.invoke_contract::<Val>(&defindex_address, &Symbol::new(&e, "initialize"), init_args);
    +
    +        add_new_defindex(&e, defindex_address.clone());
    +        events::emit_create_defindex_vault(&e, emergency_manager, fee_receiver, manager, vault_fee, assets);
    +        Ok(defindex_address)
    +    }
    +
    +    /// Creates a new DeFindex Vault with specified parameters and makes the first deposit to set ratios.
    +    ///
    +    /// # Arguments
    +    /// * `e` - The environment in which the contract is running.
    +    /// * `emergency_manager` - The address assigned emergency control over the vault.
    +    /// * `fee_receiver` - The address designated to receive fees from the vault.
    +    /// * `vault_fee` - The percentage share of fees allocated to the vault's fee receiver.
    +    /// * `vault_name` - The name of the vault.
    +    /// * `vault_symbol` - The symbol of the vault.
    +    /// * `manager` - The address assigned as the vault manager.
    +    /// * `assets` - A vector of `AssetStrategySet` structs that define the assets managed by the vault.
    +    /// * `amounts` - A vector of `AssetAmounts` structs that define the initial deposit amounts.
    +    /// * `salt` - A salt used for ensuring unique addresses for each deployed vault.
    +    ///
    +    /// # Returns
    +    /// * `Result<Address, FactoryError>` - Returns the address of the new vault, or an error if unsuccessful.
    +    fn create_defindex_vault_deposit(
    +        e: Env, 
    +        caller: Address,
    +        emergency_manager: Address, 
    +        fee_receiver: Address, 
    +        vault_fee: u32,
    +        vault_name: String,
    +        vault_symbol: String,
             manager: Address,
    -        assets: Vec<AssetAllocation>,
    +        assets: Vec<AssetStrategySet>,
    +        amounts: Vec<i128>,
             salt: BytesN<32>
         ) -> Result<Address, FactoryError> {
             extend_instance_ttl(&e);
    +        caller.require_auth();
    +
    +        if assets.len() != amounts.len() {
    +            return Err(FactoryError::AssetLengthMismatch);
    +        }
     
             let current_contract = e.current_contract_address();
     
    -        let defi_wasm_hash = get_defi_wasm_hash(&e)?;
    -        let defindex_address = create_contract(&e, defi_wasm_hash, salt);
    +        let vault_wasm_hash = get_vault_wasm_hash(&e)?;
    +        let defindex_address = create_contract(&e, vault_wasm_hash, salt);
     
             let defindex_receiver = get_defindex_receiver(&e);
     
    -        defindex::Client::new(&e, &defindex_address).initialize(
    -            &assets,
    -            &manager,
    -            &emergency_manager,
    -            &fee_receiver,
    -            &vault_share,
    -            &defindex_receiver,
    -            &current_contract,
    -        );
    +        let mut init_args: Vec<Val> = vec![&e];
    +        init_args.push_back(assets.to_val());
    +        init_args.push_back(manager.to_val());
    +        init_args.push_back(emergency_manager.to_val());
    +        init_args.push_back(fee_receiver.to_val());
    +        init_args.push_back(vault_fee.into_val(&e));
    +        init_args.push_back(defindex_receiver.to_val());
    +        init_args.push_back(current_contract.to_val());
    +        init_args.push_back(vault_name.to_val());
    +        init_args.push_back(vault_symbol.to_val());
    +
    +        e.invoke_contract::<Val>(&defindex_address, &Symbol::new(&e, "initialize"), init_args);
    +
    +        let mut amounts_min = Vec::new(&e);
    +        for _ in 0..amounts.len() {
    +            amounts_min.push_back(0i128);
    +        }
    +
    +        let mut deposit_args: Vec<Val> = vec![&e];
    +        deposit_args.push_back(amounts.to_val());
    +        deposit_args.push_back(amounts_min.to_val());
    +        deposit_args.push_back(caller.to_val());
    +        deposit_args.push_back(false.into_val(&e));
    +        
    +        e.invoke_contract::<Val>(&defindex_address, &Symbol::new(&e, "deposit"), deposit_args);
     
             add_new_defindex(&e, defindex_address.clone());
    -        events::emit_create_defindex_vault(&e, emergency_manager, fee_receiver, manager, vault_share, assets);
    +        events::emit_create_defindex_vault(&e, emergency_manager, fee_receiver, manager, vault_fee, assets);
             Ok(defindex_address)
         }
     
    @@ -599,14 +827,14 @@
         ///
         /// # Returns
         /// * `Result<(), FactoryError>` - Returns Ok(()) if successful, or an error if not authorized.
    -    fn set_fee_rate(e: Env, fee_rate: u32) -> Result<(), FactoryError> {
    +    fn set_defindex_fee(e: Env, defindex_fee: u32) -> Result<(), FactoryError> {
             check_initialized(&e)?;
             extend_instance_ttl(&e);
             let admin = get_admin(&e);
             admin.require_auth();
     
    -        put_fee_rate(&e, &fee_rate);
    -        events::emit_new_fee_rate(&e, fee_rate);
    +        put_defindex_fee(&e, &defindex_fee);
    +        events::emit_new_defindex_fee(&e, defindex_fee);
             Ok(())
         }
     
    @@ -658,7 +886,7 @@
         ///
         /// # Returns
         /// * `Result<u32, FactoryError>` - Returns the fee rate in basis points or an error if not found.
    -    fn fee_rate(e: Env) -> Result<u32, FactoryError> {
    +    fn defindex_fee(e: Env) -> Result<u32, FactoryError> {
             check_initialized(&e)?;
             extend_instance_ttl(&e);
             Ok(get_fee_rate(&e))
    diff --git a/apps/rust_docs/src/defindex_factory/storage.rs.html b/apps/rust_docs/src/defindex_factory/storage.rs.html
    index f31476a8..3a1b0b79 100644
    --- a/apps/rust_docs/src/defindex_factory/storage.rs.html
    +++ b/apps/rust_docs/src/defindex_factory/storage.rs.html
    @@ -1,4 +1,4 @@
    -storage.rs - source
    1
    +storage.rs - source
    1
     2
     3
     4
    @@ -150,14 +150,14 @@
         }
     }
     
    -pub fn get_defi_wasm_hash(e: &Env) -> Result<BytesN<32>, FactoryError>{
    +pub fn get_vault_wasm_hash(e: &Env) -> Result<BytesN<32>, FactoryError>{
         let key = DataKey::DeFindexWasmHash;
         get_persistent_extend_or_error(&e, &key, FactoryError::NotInitialized)
     }
     
    -pub fn put_defi_wasm_hash(e: &Env, pair_wasm_hash: BytesN<32>) {
    +pub fn put_vault_wasm_hash(e: &Env, vault_wasm_hash: BytesN<32>) {
         let key = DataKey::DeFindexWasmHash;
    -    e.storage().persistent().set(&key, &pair_wasm_hash);
    +    e.storage().persistent().set(&key, &vault_wasm_hash);
         e.storage()
                 .persistent()
                 .extend_ttl(&key, PERSISTENT_LIFETIME_THRESHOLD, PERSISTENT_BUMP_AMOUNT)
    @@ -207,7 +207,7 @@
     }
     
     // Fee Rate BPS (MAX BPS = 10000)
    -pub fn put_fee_rate(e: &Env, value: &u32) {
    +pub fn put_defindex_fee(e: &Env, value: &u32) {
         e.storage().instance().set(&DataKey::FeeRate, value);
     }
     
    diff --git a/apps/rust_docs/src/defindex_factory/vault.rs.html b/apps/rust_docs/src/defindex_factory/vault.rs.html
    new file mode 100644
    index 00000000..a11f8660
    --- /dev/null
    +++ b/apps/rust_docs/src/defindex_factory/vault.rs.html
    @@ -0,0 +1,28 @@
    +vault.rs - source
    1
    +2
    +3
    +4
    +5
    +6
    +7
    +8
    +9
    +10
    +11
    +12
    +13
    +14
    +
    #![allow(unused)]
    +use soroban_sdk::{contracttype, contracterror, xdr::ToXdr, Address, Bytes, BytesN, Env, Vec};
    +
    +// Define a function to create a new contract instance
    +pub fn create_contract(
    +    e: &Env, // Pass in the current environment as an argument
    +    defindex_wasm_hash: BytesN<32>, // Pass in the hash of the token contract's WASM file
    +    salt: BytesN<32>,
    +) -> Address {
    +
    +    e.deployer()
    +        .with_current_contract(e.crypto().sha256(&salt.into())) 
    +        .deploy(defindex_wasm_hash)
    +}
    \ No newline at end of file diff --git a/apps/rust_docs/src/defindex_strategy_core/error.rs.html b/apps/rust_docs/src/defindex_strategy_core/error.rs.html index 1eebecae..44d6c58a 100644 --- a/apps/rust_docs/src/defindex_strategy_core/error.rs.html +++ b/apps/rust_docs/src/defindex_strategy_core/error.rs.html @@ -1,4 +1,4 @@ -error.rs - source
    1
    +error.rs - source
    1
     2
     3
     4
    @@ -18,6 +18,7 @@
     18
     19
     20
    +21
     
    use soroban_sdk::{self, contracterror};
     
     #[contracterror]
    @@ -31,6 +32,7 @@
         // Validation Errors
         NegativeNotAllowed = 410,
         InvalidArgument = 411,
    +    InsufficientBalance = 412,
     
         // Protocol Errors
         ProtocolAddressNotFound = 420,
    diff --git a/apps/rust_docs/src/defindex_strategy_core/event.rs.html b/apps/rust_docs/src/defindex_strategy_core/event.rs.html
    index 4411473e..0a8bbb2e 100644
    --- a/apps/rust_docs/src/defindex_strategy_core/event.rs.html
    +++ b/apps/rust_docs/src/defindex_strategy_core/event.rs.html
    @@ -1,4 +1,4 @@
    -event.rs - source
    1
    +event.rs - source
    1
     2
     3
     4
    diff --git a/apps/rust_docs/src/defindex_strategy_core/lib.rs.html b/apps/rust_docs/src/defindex_strategy_core/lib.rs.html
    index 47dc98b5..e05b4f7d 100644
    --- a/apps/rust_docs/src/defindex_strategy_core/lib.rs.html
    +++ b/apps/rust_docs/src/defindex_strategy_core/lib.rs.html
    @@ -1,4 +1,4 @@
    -lib.rs - source
    1
    +lib.rs - source
    1
     2
     3
     4
    diff --git a/apps/rust_docs/src/defindex_vault/access.rs.html b/apps/rust_docs/src/defindex_vault/access.rs.html
    index b4a470b5..d7a6d4c1 100644
    --- a/apps/rust_docs/src/defindex_vault/access.rs.html
    +++ b/apps/rust_docs/src/defindex_vault/access.rs.html
    @@ -1,4 +1,4 @@
    -access.rs - source
    1
    +access.rs - source
    1
     2
     3
     4
    @@ -109,6 +109,9 @@
     109
     110
     111
    +112
    +113
    +114
     
    use crate::error::ContractError;
     use crate::utils::bump_instance;
     use soroban_sdk::{contracttype, panic_with_error, Address, Env};
    @@ -117,7 +120,7 @@
     #[contracttype]
     pub enum RolesDataKey {
         EmergencyManager, // Role: Emergency Manager
    -    FeeReceiver,      // Role: Fee Receiver
    +    VaultFeeReceiver, // Role: Fee Receiver
         Manager,          // Role: Manager
     }
     
    @@ -193,13 +196,16 @@
     
     // Role-specific setters and getters
     impl AccessControl {
    -    pub fn set_fee_receiver(&self, caller: &Address, fee_receiver: &Address) {
    -        self.require_any_role(&[RolesDataKey::Manager, RolesDataKey::FeeReceiver], caller);
    -        self.set_role(&RolesDataKey::FeeReceiver, fee_receiver);
    +    pub fn set_fee_receiver(&self, caller: &Address, vault_fee_receiver: &Address) {
    +        self.require_any_role(
    +            &[RolesDataKey::Manager, RolesDataKey::VaultFeeReceiver],
    +            caller,
    +        );
    +        self.set_role(&RolesDataKey::VaultFeeReceiver, vault_fee_receiver);
         }
     
         pub fn get_fee_receiver(&self) -> Result<Address, ContractError> {
    -        self.check_role(&RolesDataKey::FeeReceiver)
    +        self.check_role(&RolesDataKey::VaultFeeReceiver)
         }
     
         pub fn set_manager(&self, manager: &Address) {
    diff --git a/apps/rust_docs/src/defindex_vault/aggregator.rs.html b/apps/rust_docs/src/defindex_vault/aggregator.rs.html
    new file mode 100644
    index 00000000..7e0d9a4f
    --- /dev/null
    +++ b/apps/rust_docs/src/defindex_vault/aggregator.rs.html
    @@ -0,0 +1,173 @@
    +aggregator.rs - source
    1
    +2
    +3
    +4
    +5
    +6
    +7
    +8
    +9
    +10
    +11
    +12
    +13
    +14
    +15
    +16
    +17
    +18
    +19
    +20
    +21
    +22
    +23
    +24
    +25
    +26
    +27
    +28
    +29
    +30
    +31
    +32
    +33
    +34
    +35
    +36
    +37
    +38
    +39
    +40
    +41
    +42
    +43
    +44
    +45
    +46
    +47
    +48
    +49
    +50
    +51
    +52
    +53
    +54
    +55
    +56
    +57
    +58
    +59
    +60
    +61
    +62
    +63
    +64
    +65
    +66
    +67
    +68
    +69
    +70
    +71
    +72
    +73
    +74
    +75
    +76
    +77
    +78
    +79
    +80
    +81
    +82
    +83
    +84
    +85
    +86
    +
    use soroban_sdk::{vec, Address, Env, IntoVal, Symbol, Val, Vec};
    +
    +use crate::{
    +    models::DexDistribution,
    +    storage::{get_assets, get_factory},
    +    ContractError,
    +};
    +
    +fn fetch_aggregator_address(e: &Env) -> Address {
    +    let factory_address = get_factory(e);
    +
    +    e.invoke_contract(
    +        &factory_address,
    +        &Symbol::new(&e, "aggregator"),
    +        Vec::new(&e),
    +    )
    +}
    +
    +fn is_supported_asset(e: &Env, token: &Address) -> bool {
    +    let assets = get_assets(e);
    +    assets.iter().any(|asset| &asset.address == token)
    +}
    +
    +pub fn internal_swap_exact_tokens_for_tokens(
    +    e: &Env,
    +    token_in: &Address,
    +    token_out: &Address,
    +    amount_in: &i128,
    +    amount_out_min: &i128,
    +    distribution: &Vec<DexDistribution>,
    +    deadline: &u64,
    +) -> Result<(), ContractError> {
    +    let aggregator_address = fetch_aggregator_address(e);
    +
    +    // Check if both tokens are supported by the vault
    +    if !is_supported_asset(e, token_in) || !is_supported_asset(e, token_out) {
    +        return Err(ContractError::UnsupportedAsset);
    +    }
    +
    +    let mut swap_args: Vec<Val> = vec![&e];
    +    swap_args.push_back(token_in.to_val());
    +    swap_args.push_back(token_out.to_val());
    +    swap_args.push_back(amount_in.into_val(e));
    +    swap_args.push_back(amount_out_min.into_val(e));
    +    swap_args.push_back(distribution.into_val(e));
    +    swap_args.push_back(e.current_contract_address().to_val());
    +    swap_args.push_back(deadline.into_val(e));
    +
    +    e.invoke_contract(
    +        &aggregator_address,
    +        &Symbol::new(&e, "swap_exact_tokens_for_tokens"),
    +        swap_args,
    +    )
    +}
    +
    +pub fn internal_swap_tokens_for_exact_tokens(
    +    e: &Env,
    +    token_in: &Address,
    +    token_out: &Address,
    +    amount_out: &i128,
    +    amount_in_max: &i128,
    +    distribution: &Vec<DexDistribution>,
    +    deadline: &u64,
    +) -> Result<(), ContractError> {
    +    let aggregator_address = fetch_aggregator_address(e);
    +
    +    // Check if both tokens are supported by the vault
    +    if !is_supported_asset(e, token_in) || !is_supported_asset(e, token_out) {
    +        return Err(ContractError::UnsupportedAsset);
    +    }
    +
    +    let mut swap_args: Vec<Val> = vec![&e];
    +    swap_args.push_back(token_in.to_val());
    +    swap_args.push_back(token_out.to_val());
    +    swap_args.push_back(amount_out.into_val(e));
    +    swap_args.push_back(amount_in_max.into_val(e));
    +    swap_args.push_back(distribution.into_val(e));
    +    swap_args.push_back(e.current_contract_address().to_val());
    +    swap_args.push_back(deadline.into_val(e));
    +
    +    e.invoke_contract(
    +        &aggregator_address,
    +        &Symbol::new(&e, "swap_tokens_for_exact_tokens"),
    +        swap_args,
    +    )
    +}
    +
    \ No newline at end of file diff --git a/apps/rust_docs/src/defindex_vault/constants.rs.html b/apps/rust_docs/src/defindex_vault/constants.rs.html index 9b634b88..71eec3ca 100644 --- a/apps/rust_docs/src/defindex_vault/constants.rs.html +++ b/apps/rust_docs/src/defindex_vault/constants.rs.html @@ -1,4 +1,5 @@ -constants.rs - source
    1
    +constants.rs - source
    1
     2
     
    pub(crate) const MAX_BPS: i128 = 10_000;
    -pub(crate) const SECONDS_PER_YEAR: i128 = 31_536_000;
    \ No newline at end of file +pub(crate) const SECONDS_PER_YEAR: i128 = 31_536_000; +
    \ No newline at end of file diff --git a/apps/rust_docs/src/defindex_vault/deposit.rs.html b/apps/rust_docs/src/defindex_vault/deposit.rs.html new file mode 100644 index 00000000..cfd84a81 --- /dev/null +++ b/apps/rust_docs/src/defindex_vault/deposit.rs.html @@ -0,0 +1,311 @@ +deposit.rs - source
    1
    +2
    +3
    +4
    +5
    +6
    +7
    +8
    +9
    +10
    +11
    +12
    +13
    +14
    +15
    +16
    +17
    +18
    +19
    +20
    +21
    +22
    +23
    +24
    +25
    +26
    +27
    +28
    +29
    +30
    +31
    +32
    +33
    +34
    +35
    +36
    +37
    +38
    +39
    +40
    +41
    +42
    +43
    +44
    +45
    +46
    +47
    +48
    +49
    +50
    +51
    +52
    +53
    +54
    +55
    +56
    +57
    +58
    +59
    +60
    +61
    +62
    +63
    +64
    +65
    +66
    +67
    +68
    +69
    +70
    +71
    +72
    +73
    +74
    +75
    +76
    +77
    +78
    +79
    +80
    +81
    +82
    +83
    +84
    +85
    +86
    +87
    +88
    +89
    +90
    +91
    +92
    +93
    +94
    +95
    +96
    +97
    +98
    +99
    +100
    +101
    +102
    +103
    +104
    +105
    +106
    +107
    +108
    +109
    +110
    +111
    +112
    +113
    +114
    +115
    +116
    +117
    +118
    +119
    +120
    +121
    +122
    +123
    +124
    +125
    +126
    +127
    +128
    +129
    +130
    +131
    +132
    +133
    +134
    +135
    +136
    +137
    +138
    +139
    +140
    +141
    +142
    +143
    +144
    +145
    +146
    +147
    +148
    +149
    +150
    +151
    +152
    +153
    +154
    +155
    +
    use common::models::AssetStrategySet;
    +use soroban_sdk::{panic_with_error, token::TokenClient, Address, Env, Vec};
    +
    +use crate::{
    +    funds::{
    +        fetch_invested_funds_for_asset, fetch_invested_funds_for_strategy,
    +        fetch_total_managed_funds,
    +    },
    +    investment::check_and_execute_investments,
    +    models::{AssetInvestmentAllocation, StrategyAllocation},
    +    storage::get_assets,
    +    token::{internal_mint, VaultToken},
    +    utils::{calculate_deposit_amounts_and_shares_to_mint, check_nonnegative_amount},
    +    ContractError, MINIMUM_LIQUIDITY,
    +};
    +
    +/// Common logic for processing deposits.
    +pub fn process_deposit(
    +    e: &Env,
    +    assets: &Vec<AssetStrategySet>,
    +    amounts_desired: &Vec<i128>,
    +    amounts_min: &Vec<i128>,
    +    from: &Address,
    +) -> Result<(Vec<i128>, i128), ContractError> {
    +    let assets_length = assets.len();
    +
    +    // Validate inputs
    +    if assets_length != amounts_desired.len() || assets_length != amounts_min.len() {
    +        panic_with_error!(&e, ContractError::WrongAmountsLength);
    +    }
    +
    +    for amount in amounts_desired.iter() {
    +        check_nonnegative_amount(amount)?;
    +    }
    +
    +    let total_supply = VaultToken::total_supply(e.clone());
    +    let (amounts, shares_to_mint) = if assets_length == 1 {
    +        calculate_single_asset_shares(e, amounts_desired, total_supply)?
    +    } else {
    +        if total_supply == 0 {
    +            (amounts_desired.clone(), amounts_desired.iter().sum())
    +        } else {
    +            calculate_deposit_amounts_and_shares_to_mint(&e, &assets, amounts_desired, amounts_min)?
    +        }
    +    };
    +
    +    // Transfer assets
    +    for (i, amount) in amounts.iter().enumerate() {
    +        if amount < amounts_min.get(i as u32).unwrap() {
    +            panic_with_error!(&e, ContractError::InsufficientAmount);
    +        }
    +        if amount > 0 {
    +            let asset = assets.get(i as u32).unwrap();
    +            let asset_client = TokenClient::new(&e, &asset.address);
    +            asset_client.transfer(&from, &e.current_contract_address(), &amount);
    +        }
    +    }
    +
    +    // Mint shares
    +    mint_shares(e, total_supply, shares_to_mint, from.clone())?;
    +
    +    Ok((amounts, shares_to_mint))
    +}
    +
    +/// Calculate shares for single-asset deposits.
    +fn calculate_single_asset_shares(
    +    e: &Env,
    +    amounts_desired: &Vec<i128>,
    +    total_supply: i128,
    +) -> Result<(Vec<i128>, i128), ContractError> {
    +    let shares = if total_supply == 0 {
    +        amounts_desired.get(0).unwrap()
    +    } else {
    +        let total_managed_funds = fetch_total_managed_funds(&e);
    +        VaultToken::total_supply(e.clone())
    +            .checked_mul(amounts_desired.get(0).unwrap())
    +            .unwrap_or_else(|| panic_with_error!(&e, ContractError::ArithmeticError))
    +            .checked_div(
    +                total_managed_funds
    +                    .get(get_assets(&e).get(0).unwrap().address.clone())
    +                    .unwrap().total_amount,
    +            )
    +            .unwrap_or_else(|| panic_with_error!(&e, ContractError::ArithmeticError))
    +    };
    +    Ok((amounts_desired.clone(), shares))
    +}
    +
    +/// Mint vault shares.
    +fn mint_shares(
    +    e: &Env,
    +    total_supply: i128,
    +    shares_to_mint: i128,
    +    from: Address,
    +) -> Result<(), ContractError> {
    +    if total_supply == 0 {
    +        if shares_to_mint < MINIMUM_LIQUIDITY {
    +            panic_with_error!(&e, ContractError::InsufficientAmount);
    +        }
    +        internal_mint(e.clone(), e.current_contract_address(), MINIMUM_LIQUIDITY);
    +        internal_mint(
    +            e.clone(),
    +            from.clone(),
    +            shares_to_mint.checked_sub(MINIMUM_LIQUIDITY).unwrap(),
    +        );
    +    } else {
    +        internal_mint(e.clone(), from, shares_to_mint);
    +    }
    +    Ok(())
    +}
    +
    +/// Generate investment allocations and execute them.
    +pub fn generate_and_execute_investments(
    +    e: &Env,
    +    amounts: &Vec<i128>,
    +    assets: &Vec<AssetStrategySet>,
    +) -> Result<(), ContractError> {
    +    let mut asset_investments = Vec::new(&e);
    +
    +    for (i, amount) in amounts.iter().enumerate() {
    +        let asset = assets.get(i as u32).unwrap();
    +        let (asset_invested_funds, _) = fetch_invested_funds_for_asset(&e, &asset);
    +
    +        let mut strategy_allocations = Vec::new(&e);
    +        let mut remaining_amount = amount;
    +
    +        for (j, strategy) in asset.strategies.iter().enumerate() {
    +            let strategy_invested_funds = fetch_invested_funds_for_strategy(&e, &strategy.address);
    +
    +            let mut invest_amount = if asset_invested_funds > 0 {
    +                (amount * strategy_invested_funds) / asset_invested_funds
    +            } else {
    +                0
    +            };
    +
    +            if j == asset.strategies.len() as usize - 1 {
    +                invest_amount = remaining_amount;
    +            }
    +
    +            remaining_amount -= invest_amount;
    +
    +            strategy_allocations.push_back(Some(StrategyAllocation {
    +                strategy_address: strategy.address.clone(),
    +                amount: invest_amount,
    +            }));
    +        }
    +
    +        asset_investments.push_back(Some(AssetInvestmentAllocation {
    +            asset: asset.address.clone(),
    +            strategy_allocations,
    +        }));
    +    }
    +
    +    check_and_execute_investments(e.clone(), assets.clone(), asset_investments)?;
    +    Ok(())
    +}
    +
    \ No newline at end of file diff --git a/apps/rust_docs/src/defindex_vault/error.rs.html b/apps/rust_docs/src/defindex_vault/error.rs.html index 182cc1e6..9a48190b 100644 --- a/apps/rust_docs/src/defindex_vault/error.rs.html +++ b/apps/rust_docs/src/defindex_vault/error.rs.html @@ -1,4 +1,4 @@ -error.rs - source
    1
    +error.rs - source
    1
     2
     3
     4
    @@ -33,6 +33,20 @@
     33
     34
     35
    +36
    +37
    +38
    +39
    +40
    +41
    +42
    +43
    +44
    +45
    +46
    +47
    +48
    +49
     
    use soroban_sdk::{self, contracterror};
     
     #[contracterror]
    @@ -43,14 +57,25 @@
         NotInitialized = 100,
         AlreadyInitialized = 101,
         InvalidRatio = 102,
    -    StrategyDoesNotSupportAsset=103,
    +    StrategyDoesNotSupportAsset = 103,
    +    NoAssetAllocation = 104,
     
         // Validation Errors (11x)
         NegativeNotAllowed = 110,
         InsufficientBalance = 111,
    -    WrongAmuntsLength = 112,
    +    WrongAmountsLength = 112,
         NotEnoughIdleFunds = 113,
         InsufficientManagedFunds = 114,
    +    MissingInstructionData = 115,
    +    UnsupportedAsset = 116,
    +    InsufficientAmount = 117,
    +    NoOptimalAmounts = 118, //this should not happen
    +    WrongInvestmentLength = 119,
    +    WrongAssetAddress = 122,
    +    WrongStrategiesLength = 123,
    +    AmountOverTotalSupply = 124,
    +    NoInstructions = 125,
    +
     
         // Arithmetic Errors (12x)
         ArithmeticError = 120,
    @@ -63,6 +88,9 @@
         // Strategy Errors (14x)
         StrategyNotFound = 140,
         StrategyPausedOrNotFound = 141,
    +    StrategyWithdrawError = 142,
    +    StrategyInvestError = 143,
    +    StrategyPaused = 144,
     
         // Asset Errors (15x)
         AssetNotFound = 150,
    diff --git a/apps/rust_docs/src/defindex_vault/events.rs.html b/apps/rust_docs/src/defindex_vault/events.rs.html
    index 246a3a11..df6f9a0f 100644
    --- a/apps/rust_docs/src/defindex_vault/events.rs.html
    +++ b/apps/rust_docs/src/defindex_vault/events.rs.html
    @@ -1,4 +1,4 @@
    -events.rs - source
    1
    +events.rs - source
    1
     2
     3
     4
    @@ -229,40 +229,35 @@
     229
     230
     231
    -232
    -233
    -234
    -235
    -236
     
    //! Definition of the Events used in the DeFindex Vault contract
    -use soroban_sdk::{contracttype, symbol_short, Address, Env, Vec};
    -use crate::models::AssetAllocation;
    +use common::models::AssetStrategySet;
    +use soroban_sdk::{contracttype, symbol_short, Address, Env, Vec};
     
     // INITIALIZED VAULT EVENT
     #[contracttype]
     #[derive(Clone, Debug, Eq, PartialEq)]
     pub struct InitializedVaultEvent {
         pub emergency_manager: Address,
    -    pub fee_receiver: Address,
    +    pub vault_fee_receiver: Address,
         pub manager: Address,
    -    pub defindex_receiver: Address,
    -    pub assets: Vec<AssetAllocation>,
    +    pub defindex_protocol_receiver: Address,
    +    pub assets: Vec<AssetStrategySet>,
     }
     
     /// Publishes an `InitializedVaultEvent` to the event stream.
     pub(crate) fn emit_initialized_vault(
         e: &Env,
         emergency_manager: Address,
    -    fee_receiver: Address,
    +    vault_fee_receiver: Address,
         manager: Address,
    -    defindex_receiver: Address,
    -    assets: Vec<AssetAllocation>,
    +    defindex_protocol_receiver: Address,
    +    assets: Vec<AssetStrategySet>,
     ) {
         let event = InitializedVaultEvent {
             emergency_manager,
    -        fee_receiver,
    +        vault_fee_receiver,
             manager,
    -        defindex_receiver,
    +        defindex_protocol_receiver,
             assets,
         };
     
    @@ -414,9 +409,7 @@
     
     /// Publishes a `ManagerChangedEvent` to the event stream.
     pub(crate) fn emit_manager_changed_event(e: &Env, new_manager: Address) {
    -    let event = ManagerChangedEvent {
    -        new_manager,
    -    };
    +    let event = ManagerChangedEvent { new_manager };
     
         e.events()
             .publish(("DeFindexVault", symbol_short!("nmanager")), event);
    @@ -430,10 +423,7 @@
     }
     
     /// Publishes an `EmergencyManagerChangedEvent` to the event stream.
    -pub(crate) fn emit_emergency_manager_changed_event(
    -    e: &Env,
    -    new_emergency_manager: Address,
    -) {
    +pub(crate) fn emit_emergency_manager_changed_event(e: &Env, new_emergency_manager: Address) {
         let event = EmergencyManagerChangedEvent {
             new_emergency_manager,
         };
    @@ -446,7 +436,7 @@
     #[contracttype]
     #[derive(Clone, Debug, Eq, PartialEq)]
     pub struct FeesMintedEvent {
    -    pub defindex_receiver: Address,
    +    pub defindex_protocol_receiver: Address,
         pub defindex_shares: i128,
         pub vault_receiver: Address,
         pub vault_shares: i128,
    @@ -455,13 +445,13 @@
     /// Publishes an `EmergencyManagerChangedEvent` to the event stream.
     pub(crate) fn emit_fees_minted_event(
         e: &Env,
    -    defindex_receiver: Address,
    +    defindex_protocol_receiver: Address,
         defindex_shares: i128,
         vault_receiver: Address,
         vault_shares: i128,
     ) {
         let event = FeesMintedEvent {
    -        defindex_receiver,
    +        defindex_protocol_receiver,
             defindex_shares,
             vault_receiver,
             vault_shares,
    @@ -469,4 +459,5 @@
     
         e.events()
             .publish(("DeFindexVault", symbol_short!("mfees")), event);
    -}
    \ No newline at end of file +} +
    \ No newline at end of file diff --git a/apps/rust_docs/src/defindex_vault/fee.rs.html b/apps/rust_docs/src/defindex_vault/fee.rs.html index e4d1ee88..d016faca 100644 --- a/apps/rust_docs/src/defindex_vault/fee.rs.html +++ b/apps/rust_docs/src/defindex_vault/fee.rs.html @@ -1,4 +1,4 @@ -fee.rs - source
    1
    +fee.rs - source
    1
     2
     3
     4
    @@ -80,85 +80,136 @@
     80
     81
     82
    -
    use soroban_sdk::{Address, Env, Map, Symbol, Vec};
    -
    -use crate::{access::AccessControl, constants::{MAX_BPS, SECONDS_PER_YEAR}, events, funds::fetch_total_managed_funds, storage::{get_defindex_receiver, get_factory, get_last_fee_assesment, get_vault_share, set_last_fee_assesment}, token::internal_mint, utils::calculate_dftokens_from_asset_amounts, ContractError};
    +83
    +84
    +85
    +86
    +87
    +88
    +89
    +90
    +91
    +92
    +93
    +94
    +95
    +96
    +97
    +98
    +99
    +100
    +101
    +102
    +103
    +104
    +105
    +106
    +107
    +
    use soroban_sdk::{Env, Symbol, Vec};
    +
    +use crate::{
    +    access::AccessControl,
    +    constants::{MAX_BPS, SECONDS_PER_YEAR},
    +    events,
    +    storage::{
    +        get_defindex_protocol_fee_receiver, get_factory, get_last_fee_assesment, get_vault_fee,
    +        set_last_fee_assesment,
    +    },
    +    token::{internal_mint, VaultToken},
    +    ContractError,
    +};
     
     /// Fetches the current fee rate from the factory contract.
     /// The fee rate is expressed in basis points (BPS).
    -fn fetch_fee_rate(e: &Env) -> u32 {
    -  let factory_address = get_factory(e);
    -  // Interacts with the factory contract to get the fee rate.
    -  e.invoke_contract(
    -    &factory_address,
    -    &Symbol::new(&e, "fee_rate"), 
    -    Vec::new(&e)
    -  )
    +pub fn fetch_defindex_fee(e: &Env) -> u32 {
    +    let factory_address = get_factory(e);
    +    // Interacts with the factory contract to get the fee rate.
    +    e.invoke_contract(
    +      &factory_address,
    +      &Symbol::new(&e, "defindex_fee"), 
    +      Vec::new(&e)
    +    )
     }
     
    -fn calculate_fees(e: &Env, time_elapsed: u64, fee_rate: u32) -> Result<i128, ContractError> {
    -
    -    let total_managed_funds = fetch_total_managed_funds(e); // Get total managed funds per asset
    +/// Calculates the required fees in dfTokens based on the current APR fee rate.
    +fn calculate_fees(e: &Env, time_elapsed: u64, fee_rate: u32) -> Result<i128, ContractError> {
    +    let total_supply = VaultToken::total_supply(e.clone());
    +
    +    // fee_rate as i128 * total_supply * time_elapsed / SECONDS_PER_YEAR * MAX_BPS - fee_rate as i128 * time_elapsed;
    +    let numerator = (fee_rate as i128)
    +        .checked_mul(total_supply)
    +        .unwrap()
    +        .checked_mul(time_elapsed as i128)
    +        .unwrap();
    +    let denominator = SECONDS_PER_YEAR
    +        .checked_mul(MAX_BPS)
    +        .unwrap()
    +        .checked_sub((fee_rate as i128).checked_mul(time_elapsed as i128).unwrap())
    +        .unwrap();
    +    let fees = numerator.checked_div(denominator).unwrap();
         
    -    let seconds_per_year = SECONDS_PER_YEAR; // 365 days in seconds
    -
    -    let mut total_fees_per_asset: Map<Address, i128> = Map::new(&e);
    -
    -    // Iterate over each asset in the vault
    -    for (asset_address, amount) in total_managed_funds.iter() {
    -        // Fetch current managed funds for each asset
    -        let current_asset_value = amount;
    -
    -        // Calculate the fee for this asset based on the fee rate and time elapsed
    -        let asset_fee = (current_asset_value * fee_rate as i128 * time_elapsed as i128) / (seconds_per_year * MAX_BPS);
    -
    -        total_fees_per_asset.set(asset_address.clone(), asset_fee);
    -
    -    }
    -
    -    let total_fees_in_dftokens = calculate_dftokens_from_asset_amounts(e, total_fees_per_asset)?;
    -
    -    Ok(total_fees_in_dftokens)
    +    Ok(fees)
     }
     
    -pub fn collect_fees(e: &Env) -> Result<(), ContractError> {
    +/// Collects and mints fees in dfTokens, distributing them to the appropriate fee receivers.
    +pub fn collect_fees(e: &Env) -> Result<(), ContractError> {
         let current_timestamp = e.ledger().timestamp();
    -    let last_fee_assessment = get_last_fee_assesment(e); 
    +    // If last_fee_assesment was not set yet, this will be set to the current timestamp
    +    let last_fee_assessment = get_last_fee_assesment(e);
    +
    +    // Update the last fee assessment timestamp
    +    // Set it now to Avoid Reentrancy Attack
    +    set_last_fee_assesment(e, &current_timestamp);
     
         let time_elapsed = current_timestamp.checked_sub(last_fee_assessment).unwrap();
     
    -    if time_elapsed == 0 {
    +    // If no time has passed since the last fee assessment, no fees are collected
    +    if time_elapsed == 0 {
             return Ok(());
         }
     
    -    let fee_rate = fetch_fee_rate(e);
    +    // Fetch the individual fees for DeFindex and Vault, then calculate the total rate
    +    let defindex_fee = fetch_defindex_fee(e);
    +    let vault_fee = get_vault_fee(e);
    +    let total_fee_rate = defindex_fee.checked_add(vault_fee).unwrap();
     
    -    let total_fees = calculate_fees(e, time_elapsed, fee_rate)?;
    +    // Calculate the total fees in dfTokens based on the combined fee rate
    +    let total_fees = calculate_fees(e, time_elapsed, total_fee_rate)?;
     
    -    // Mint the total fees as dfTokens
    -    mint_fees(e, total_fees)?;
    +    // Mint and distribute the fees proportionally
    +    mint_fees(e, total_fees, defindex_fee, vault_fee)?;
     
    -    // Update the last fee assessment timestamp
    -    set_last_fee_assesment(e, &current_timestamp);
     
         Ok(())
     }
     
    -fn mint_fees(e: &Env, total_fees: i128) -> Result<(), ContractError> {
    +/// Mints dfTokens for fees and distributes them to the vault fee receiver and DeFindex receiver.
    +fn mint_fees(e: &Env, total_fees: i128, defindex_fee: u32, vault_fee: u32) -> Result<(), ContractError> {
         let access_control = AccessControl::new(&e);
    -    
    -    let vault_fee_receiver = access_control.get_fee_receiver()?;
    -    let defindex_receiver = get_defindex_receiver(e);
    -
    -    let vault_share_bps = get_vault_share(e);
     
    -    let vault_shares = (total_fees * vault_share_bps as i128) / MAX_BPS;
    -    
    -    let defindex_shares = total_fees - vault_shares;
    -
    -    internal_mint(e.clone(), vault_fee_receiver.clone(), vault_shares);
    -    internal_mint(e.clone(), defindex_receiver.clone(), defindex_shares);
    -
    -    events::emit_fees_minted_event(e, defindex_receiver, defindex_shares, vault_fee_receiver, vault_shares);
    +    let vault_fee_receiver = access_control.get_fee_receiver()?;
    +    let defindex_protocol_receiver = get_defindex_protocol_fee_receiver(e);
    +
    +    // Calculate shares for each receiver based on their fee proportion
    +    let total_fee_bps = defindex_fee as i128 + vault_fee as i128;
    +    let defindex_shares = (total_fees * defindex_fee as i128) / total_fee_bps;
    +    let vault_shares = total_fees - defindex_shares;
    +
    +    // Mint shares for both receivers
    +    internal_mint(e.clone(), vault_fee_receiver.clone(), vault_shares);
    +    internal_mint(
    +        e.clone(),
    +        defindex_protocol_receiver.clone(),
    +        defindex_shares,
    +    );
    +
    +    events::emit_fees_minted_event(
    +        e,
    +        defindex_protocol_receiver,
    +        defindex_shares,
    +        vault_fee_receiver,
    +        vault_shares,
    +    );
         Ok(())
    -}
    \ No newline at end of file +} +
    \ No newline at end of file diff --git a/apps/rust_docs/src/defindex_vault/funds.rs.html b/apps/rust_docs/src/defindex_vault/funds.rs.html index 116150e4..ca92d951 100644 --- a/apps/rust_docs/src/defindex_vault/funds.rs.html +++ b/apps/rust_docs/src/defindex_vault/funds.rs.html @@ -1,4 +1,4 @@ -funds.rs - source
    1
    +funds.rs - source
    1
     2
     3
     4
    @@ -110,35 +110,41 @@
     110
     111
     112
    +113
    +114
    +115
    +116
    +117
    +118
    +119
     
    use soroban_sdk::token::TokenClient;
    -use soroban_sdk::{Address, Env, Map};
    +use soroban_sdk::{Address, Env, Map, Vec};
     
    -use crate::models::AssetAllocation;
    +use common::models::AssetStrategySet;
    +use crate::models::{StrategyAllocation, CurrentAssetInvestmentAllocation};
     use crate::storage::get_assets;
     use crate::strategies::get_strategy_client;
     
    -// Funds for AssetAllocation 
    -
    -/// Fetches the idle funds for a given asset. Idle funds refer to the balance of the asset
    +/// Fetches the idle funds for a given asset. Idle funds refer to the balance of the asset
     /// that is currently not invested in any strategies.
    -/// 
    +///
     /// # Arguments
     /// * `e` - The current environment instance.
     /// * `asset` - The asset for which idle funds are being fetched.
    -/// 
    +///
     /// # Returns
     /// * The idle balance (i128) of the asset in the current contract address.
    -fn fetch_idle_funds_for_asset(e: &Env, asset: &AssetAllocation) -> i128 {
    -    TokenClient::new(e, &asset.address).balance(&e.current_contract_address())
    +pub fn fetch_idle_funds_for_asset(e: &Env, asset: &Address) -> i128 {
    +    TokenClient::new(e, &asset).balance(&e.current_contract_address())
     }
     
    -/// Fetches the total funds that are invested for a given asset. 
    +/// Fetches the total funds that are invested for a given asset.
     /// It iterates through all the strategies associated with the asset and sums their balances.
    -/// 
    +///
     /// # Arguments
     /// * `e` - The current environment instance.
     /// * `asset` - The asset for which invested funds are being fetched.
    -/// 
    +///
     /// # Returns
     /// * The total invested balance (i128) of the asset across all strategies.
     pub fn fetch_invested_funds_for_strategy(e: &Env, strategy_address: &Address) -> i128 {
    @@ -146,79 +152,87 @@
         strategy_client.balance(&e.current_contract_address())
     }
     
    -/// Fetches the total funds that are invested for a given asset. 
    -/// It iterates through all the strategies associated with the asset and sums their balances.
    -/// 
    -/// # Arguments
    -/// * `e` - The current environment instance.
    -/// * `asset` - The asset for which invested funds are being fetched.
    -/// 
    -/// # Returns
    -/// * The total invested balance (i128) of the asset across all strategies.
    -pub fn fetch_invested_funds_for_asset(e: &Env, asset: &AssetAllocation) -> i128 {
    +
    +// return total invested funds but also a vec of StrategyAllocation
    +pub fn fetch_invested_funds_for_asset(e: &Env, asset: &AssetStrategySet) -> (i128, Vec<StrategyAllocation>){
         let mut invested_funds = 0;
    +    let mut strategy_allocations: Vec<StrategyAllocation> = Vec::new(e);
         for strategy in asset.strategies.iter() {
    -        invested_funds += fetch_invested_funds_for_strategy(e, &strategy.address);
    +        let strategy_balance = fetch_invested_funds_for_strategy(e, &strategy.address);
    +        invested_funds += strategy_balance;
    +        strategy_allocations.push_back(StrategyAllocation {
    +            strategy_address: strategy.address.clone(),
    +            amount: strategy_balance,
    +        });
         }
    -    invested_funds
    +    (invested_funds, strategy_allocations)
     }
     
     
    -// Pub functions
    -
    -/// Fetches the current idle funds for all assets managed by the contract. 
    +/// Fetches the current idle funds for all assets managed by the contract.
     /// It returns a map where the key is the asset's address and the value is the idle balance.
    -/// 
    +///
     /// # Arguments
     /// * `e` - The current environment instance.
    -/// 
    +///
     /// # Returns
     /// * A map where each entry represents an asset's address and its corresponding idle balance.
     pub fn fetch_current_idle_funds(e: &Env) -> Map<Address, i128> {
         let assets = get_assets(e);
         let mut map: Map<Address, i128> = Map::new(e);
         for asset in assets {
    -        map.set(asset.address.clone(), fetch_idle_funds_for_asset(e, &asset));
    +        map.set(asset.address.clone(), fetch_idle_funds_for_asset(e, &asset.address));
         }
         map
     }
     
    -/// Fetches the current invested funds for all assets managed by the contract. 
    +/// Fetches the current invested funds for all assets managed by the contract.
     /// It returns a map where the key is the asset's address and the value is the invested balance.
    -/// 
    +///
     /// # Arguments
     /// * `e` - The current environment instance.
    -/// 
    +///
     /// # Returns
     /// * A map where each entry represents an asset's address and its corresponding invested balance.
     pub fn fetch_current_invested_funds(e: &Env) -> Map<Address, i128> {
         let assets = get_assets(e);
         let mut map: Map<Address, i128> = Map::new(e);
         for asset in assets {
    +        let (invested_funds, _) = fetch_invested_funds_for_asset(e, &asset);
             map.set(
                 asset.address.clone(),
    -            fetch_invested_funds_for_asset(e, &asset),
    +            invested_funds
             );
         }
         map
     }
     
     /// Fetches the total managed funds for all assets. This includes both idle and invested funds.
    -/// It returns a map where the key is the asset's address and the value is the total managed balance 
    +/// It returns a map where the key is the asset's address and the value is the total managed balance
     /// (idle + invested). With this map we can calculate the current managed funds ratio.
    -/// 
    +///
     /// # Arguments
     /// * `e` - The current environment instance.
    -/// 
    +///
     /// # Returns
     /// * A map where each entry represents an asset's address and its total managed balance.
    -pub fn fetch_total_managed_funds(e: &Env) -> Map<Address, i128> {
    +pub fn fetch_total_managed_funds(e: &Env) -> Map<Address, CurrentAssetInvestmentAllocation> {
         let assets = get_assets(e);
    -    let mut map: Map<Address, i128> = Map::new(e);
    +    let mut map: Map<Address, CurrentAssetInvestmentAllocation> = Map::new(e);
         for asset in assets {
    -        let idle_funds = fetch_idle_funds_for_asset(e, &asset);
    -        let invested_funds = fetch_invested_funds_for_asset(e, &asset);
    -        map.set(asset.address.clone(), idle_funds + invested_funds);
    +        let idle_amount = fetch_idle_funds_for_asset(e, &asset.address);
    +        let (invested_amount, strategy_allocations) = fetch_invested_funds_for_asset(e, &asset);
    +        let total_amount = idle_amount + invested_amount;
    +        map.set(
    +            asset.address.clone(),
    +            CurrentAssetInvestmentAllocation {
    +                asset: asset.address.clone(),
    +                total_amount,
    +                idle_amount,
    +                invested_amount,
    +                strategy_allocations,
    +            },
    +        );
         }
         map
     }
    diff --git a/apps/rust_docs/src/defindex_vault/interface.rs.html b/apps/rust_docs/src/defindex_vault/interface.rs.html
    index 085866c5..4a7d8897 100644
    --- a/apps/rust_docs/src/defindex_vault/interface.rs.html
    +++ b/apps/rust_docs/src/defindex_vault/interface.rs.html
    @@ -1,4 +1,4 @@
    -interface.rs - source
    1
    +interface.rs - source
    1
     2
     3
     4
    @@ -244,63 +244,175 @@
     244
     245
     246
    -
    use soroban_sdk::{Address, Env, Map, Vec};
    +247
    +248
    +249
    +250
    +251
    +252
    +253
    +254
    +255
    +256
    +257
    +258
    +259
    +260
    +261
    +262
    +263
    +264
    +265
    +266
    +267
    +268
    +269
    +270
    +271
    +272
    +273
    +274
    +275
    +276
    +277
    +278
    +279
    +280
    +281
    +282
    +283
    +284
    +285
    +286
    +287
    +288
    +289
    +290
    +291
    +292
    +293
    +294
    +295
    +296
    +297
    +298
    +299
    +300
    +301
    +302
    +303
    +304
    +305
    +306
    +307
    +308
    +309
    +310
    +311
    +312
    +313
    +314
    +315
    +316
    +317
    +318
    +319
    +320
    +321
    +322
    +323
    +324
    +325
    +326
    +327
    +328
    +329
    +330
    +331
    +332
    +
    use soroban_sdk::{Address, Env, Map, String, Vec};
     
     use crate::{
    -    models::{AssetAllocation, Investment},
    +    models::{Instruction, AssetInvestmentAllocation, CurrentAssetInvestmentAllocation},
         ContractError,
     };
    +use common::models::AssetStrategySet;
     
     pub trait VaultTrait {
    -
         /// Initializes the DeFindex Vault contract with the required parameters.
         ///
    -    /// This function sets the roles for emergency manager, fee receiver, and manager.
    +    /// This function sets the roles for manager, emergency manager, vault fee receiver, and manager.
         /// It also stores the list of assets to be managed by the vault, including strategies for each asset.
    -    /// 
    -    /// # Arguments:
    -    /// * `e` - The environment.
    -    /// * `assets` - A vector of `AssetAllocation` structs representing the assets and their associated strategies.
    -    /// * `manager` - The address responsible for managing the vault.
    -    /// * `emergency_manager` - The address with emergency control over the vault.
    -    /// * `fee_receiver` - The address that will receive fees from the vault.
    -    /// * `vault_share` - The percentage of the vault's fees that will be sent to the DeFindex receiver. in BPS.
    -    /// * `defindex_receiver` - The address that will receive fees for DeFindex from the vault.
    -    /// * `factory` - The address of the factory that deployed the vault.
         ///
    -    /// # Returns:
    -    /// * `Result<(), ContractError>` - Ok if successful, otherwise returns a ContractError.
    +    /// # Arguments
    +    /// - `assets`: List of asset allocations for the vault, including strategies associated with each asset.
    +    /// - `manager`: Primary vault manager with permissions for vault control.
    +    /// - `emergency_manager`: Address with emergency access for emergency control over the vault.
    +    /// - `vault_fee_receiver`: Address designated to receive the vault fee receiver's portion of management fees.
    +    /// - `vault_fee`: Vault-specific fee percentage in basis points (typically set at 0-2% APR).
    +    /// - `defindex_protocol_receiver`: Address receiving DeFindex’s protocol-wide fee in basis points (0.5% APR).
    +    /// - `factory`: Factory contract address for deployment linkage.
    +    /// - `vault_name`: Name of the vault token to be displayed in metadata.
    +    /// - `vault_symbol`: Symbol representing the vault’s token.
    +    ///
    +    /// # Returns
    +    /// - `Result<(), ContractError>`: Returns `Ok(())` if initialization succeeds, or a `ContractError` if
    +    ///   any setup fails (e.g., strategy mismatch with asset).
    +    ///
    +    /// # Errors
    +    /// - `ContractError::AlreadyInitialized`: If the vault has already been initialized.
    +    /// - `ContractError::StrategyDoesNotSupportAsset`: If a strategy within an asset does not support the asset’s contract.
    +    ///
         fn initialize(
             e: Env,
    -        assets: Vec<AssetAllocation>,
    +        assets: Vec<AssetStrategySet>,
             manager: Address,
             emergency_manager: Address,
    -        fee_receiver: Address,
    -        vault_share: u32,
    -        defindex_receiver: Address,
    +        vault_fee_receiver: Address,
    +        vault_fee: u32,
    +        defindex_protocol_receiver: Address,
             factory: Address,
    +        vault_name: String,
    +        vault_symbol: String,
         ) -> Result<(), ContractError>;
     
    -    /// Handles deposits into the DeFindex Vault.
    +    /// Handles user deposits into the DeFindex Vault.
         ///
    -    /// This function transfers the desired amounts of each asset into the vault, distributes the assets
    -    /// across the strategies according to the vault's ratios, and mints dfTokens representing the user's
    -    /// share in the vault.
    +    /// This function processes a deposit by transferring each specified asset amount from the user's address to
    +    /// the vault, allocating assets according to the vault's defined strategy ratios, and minting dfTokens that 
    +    /// represent the user's proportional share in the vault. The `amounts_desired` and `amounts_min` vectors should 
    +    /// align with the vault's asset order to ensure correct allocation.
         ///
    -    /// # Arguments:
    -    /// * `e` - The environment.
    -    /// * `amounts_desired` - A vector of the amounts the user wishes to deposit for each asset.
    -    /// * `amounts_min` - A vector of minimum amounts required for the deposit to proceed.
    +    /// # Parameters
    +    /// * `e` - The current environment reference (`Env`), for access to the contract state and utilities.
    +    /// * `amounts_desired` - A vector specifying the user's intended deposit amounts for each asset.
    +    /// * `amounts_min` - A vector of minimum deposit amounts required for the transaction to proceed.
         /// * `from` - The address of the user making the deposit.
         ///
    -    /// # Returns:
    -    /// * `Result<(), ContractError>` - Ok if successful, otherwise returns a ContractError.
    +    /// # Returns
    +    /// * `Result<(Vec<i128>, i128), ContractError>` - Returns the actual deposited `amounts` and `shares_to_mint` if successful,
    +    ///   otherwise a `ContractError`.
    +    ///
    +    /// # Function Flow
    +    /// 1. **Fee Collection**: Collects accrued fees before processing the deposit.
    +    /// 2. **Validation**: Checks that the lengths of `amounts_desired` and `amounts_min` match the vault's assets.
    +    /// 3. **Share Calculation**: Calculates `shares_to_mint` based on the vault's total managed funds and the deposit amount.
    +    /// 4. **Asset Transfer**: Transfers each specified amount from the user’s address to the vault as idle funds.
    +    /// 5. **dfToken Minting**: Mints new dfTokens for the user to represent their ownership in the vault.
    +    ///
    +    /// # Notes
    +    /// - For the first deposit, if the vault has only one asset, shares are calculated directly based on the deposit amount.
    +    /// - For multiple assets, the function delegates to `calculate_deposit_amounts_and_shares_to_mint`
    +    ///   for precise share computation.
    +    /// - An event is emitted to log the deposit, including the actual deposited amounts and minted shares.
    +    ///
         fn deposit(
             e: Env,
             amounts_desired: Vec<i128>,
             amounts_min: Vec<i128>,
             from: Address,
    -    ) -> Result<(), ContractError>;
    +        invest: bool,
    +    ) -> Result<(Vec<i128>, i128), ContractError>;
     
         /// Withdraws assets from the DeFindex Vault by burning dfTokens.
         ///
    @@ -330,7 +442,11 @@
         ///
         /// # Returns:
         /// * `Result<(), ContractError>` - Ok if successful, otherwise returns a ContractError.
    -    fn emergency_withdraw(e: Env, strategy_address: Address, caller: Address) -> Result<(), ContractError>;
    +    fn emergency_withdraw(
    +        e: Env,
    +        strategy_address: Address,
    +        caller: Address,
    +    ) -> Result<(), ContractError>;
     
         /// Pauses a strategy to prevent it from being used in the vault.
         ///
    @@ -344,7 +460,11 @@
         ///
         /// # Returns:
         /// * `Result<(), ContractError>` - Ok if successful, otherwise returns a ContractError.
    -    fn pause_strategy(e: Env, strategy_address: Address, caller: Address) -> Result<(), ContractError>;
    +    fn pause_strategy(
    +        e: Env,
    +        strategy_address: Address,
    +        caller: Address,
    +    ) -> Result<(), ContractError>;
     
         /// Unpauses a previously paused strategy.
         ///
    @@ -358,7 +478,11 @@
         ///
         /// # Returns:
         /// * `Result<(), ContractError>` - Ok if successful, otherwise returns a ContractError.
    -    fn unpause_strategy(e: Env, strategy_address: Address, caller: Address) -> Result<(), ContractError>;
    +    fn unpause_strategy(
    +        e: Env,
    +        strategy_address: Address,
    +        caller: Address,
    +    ) -> Result<(), ContractError>;
     
         /// Retrieves the list of assets managed by the DeFindex Vault.
         ///
    @@ -366,8 +490,8 @@
         /// * `e` - The environment.
         ///
         /// # Returns:
    -    /// * `Vec<AssetAllocation>` - A vector of `AssetAllocation` structs representing the assets managed by the vault.
    -    fn get_assets(e: Env) -> Vec<AssetAllocation>;
    +    /// * `Vec<AssetStrategySet>` - A vector of `AssetStrategySet` structs representing the assets managed by the vault.
    +    fn get_assets(e: Env) -> Vec<AssetStrategySet>;
     
         /// Returns the total managed funds of the vault, including both invested and idle funds.
         ///
    @@ -379,8 +503,8 @@
         ///
         /// # Returns:
         /// * `Map<Address, i128>` - A map of asset addresses to their total managed amounts.
    -    fn fetch_total_managed_funds(e: &Env) -> Map<Address, i128>;
    -    
    +    fn fetch_total_managed_funds(e: &Env) -> Map<Address, CurrentAssetInvestmentAllocation>;
    +
         /// Returns the current invested funds, representing the total assets allocated to strategies.
         ///
         /// This function provides a map where the key is the asset address and the value is the total amount
    @@ -405,10 +529,28 @@
         /// * `Map<Address, i128>` - A map of asset addresses to their total idle amounts.
         fn fetch_current_idle_funds(e: &Env) -> Map<Address, i128>;
     
    +
    +    // Calculates the corresponding amounts of each asset per a given number of vault shares.
    +    /// This function extends the contract's time-to-live and calculates how much of each asset corresponds 
    +    /// per the provided number of vault shares (`vault_shares`). It provides proportional allocations for each asset 
    +    /// in the vault relative to the specified shares.
    +    ///
    +    /// # Arguments
    +    /// * `e` - The current environment reference.
    +    /// * `vault_shares` - The number of vault shares for which the corresponding asset amounts are calculated.
    +    ///
    +    /// # Returns
    +    /// * `Map<Address, i128>` - A map containing each asset address and its corresponding proportional amount.
    +    fn get_asset_amounts_per_shares(e: Env, vault_shares: i128) -> Result<Map<Address, i128>, ContractError>;
    +    
         // TODO: DELETE THIS, USED FOR TESTING
         /// Temporary method for testing purposes.
    -    fn get_asset_amounts_for_dftokens(e: Env, df_token: i128) -> Map<Address, i128>;
    +    // fn get_asset_amounts_for_dftokens(e: Env, df_token: i128) -> Map<Address, i128>;
     
    +    fn get_fees(e: Env) -> (u32, u32);
    +
    +    /// Collects the fees from the vault and transfers them to the fee receiver addresses. 
    +    fn collect_fees(e: Env) -> Result<(), ContractError>;
     }
     
     pub trait AdminInterfaceTrait {
    @@ -419,7 +561,7 @@
         /// # Arguments:
         /// * `e` - The environment.
         /// * `caller` - The address initiating the change (must be the manager or emergency manager).
    -    /// * `fee_receiver` - The new fee receiver address.
    +    /// * `vault_fee_receiver` - The new fee receiver address.
         ///
         /// # Returns:
         /// * `()` - No return value.
    @@ -478,15 +620,46 @@
     }
     
     pub trait VaultManagementTrait {
    +    /// Executes the investment of the vault's idle funds based on the specified asset allocations.
    +    /// This function allows partial investments by providing an optional allocation for each asset,
    +    /// and it ensures proper authorization and validation checks before proceeding with investments.
    +    ///
    +    /// # Arguments
    +    /// * `e` - The current environment reference.
    +    /// * `asset_investments` - A vector of optional `AssetInvestmentAllocation` structures, where each element 
    +    ///   represents an allocation for a specific asset. The vector must match the number of vault assets in length.
    +    ///
    +    /// # Returns
    +    /// * `Result<(), ContractError>` - Returns `Ok(())` if the investments are successful or a `ContractError`
    +    ///   if any issue occurs during validation or execution.
    +    ///
    +    /// # Function Flow
    +    /// 1. **Extend Instance TTL**: Extends the contract instance's time-to-live to keep the instance active.
    +    /// 2. **Check Initialization**: Verifies that the vault is properly initialized before proceeding.
    +    /// 3. **Access Control**: Ensures the caller has the `Manager` role required to initiate investments.
    +    /// 4. **Asset Count Validation**: Verifies that the length of the `asset_investments` vector matches
    +    ///    the number of assets managed by the vault. If they don't match, a `WrongInvestmentLength` error is returned.
    +    /// 5. **Investment Execution**: Calls the `check_and_execute_investments` function to perform the investment
    +    ///    after validating the inputs and ensuring correct execution flows for each asset allocation.
    +    ///
    +    /// # Errors
    +    /// * Returns `ContractError::WrongInvestmentLength` if the length of `asset_investments` does not match the vault assets.
    +    /// * Returns `ContractError` if access control validation fails or if investment execution encounters an issue.
    +    ///
    +    /// # Security
    +    /// - Only addresses with the `Manager` role can call this function, ensuring restricted access to managing investments.
    +    fn invest(e: Env, 
    +        asset_investments: Vec<Option<AssetInvestmentAllocation>>
    +    ) -> Result<(), ContractError>;
     
    -    /// Invests the vault's idle funds into the specified strategies.
    -    /// 
    +    /// Rebalances the vault by executing a series of instructions.
    +    ///
         /// # Arguments:
         /// * `e` - The environment.
    -    /// * `investment` - A vector of `Investment` structs representing the amount to invest in each strategy.
    -    /// * `caller` - The address of the caller.
    -    /// 
    +    /// * `instructions` - A vector of `Instruction` structs representing actions (withdraw, invest, swap, zapper) to be taken.
    +    ///
         /// # Returns:
         /// * `Result<(), ContractError>` - Ok if successful, otherwise returns a ContractError.
    -    fn invest(e: Env, investment: Vec<Investment>) -> Result<(), ContractError>;
    -}
    \ No newline at end of file +
    fn rebalance(e: Env, instructions: Vec<Instruction>) -> Result<(), ContractError>; +} +
    \ No newline at end of file diff --git a/apps/rust_docs/src/defindex_vault/investment.rs.html b/apps/rust_docs/src/defindex_vault/investment.rs.html index 3312e730..51af785f 100644 --- a/apps/rust_docs/src/defindex_vault/investment.rs.html +++ b/apps/rust_docs/src/defindex_vault/investment.rs.html @@ -1,4 +1,4 @@ -investment.rs - source
    1
    +investment.rs - source
    1
     2
     3
     4
    @@ -42,47 +42,153 @@
     42
     43
     44
    -
    use soroban_sdk::{Address, Env, Map, Vec};
    +45
    +46
    +47
    +48
    +49
    +50
    +51
    +52
    +53
    +54
    +55
    +56
    +57
    +58
    +59
    +60
    +61
    +62
    +63
    +64
    +65
    +66
    +67
    +68
    +69
    +70
    +71
    +72
    +73
    +74
    +75
    +76
    +77
    +78
    +79
    +80
    +81
    +82
    +83
    +84
    +85
    +86
    +87
    +88
    +89
    +90
    +91
    +92
    +93
    +94
    +95
    +96
    +97
    +
    use soroban_sdk::{Env, Vec, panic_with_error};
     
    -use crate::{models::Investment, strategies::{get_strategy_asset, get_strategy_client}, utils::check_nonnegative_amount, ContractError};
    +use crate::{
    +    models::AssetInvestmentAllocation,
    +    strategies::invest_in_strategy,
    +    utils::{check_nonnegative_amount},
    +    ContractError,
    +};
    +use common::models::AssetStrategySet;
     
    -pub fn prepare_investment(e: &Env, investments: Vec<Investment>, idle_funds: Map<Address, i128>) -> Result<Map<Address, i128>, ContractError> {
    -  let mut total_investment_per_asset: Map<Address, i128> = Map::new(e);
    -  
    -  for investment in investments.iter() {
    -      let strategy_address = &investment.strategy;
    -      let amount_to_invest = investment.amount;
    -      check_nonnegative_amount(amount_to_invest.clone())?;
    -  
    -      // Find the corresponding asset for the strategy
    -      let asset = get_strategy_asset(&e, strategy_address)?;
    -  
    -      // Track investment per asset
    -      let current_investment = total_investment_per_asset
    -          .get(asset.address.clone())
    -          .unwrap_or(0);
    -      let updated_investment = current_investment.checked_add(amount_to_invest).ok_or(ContractError::Overflow)?;
    -  
    -      total_investment_per_asset.set(asset.address.clone(), updated_investment);
    -  
    -      // Check if total investment exceeds idle funds
    -      let idle_balance = idle_funds.get(asset.address.clone()).unwrap_or(0);
    -      if updated_investment > idle_balance {
    -          return Err(ContractError::NotEnoughIdleFunds);
    -      }
    -  }
    -  
    -  Ok(total_investment_per_asset)
    -}
    +/// Checks and executes the investments for each asset based on provided allocations.
    +/// The function iterates through the specified assets and asset investments to ensure validity 
    +/// and executes investments accordingly.
    +///
    +/// # Arguments
    +/// * `e` - The current environment reference.
    +/// * `assets` - A vector of `AssetStrategySet` that holds information about assets and their associated strategies.
    +/// * `asset_investments` - A vector of optional investment allocations for each asset.
    +///s
    +/// # Returns
    +/// * `Result<(), ContractError>` - Returns `Ok(())` if all investments are successful or an appropriate `ContractError` if any issue is encountered.
    +///
    +/// # Function Flow
    +/// 1. **Iterate Over Asset Investments**: Loops through each asset investment allocation.
    +/// 2. **Validation**:
    +///    - **Asset Address Check**: Ensures that the asset's address matches the expected address in the allocation.
    +///    - **Strategy Length Check**: Verifies that the number of strategies matches between the asset and the corresponding allocation.
    +///    - **Note**: The total intended investment check has been removed as the subsequent operations inherently perform the same validation.
    +/// 3. **Process Strategy Investments**:
    +///    - For each strategy within an asset:
    +///      - **Non-Negative Amount Check**: Validates that the investment amount is non-negative.
    +///      - **Strategy Active Check**: Ensures that the strategy is not paused before proceeding with the investment.
    +///      - **Execute Investment**: Calls the `invest_in_strategy` fuction if all checks pass.
    +///
    +/// # Errors
    +/// * Returns `ContractError::WrongAssetAddress` if an asset's address does not match the expected address.
    +/// * Returns `ContractError::WrongStrategiesLength` if the number of strategies in the asset and allocation do not match.
    +/// * Returns `ContractError::StrategyPaused` if an investment targets a paused strategy.
    +///
    +pub fn check_and_execute_investments(
    +    e: Env, 
    +    assets: Vec<AssetStrategySet>,
    +    asset_investments: Vec<Option<AssetInvestmentAllocation>>
    +) -> Result<(), ContractError> {
     
    -pub fn execute_investment(e: &Env, investments: Vec<Investment>) -> Result<(), ContractError> {
    -  for investment in investments.iter() {
    -      let strategy_address = &investment.strategy;
    -      let amount_to_invest = investment.amount;
    +    // Iterate over each asset investment allocation
    +    for (i, asset_investment_opt) in asset_investments.iter().enumerate() {
    +        if let Some(asset_investment) = asset_investment_opt { // Proceed only if allocation is defined
    +            let asset = assets.get(i as u32).unwrap();
     
    -      let strategy_client = get_strategy_client(&e, strategy_address.clone());
    -      strategy_client.deposit(&amount_to_invest, &e.current_contract_address());
    -  }
    +            // Verify the asset address matches the specified investment allocation
    +            if asset.address != asset_investment.asset {
    +                panic_with_error!(&e, ContractError::WrongAssetAddress);
    +            }
     
    -  Ok(())
    +            // Ensure the number of strategies aligns between asset and investment
    +            if asset.strategies.len() != asset_investment.strategy_allocations.len() {
    +                panic_with_error!(&e, ContractError::WrongStrategiesLength);
    +            }
    +
    +            // NOTE: We can avoid this check as it if total idle funds exceed funds to invest, this will fail
    +            // when trying to transfer
    +
    +            // // Calculate total intended investment for this asset
    +            // let total_asset_investment: i128 = asset_investment.investments.iter()
    +            //     .filter_map(|strategy| strategy.as_ref().map(|s| s.amount.unwrap_or(0)))
    +            //     .sum();
    +
    +            // // Verify total intended investment does not exceed idle funds for this asset
    +            // if total_asset_investment > fetch_idle_funds_for_asset(&e, &asset_investment.asset) {
    +            //     panic_with_error!(&e, ContractError::InsufficientIdleFunds);
    +            // }
    +
    +            // Process each defined strategy investment for the current asset
    +            for (j, strategy_investment_opt) in asset_investment.strategy_allocations.iter().enumerate() {
    +                if let Some(strategy_investment) = strategy_investment_opt {
    +                    // Validate amount is non-negative
    +                    check_nonnegative_amount(strategy_investment.amount)?;
    +
    +                    // Ensure the strategy is active before proceeding
    +                    let strategy = asset.strategies.get(j as u32).unwrap();
    +                    if strategy_investment.amount > 0 && strategy.paused {
    +                        panic_with_error!(&e, ContractError::StrategyPaused);
    +                    }
    +
    +                    // Execute the investment if checks pass
    +                    invest_in_strategy(
    +                        &e,
    +                        &asset.address,
    +                        &strategy.address, 
    +                        &strategy_investment.amount)?;
    +                }
    +            }
    +        }
    +    }
    +    Ok(())
     }
    \ No newline at end of file diff --git a/apps/rust_docs/src/defindex_vault/lib.rs.html b/apps/rust_docs/src/defindex_vault/lib.rs.html index be0503aa..201be0d2 100644 --- a/apps/rust_docs/src/defindex_vault/lib.rs.html +++ b/apps/rust_docs/src/defindex_vault/lib.rs.html @@ -1,4 +1,4 @@ -lib.rs - source
    1
    +lib.rs - source
    1
     2
     3
     4
    @@ -575,16 +575,192 @@
     575
     576
     577
    +578
    +579
    +580
    +581
    +582
    +583
    +584
    +585
    +586
    +587
    +588
    +589
    +590
    +591
    +592
    +593
    +594
    +595
    +596
    +597
    +598
    +599
    +600
    +601
    +602
    +603
    +604
    +605
    +606
    +607
    +608
    +609
    +610
    +611
    +612
    +613
    +614
    +615
    +616
    +617
    +618
    +619
    +620
    +621
    +622
    +623
    +624
    +625
    +626
    +627
    +628
    +629
    +630
    +631
    +632
    +633
    +634
    +635
    +636
    +637
    +638
    +639
    +640
    +641
    +642
    +643
    +644
    +645
    +646
    +647
    +648
    +649
    +650
    +651
    +652
    +653
    +654
    +655
    +656
    +657
    +658
    +659
    +660
    +661
    +662
    +663
    +664
    +665
    +666
    +667
    +668
    +669
    +670
    +671
    +672
    +673
    +674
    +675
    +676
    +677
    +678
    +679
    +680
    +681
    +682
    +683
    +684
    +685
    +686
    +687
    +688
    +689
    +690
    +691
    +692
    +693
    +694
    +695
    +696
    +697
    +698
    +699
    +700
    +701
    +702
    +703
    +704
    +705
    +706
    +707
    +708
    +709
    +710
    +711
    +712
    +713
    +714
    +715
    +716
    +717
    +718
    +719
    +720
    +721
    +722
    +723
    +724
    +725
    +726
    +727
    +728
    +729
    +730
    +731
    +732
    +733
    +734
    +735
    +736
    +737
    +738
    +739
    +740
    +741
    +742
    +743
    +744
    +745
    +746
    +747
    +748
    +749
    +750
     
    #![no_std]
    -use fee::collect_fees;
    -use investment::{execute_investment, prepare_investment};
    +use deposit::{generate_and_execute_investments, process_deposit};
     use soroban_sdk::{
    -    contract, contractimpl, panic_with_error, token::{TokenClient, TokenInterface}, Address, Env, Map, String, Vec
    +    contract, contractimpl, panic_with_error,
    +    token::{TokenClient, TokenInterface},
    +    Address, Env, Map, String, Vec,
     };
     use soroban_token_sdk::metadata::TokenMetadata;
     
     mod access;
    +mod aggregator;
     mod constants;
    +mod deposit;
     mod error;
     mod events;
     mod fee;
    @@ -599,18 +775,37 @@
     mod utils;
     
     use access::{AccessControl, AccessControlTrait, RolesDataKey};
    -use funds::{fetch_current_idle_funds, fetch_current_invested_funds, fetch_total_managed_funds};
    -use interface::{AdminInterfaceTrait, VaultTrait, VaultManagementTrait};
    -use models::{AssetAllocation, Investment};
    +use aggregator::{internal_swap_exact_tokens_for_tokens, internal_swap_tokens_for_exact_tokens};
    +use fee::{collect_fees, fetch_defindex_fee};
    +use funds::{fetch_current_idle_funds, fetch_current_invested_funds, fetch_total_managed_funds}; 
    +use interface::{AdminInterfaceTrait, VaultManagementTrait, VaultTrait};
    +use investment::check_and_execute_investments;
    +use models::{
    +    Instruction, OptionalSwapDetailsExactIn,
    +    OptionalSwapDetailsExactOut, CurrentAssetInvestmentAllocation,
    +    ActionType, AssetInvestmentAllocation,
    +};
     use storage::{
    -    get_assets, set_asset, set_defindex_receiver, set_factory, set_last_fee_assesment, set_total_assets, set_vault_share
    +    extend_instance_ttl, get_assets, get_vault_fee, set_asset, set_defindex_protocol_fee_receiver,
    +    set_factory, set_total_assets, set_vault_fee,
    +};
    +use strategies::{
    +    get_strategy_asset, get_strategy_client,
    +    get_strategy_struct, invest_in_strategy, pause_strategy, unpause_strategy,
    +    withdraw_from_strategy,
     };
    -use strategies::{get_asset_allocation_from_address, get_strategy_asset, get_strategy_client, get_strategy_struct, pause_strategy, unpause_strategy};
    -use token::{internal_mint, internal_burn, write_metadata, VaultToken};
    +use token::{internal_burn, write_metadata, VaultToken};
     use utils::{
    -    calculate_asset_amounts_for_dftokens, calculate_deposit_amounts_and_shares_to_mint, calculate_withdrawal_amounts, check_initialized, check_nonnegative_amount
    +    calculate_asset_amounts_per_vault_shares,
    +    check_initialized,
    +    check_nonnegative_amount,
     };
     
    +use common::models::AssetStrategySet;
    +use defindex_strategy_core::DeFindexStrategyClient;
    +
    +static MINIMUM_LIQUIDITY: i128 = 1000;
    +
     pub use error::ContractError;
     
     #[contract]
    @@ -620,261 +815,270 @@
     impl VaultTrait for DeFindexVault {
         /// Initializes the DeFindex Vault contract with the required parameters.
         ///
    -    /// This function sets the roles for emergency manager, fee receiver, and manager.
    +    /// This function sets the roles for manager, emergency manager, vault fee receiver, and manager.
         /// It also stores the list of assets to be managed by the vault, including strategies for each asset.
    -    /// 
    -    /// # Arguments:
    -    /// * `e` - The environment.
    -    /// * `assets` - A vector of `AssetAllocation` structs representing the assets and their associated strategies.
    -    /// * `manager` - The address responsible for managing the vault.
    -    /// * `emergency_manager` - The address with emergency control over the vault.
    -    /// * `fee_receiver` - The address that will receive fees from the vault.
    -    /// * `vault_share` - The percentage of the vault's fees that will be sent to the DeFindex receiver. in BPS.
    -    /// * `defindex_receiver` - The address that will receive fees for DeFindex from the vault.
    -    /// * `factory` - The address of the factory that deployed the vault.
         ///
    -    /// # Returns:
    -    /// * `Result<(), ContractError>` - Ok if successful, otherwise returns a ContractError.
    +    /// # Arguments
    +    /// - `assets`: List of asset allocations for the vault, including strategies associated with each asset.
    +    /// - `manager`: Primary vault manager with permissions for vault control.
    +    /// - `emergency_manager`: Address with emergency access for emergency control over the vault.
    +    /// - `vault_fee_receiver`: Address designated to receive the vault fee receiver's portion of management fees.
    +    /// - `vault_fee`: Vault-specific fee percentage in basis points (typically set at 0-2% APR).
    +    /// - `defindex_protocol_receiver`: Address receiving DeFindex’s protocol-wide fee in basis points (0.5% APR).
    +    /// - `factory`: Factory contract address for deployment linkage.
    +    /// - `vault_name`: Name of the vault token to be displayed in metadata.
    +    /// - `vault_symbol`: Symbol representing the vault’s token.
    +    ///
    +    /// # Returns
    +    /// - `Result<(), ContractError>`: Returns `Ok(())` if initialization succeeds, or a `ContractError` if
    +    ///   any setup fails (e.g., strategy mismatch with asset).
    +    ///
    +    /// # Errors
    +    /// - `ContractError::AlreadyInitialized`: If the vault has already been initialized.
    +    /// - `ContractError::StrategyDoesNotSupportAsset`: If a strategy within an asset does not support the asset’s contract.
    +    ///
         fn initialize(
             e: Env,
    -        assets: Vec<AssetAllocation>,
    +        assets: Vec<AssetStrategySet>,
             manager: Address,
             emergency_manager: Address,
    -        fee_receiver: Address,
    -        vault_share: u32,
    -        defindex_receiver: Address,
    +        vault_fee_receiver: Address,
    +        vault_fee: u32,
    +        defindex_protocol_receiver: Address,
             factory: Address,
    +        vault_name: String,
    +        vault_symbol: String,
         ) -> Result<(), ContractError> {
    +        extend_instance_ttl(&e);
    +
             let access_control = AccessControl::new(&e);
             if access_control.has_role(&RolesDataKey::Manager) {
                 panic_with_error!(&e, ContractError::AlreadyInitialized);
             }
     
             access_control.set_role(&RolesDataKey::EmergencyManager, &emergency_manager);
    -        access_control.set_role(&RolesDataKey::FeeReceiver, &fee_receiver);
    +        access_control.set_role(&RolesDataKey::VaultFeeReceiver, &vault_fee_receiver);
             access_control.set_role(&RolesDataKey::Manager, &manager);
     
    -        // Set Vault Share (in basis points)
    -        set_vault_share(&e, &vault_share);
    +        // Set Vault Fee (in basis points)
    +        set_vault_fee(&e, &vault_fee);
     
             // Set Paltalabs Fee Receiver
    -        set_defindex_receiver(&e, &defindex_receiver);
    +        set_defindex_protocol_fee_receiver(&e, &defindex_protocol_receiver);
     
             // Set the factory address
             set_factory(&e, &factory);
     
             // Store Assets Objects
             let total_assets = assets.len();
    +
    +        // fails if the total assets is 0
    +        if total_assets == 0 {
    +            panic_with_error!(&e, ContractError::NoAssetAllocation);
    +        }
    +
             set_total_assets(&e, total_assets as u32);
             for (i, asset) in assets.iter().enumerate() {
    -            // for every asset, we need to check that the list of strategyes indeed support this asset
    -            
    -            // TODO Fix, currently failing
    -            // for strategy in asset.strategies.iter() {
    -            //     let strategy_client = DeFindexStrategyClient::new(&e, &strategy.address);
    -            //     if strategy_client.asset() != asset.address {
    -            //         panic_with_error!(&e, ContractError::StrategyDoesNotSupportAsset);
    -            //     }
    -            // }
    -            set_asset(&e, i as u32, &asset);
    +            // for every asset, we need to check that the list of strategies indeed support this asset
    +
    +            for strategy in asset.strategies.iter() {
    +                let strategy_client = DeFindexStrategyClient::new(&e, &strategy.address);
    +                if strategy_client.asset() != asset.address {
    +                    panic_with_error!(&e, ContractError::StrategyDoesNotSupportAsset);
    +                }
    +            }
    +            set_asset(&e, i as u32, &asset);
             }
     
             // Metadata for the contract's token (unchanged)
    -        // TODO: Name should be concatenated with some other name giving when initializing. Check how soroswap pairs  token are called.
    +        // TODO: Name should be concatenated with some other name giving when initializing. Check how soroswap pairs token are called.
             let decimal: u32 = 7;
    -        let name: String = String::from_str(&e, "dfToken");
    -        let symbol: String = String::from_str(&e, "DFT");
     
             write_metadata(
                 &e,
                 TokenMetadata {
                     decimal,
    -                name,
    -                symbol,
    +                name: vault_name,
    +                symbol: vault_symbol,
                 },
             );
     
    -        events::emit_initialized_vault(&e, emergency_manager, fee_receiver, manager, defindex_receiver, assets);
    +        events::emit_initialized_vault(
    +            &e,
    +            emergency_manager,
    +            vault_fee_receiver,
    +            manager,
    +            defindex_protocol_receiver,
    +            assets,
    +        );
     
             Ok(())
         }
     
    -    /// Handles deposits into the DeFindex Vault.
    +    /// Handles user deposits into the DeFindex Vault.
         ///
    -    /// This function transfers the desired amounts of each asset into the vault, distributes the assets
    -    /// across the strategies according to the vault's ratios, and mints dfTokens representing the user's
    -    /// share in the vault.
    +    /// This function processes a deposit by transferring each specified asset amount from the user's address to
    +    /// the vault, allocating assets according to the vault's defined strategy ratios, and minting vault shares that
    +    /// represent the user's proportional share in the vault. The `amounts_desired` and `amounts_min` vectors should
    +    /// align with the vault's asset order to ensure correct allocation.
         ///
    -    /// # Arguments:
    -    /// * `e` - The environment.
    -    /// * `amounts_desired` - A vector of the amounts the user wishes to deposit for each asset.
    -    /// * `amounts_min` - A vector of minimum amounts required for the deposit to proceed.
    +    /// # Parameters
    +    /// * `e` - The current environment reference (`Env`), for access to the contract state and utilities.
    +    /// * `amounts_desired` - A vector specifying the user's intended deposit amounts for each asset.
    +    /// * `amounts_min` - A vector of minimum deposit amounts required for the transaction to proceed.
         /// * `from` - The address of the user making the deposit.
         ///
    -    /// # Returns:
    -    /// * `Result<(), ContractError>` - Ok if successful, otherwise returns a ContractError.
    +    /// # Returns
    +    /// * `Result<(Vec<i128>, i128), ContractError>` - Returns the actual deposited `amounts` and `shares_to_mint` if successful,
    +    ///   otherwise a `ContractError`.
    +    ///
    +    /// # Function Flow
    +    /// 1. **Fee Collection**: Collects accrued fees before processing the deposit.
    +    /// 2. **Validation**: Checks that the lengths of `amounts_desired` and `amounts_min` match the vault's assets.
    +    /// 3. **Share Calculation**: Calculates `shares_to_mint` based on the vault's total managed funds and the deposit amount.
    +    /// 4. **Asset Transfer**: Transfers each specified amount from the user’s address to the vault as idle funds.
    +    /// 5. **Vault shares Minting**: Mints vault shares for the user to represent their ownership in the vault.
    +    ///
    +    /// # Notes
    +    /// - For the first deposit, if the vault has only one asset, shares are calculated directly based on the deposit amount.
    +    /// - For multiple assets, the function delegates to `calculate_deposit_amounts_and_shares_to_mint`
    +    ///   for precise share computation.
    +    /// - An event is emitted to log the deposit, including the actual deposited amounts and minted shares.
    +    ///
         fn deposit(
             e: Env,
             amounts_desired: Vec<i128>,
             amounts_min: Vec<i128>,
             from: Address,
    -    ) -> Result<(), ContractError> {
    +        invest: bool,
    +    ) -> Result<(Vec<i128>, i128), ContractError> {
    +        extend_instance_ttl(&e);
             check_initialized(&e)?;
             from.require_auth();
     
    -        // Set LastFeeAssessment if it is the first deposit
    -        if VaultToken::total_supply(e.clone())==0{
    -            set_last_fee_assesment(&e, &e.ledger().timestamp());
    -        }
    +        // Collect Fees
    +        // If this was not done before, last_fee_assesment will set to be current timestamp and this will return without action
    +        collect_fees(&e)?;
     
    -        // get assets
    -        let assets = get_assets(&e);
    -        // assets lenght should be equal to amounts_desired and amounts_min length
    -        let assets_length = assets.len();
    -        if assets_length != amounts_desired.len() || assets_length != amounts_min.len() {
    -            panic_with_error!(&e, ContractError::WrongAmuntsLength);
    -        }
    +        let assets = get_assets(&e);
     
    -        // for every amount desired, check non negative
    -        for amount in amounts_desired.iter() {
    -            check_nonnegative_amount(amount)?;
    -        }
    -        // for amount min is not necesary to check if it is negative
    -
    -        let (amounts, shares_to_mint) = if assets_length == 1 {
    -        // If Total Assets == 1
    -            let shares = if VaultToken::total_supply(e.clone())==0{
    -                // TODO In this case we might also want to mint a MINIMUM LIQUIDITY to be locked forever in the contract
    -                // this might be for security and practical reasons as well
    -                // shares will be equal to the amount desired to deposit, just for simplicity
    -                amounts_desired.get(0).unwrap() // here we have already check same lenght
    -            } else{
    -                // in this case we will mint a share proportional to the total managed funds
    -                let total_managed_funds = fetch_total_managed_funds(&e);
    -                VaultToken::total_supply(e.clone()) * amounts_desired.get(0).unwrap() / total_managed_funds.get(assets.get(0).unwrap().address.clone()).unwrap()
    -            };
    -            (amounts_desired, shares)
    -        } else {
    -        // If Total Assets > 1
    -            calculate_deposit_amounts_and_shares_to_mint(
    -                &e,
    -                &assets,
    -                &amounts_desired,
    -                &amounts_min,
    -            )
    -        };
    -
    -        // for every asset
    -        for (i, amount) in amounts.iter().enumerate() {
    -            if amount > 0 {
    -                let asset = assets.get(i as u32).unwrap();
    -                let asset_client = TokenClient::new(&e, &asset.address);
    -                // send the current amount to this contract
    -                asset_client.transfer(&from, &e.current_contract_address(), &amount);
    -            }
    -        }
    +        let (amounts, shares_to_mint) =
    +            process_deposit(&e, &assets, &amounts_desired, &amounts_min, &from)?;
    +        events::emit_deposit_event(&e, from, amounts.clone(), shares_to_mint.clone());
     
    -        // now we mint the corresponding dfTOkenb
    -        internal_mint(e.clone(), from.clone(), shares_to_mint);
    -
    -        events::emit_deposit_event(&e, from, amounts, shares_to_mint);
    +        if invest {
    +            // Generate investment allocations and execute them
    +            generate_and_execute_investments(&e, &amounts, &assets)?;
    +        }
     
    -        // fees assesment
    -        collect_fees(&e)?;
    -        // TODO return amounts and shares to mint
    -        Ok(())
    +        Ok((amounts, shares_to_mint))
         }
     
    -    /// Withdraws assets from the DeFindex Vault by burning dfTokens.
    +    /// Withdraws assets from the DeFindex Vault by burning Vault Share tokens.
         ///
    -    /// This function calculates the amount of assets to withdraw based on the number of dfTokens being burned,
    +    /// This function calculates the amount of assets to withdraw based on the number of Vault Share tokens being burned,
         /// then transfers the appropriate assets back to the user, pulling from both idle funds and strategies
         /// as needed.
         ///
         /// # Arguments:
         /// * `e` - The environment.
    -    /// * `df_amount` - The amount of dfTokens to burn for the withdrawal.
    +    /// * `shares_amount` - The amount of Vault Share tokens to burn for the withdrawal.
         /// * `from` - The address of the user requesting the withdrawal.
         ///
         /// # Returns:
         /// * `Result<(), ContractError>` - Ok if successful, otherwise returns a ContractError.
    -    fn withdraw(e: Env, df_amount: i128, from: Address) -> Result<Vec<i128>, ContractError> {
    +    fn withdraw(
    +        e: Env,
    +        withdraw_shares: i128,
    +        from: Address,
    +    ) -> Result<Vec<i128>, ContractError> {
    +        extend_instance_ttl(&e);
             check_initialized(&e)?;
    -        check_nonnegative_amount(df_amount)?;
    +        check_nonnegative_amount(withdraw_shares)?;
             from.require_auth();
         
    -        // Check if the user has enough dfTokens
    -        let df_user_balance = VaultToken::balance(e.clone(), from.clone());
    -        if df_user_balance < df_amount {
    -            return Err(ContractError::InsufficientBalance);
    -        }
    +        // Assess fees
    +        collect_fees(&e)?;
         
    -        // Calculate the withdrawal amounts for each asset based on the dfToken amount
    -        let asset_amounts = calculate_asset_amounts_for_dftokens(&e, df_amount);
    +        // Calculate the withdrawal amounts for each asset based on the share amounts
    +        let total_managed_funds = fetch_total_managed_funds(&e);
     
    -        // Burn the dfTokens after calculating the withdrawal amounts (so total supply is correct)
    -        internal_burn(e.clone(), from.clone(), df_amount);
    -    
    -        // Create a map to store the total amounts to transfer for each asset address
    -        let mut total_amounts_to_transfer: Map<Address, i128> = Map::new(&e);
    +        let asset_withdrawal_amounts = calculate_asset_amounts_per_vault_shares(
    +            &e,
    +            withdraw_shares,
    +            &total_managed_funds,
    +        )?;
         
    -        // Get idle funds for each asset (Map<Address, i128>)
    -        let idle_funds = fetch_current_idle_funds(&e);
    +        // Burn the shares after calculating the withdrawal amounts
    +        // this will panic with error if the user does not have enough balance
    +        internal_burn(e.clone(), from.clone(), withdraw_shares);
         
    -        // Loop through each asset and handle the withdrawal
    -        for (asset_address, required_amount) in asset_amounts.iter() {
    -            // Check idle funds for this asset
    -            let idle_balance = idle_funds.get(asset_address.clone()).unwrap_or(0);
    +        // Loop through each asset to handle the withdrawal
    +        let mut withdrawn_amounts: Vec<i128> = Vec::new(&e);
    +        for (asset_address, requested_withdrawal_amount) in asset_withdrawal_amounts.iter() {
     
    -            let mut remaining_amount = required_amount;
    -    
    -            // Withdraw as much as possible from idle funds first
    -            if idle_balance > 0 {
    -                if idle_balance >= required_amount {
    -                    // Idle funds cover the full amount
    -                    total_amounts_to_transfer.set(asset_address.clone(), required_amount);
    -                    continue;  // No need to withdraw from the strategy
    -                } else {
    -                    // Partial withdrawal from idle funds
    -                    total_amounts_to_transfer.set(asset_address.clone(), idle_balance);
    -                    remaining_amount = required_amount - idle_balance;  // Update remaining amount
    -                }
    -            }
    -    
    -            // Find the corresponding asset address for this strategy
    -            let asset_allocation = get_asset_allocation_from_address(&e, asset_address.clone())?;
    -            let withdrawal_amounts = calculate_withdrawal_amounts(&e, remaining_amount, asset_allocation);
    -
    -            for (strategy_address, amount) in withdrawal_amounts.iter() {
    -                let strategy_client = get_strategy_client(&e, strategy_address.clone());
    -                // TODO: What if the withdraw method exceeds the instructions limit? since im trying to ithdraw from all strategies of all assets...
    -                strategy_client.withdraw(&amount, &e.current_contract_address());
    -    
    -                // Update the total amounts to transfer map
    -                let current_amount = total_amounts_to_transfer.get(strategy_address.clone()).unwrap_or(0);
    -                total_amounts_to_transfer.set(asset_address.clone(), current_amount + amount);
    +            let asset_allocation = total_managed_funds
    +            .get(asset_address.clone())
    +            .unwrap_or_else(|| panic_with_error!(&e, ContractError::WrongAmountsLength));
    +
    +            // Check idle funds for this asset
    +            let idle_funds = asset_allocation.idle_amount;
    +        
    +            // Withdraw from idle funds first
    +            if idle_funds >= requested_withdrawal_amount {
    +                // Idle funds cover the full amount
    +                TokenClient::new(&e, &asset_address).transfer(
    +                    &e.current_contract_address(),
    +                    &from,
    +                    &requested_withdrawal_amount,
    +                );
    +                withdrawn_amounts.push_back(requested_withdrawal_amount);
    +                continue;
    +            } else {
    +                let mut total_withdrawn_for_asset = 0;
    +                // Partial withdrawal from idle funds
    +                total_withdrawn_for_asset += idle_funds;
    +                let remaining_withdrawal_amount = requested_withdrawal_amount - idle_funds;
    +                
    +                // Withdraw the remaining amount from strategies
    +                let total_invested_amount = asset_allocation.invested_amount;
    +                
    +                for strategy_allocation in asset_allocation.strategy_allocations.iter() {
    +                    // TODO: If strategy is paused, should we skip it? Otherwise, the calculation will go wrong.
    +                    // if strategy.paused {
    +                    //     continue;
    +                    // }
    +                    
    +                    // Amount to unwind from strategy
    +                    let strategy_withdrawal_share =
    +                    (remaining_withdrawal_amount * strategy_allocation.amount) / total_invested_amount;
    +                    
    +                    if strategy_withdrawal_share > 0 {
    +                        withdraw_from_strategy(&e, &strategy_allocation.strategy_address, &strategy_withdrawal_share)?;
    +                        TokenClient::new(&e, &asset_address).transfer(
    +                            &e.current_contract_address(),
    +                            &from,
    +                            &strategy_withdrawal_share,
    +                        );
    +                        total_withdrawn_for_asset += strategy_withdrawal_share;
    +                    }
    +                }
    +                TokenClient::new(&e, &asset_address).transfer(
    +                    &e.current_contract_address(),
    +                    &from,
    +                    &total_withdrawn_for_asset,
    +                );
    +                withdrawn_amounts.push_back(total_withdrawn_for_asset);
                 }
             }
         
    -        // Perform the transfers for the total amounts
    -        let mut amounts_withdrawn: Vec<i128> = Vec::new(&e);
    -        for (asset_address, total_amount) in total_amounts_to_transfer.iter() {
    -            TokenClient::new(&e, &asset_address).transfer(
    -                &e.current_contract_address(),
    -                &from,
    -                &total_amount,
    -            );
    -            amounts_withdrawn.push_back(total_amount);
    -        }
    -
    -        events::emit_withdraw_event(&e, from, df_amount, amounts_withdrawn.clone());
    -
    -        // fees assesment
    -        collect_fees(&e)?;
    +        events::emit_withdraw_event(&e, from, withdraw_shares, withdrawn_amounts.clone());
         
    -        Ok(amounts_withdrawn)
    +        Ok(withdrawn_amounts)
         }
     
    +    
    +
         /// Executes an emergency withdrawal from a specific strategy.
         ///
         /// This function allows the emergency manager or manager to withdraw all assets from a particular strategy
    @@ -888,31 +1092,39 @@
         ///
         /// # Returns:
         /// * `Result<(), ContractError>` - Ok if successful, otherwise returns a ContractError.
    -    fn emergency_withdraw(e: Env, strategy_address: Address, caller: Address) -> Result<(), ContractError> {
    +    fn emergency_withdraw(
    +        e: Env,
    +        strategy_address: Address,
    +        caller: Address,
    +    ) -> Result<(), ContractError> {
    +        extend_instance_ttl(&e);
             check_initialized(&e)?;
    -    
    +
             // Ensure the caller is the Manager or Emergency Manager
             let access_control = AccessControl::new(&e);
    -        access_control.require_any_role(&[RolesDataKey::EmergencyManager, RolesDataKey::Manager], &caller);
    -    
    +        access_control.require_any_role(
    +            &[RolesDataKey::EmergencyManager, RolesDataKey::Manager],
    +            &caller,
    +        );
    +
             // Find the strategy and its associated asset
             let asset = get_strategy_asset(&e, &strategy_address)?;
             // This ensures that the vault has this strategy in its list of assets
             let strategy = get_strategy_struct(&strategy_address, &asset)?;
    -        
    +
             // Withdraw all assets from the strategy
             let strategy_client = get_strategy_client(&e, strategy.address.clone());
             let strategy_balance = strategy_client.balance(&e.current_contract_address());
    -    
    +
             if strategy_balance > 0 {
                 strategy_client.withdraw(&strategy_balance, &e.current_contract_address());
     
                 //TODO: Should we check if the idle funds are corresponding to the strategy balance withdrawed?
             }
    -        
    +
             // Pause the strategy
             pause_strategy(&e, strategy_address.clone())?;
    -    
    +
             events::emit_emergency_withdraw_event(&e, caller, strategy_address, strategy_balance);
             Ok(())
         }
    @@ -929,16 +1141,25 @@
         ///
         /// # Returns:
         /// * `Result<(), ContractError>` - Ok if successful, otherwise returns a ContractError.
    -    fn pause_strategy(e: Env, strategy_address: Address, caller: Address) -> Result<(), ContractError> {
    +    fn pause_strategy(
    +        e: Env,
    +        strategy_address: Address,
    +        caller: Address,
    +    ) -> Result<(), ContractError> {
    +        extend_instance_ttl(&e);
             // Ensure the caller is the Manager or Emergency Manager
    +        // TODO: Should check if the strategy has any amount invested on it, and return an error if it has, should we let the manager to pause a strategy with funds invested?
             let access_control = AccessControl::new(&e);
    -        access_control.require_any_role(&[RolesDataKey::EmergencyManager, RolesDataKey::Manager], &caller);
    +        access_control.require_any_role(
    +            &[RolesDataKey::EmergencyManager, RolesDataKey::Manager],
    +            &caller,
    +        );
     
             pause_strategy(&e, strategy_address.clone())?;
             events::emit_strategy_paused_event(&e, strategy_address, caller);
             Ok(())
         }
    -    
    +
         /// Unpauses a previously paused strategy.
         ///
         /// This function unpauses a strategy by setting its `paused` field to `false`, allowing it to be used
    @@ -951,10 +1172,18 @@
         ///
         /// # Returns:
         /// * `Result<(), ContractError>` - Ok if successful, otherwise returns a ContractError.
    -    fn unpause_strategy(e: Env, strategy_address: Address, caller: Address) -> Result<(), ContractError> {
    +    fn unpause_strategy(
    +        e: Env,
    +        strategy_address: Address,
    +        caller: Address,
    +    ) -> Result<(), ContractError> {
    +        extend_instance_ttl(&e);
             // Ensure the caller is the Manager or Emergency Manager
             let access_control = AccessControl::new(&e);
    -        access_control.require_any_role(&[RolesDataKey::EmergencyManager, RolesDataKey::Manager], &caller);
    +        access_control.require_any_role(
    +            &[RolesDataKey::EmergencyManager, RolesDataKey::Manager],
    +            &caller,
    +        );
     
             unpause_strategy(&e, strategy_address.clone())?;
             events::emit_strategy_unpaused_event(&e, strategy_address, caller);
    @@ -967,8 +1196,9 @@
         /// * `e` - The environment.
         ///
         /// # Returns:
    -    /// * `Vec<AssetAllocation>` - A vector of `AssetAllocation` structs representing the assets managed by the vault.
    -    fn get_assets(e: Env) -> Vec<AssetAllocation> {
    +    /// * `Vec<AssetStrategySet>` - A vector of `AssetStrategySet` structs representing the assets managed by the vault.
    +    fn get_assets(e: Env) -> Vec<AssetStrategySet> {
    +        extend_instance_ttl(&e);
             get_assets(&e)
         }
     
    @@ -982,7 +1212,8 @@
         ///
         /// # Returns:
         /// * `Map<Address, i128>` - A map of asset addresses to their total managed amounts.
    -    fn fetch_total_managed_funds(e: &Env) -> Map<Address, i128> {
    +    fn fetch_total_managed_funds(e: &Env) -> Map<Address, CurrentAssetInvestmentAllocation> {
    +        extend_instance_ttl(&e);
             fetch_total_managed_funds(e)
         }
     
    @@ -997,6 +1228,7 @@
         /// # Returns:
         /// * `Map<Address, i128>` - A map of asset addresses to their total invested amounts.
         fn fetch_current_invested_funds(e: &Env) -> Map<Address, i128> {
    +        extend_instance_ttl(&e);
             fetch_current_invested_funds(e)
         }
     
    @@ -1011,13 +1243,37 @@
         /// # Returns:
         /// * `Map<Address, i128>` - A map of asset addresses to their total idle amounts.
         fn fetch_current_idle_funds(e: &Env) -> Map<Address, i128> {
    +        extend_instance_ttl(&e);
             fetch_current_idle_funds(e)
         }
     
    -    // TODO: DELETE THIS, USED FOR TESTING
    -    /// Temporary method for testing purposes.
    -    fn get_asset_amounts_for_dftokens(e: Env, df_tokens: i128) -> Map<Address, i128> {
    -        calculate_asset_amounts_for_dftokens(&e, df_tokens)
    +    // Calculates the corresponding amounts of each asset per a given number of vault shares.
    +    /// This function extends the contract's time-to-live and calculates how much of each asset corresponds 
    +    /// per the provided number of vault shares (`vault_shares`). It provides proportional allocations for each asset 
    +    /// in the vault relative to the specified shares.
    +    ///
    +    /// # Arguments
    +    /// * `e` - The current environment reference.
    +    /// * `vault_shares` - The number of vault shares for which the corresponding asset amounts are calculated.
    +    ///
    +    /// # Returns
    +    /// * `Map<Address, i128>` - A map containing each asset address and its corresponding proportional amount.
    +    fn get_asset_amounts_per_shares(e: Env, vault_shares: i128) -> Result<Map<Address, i128>, ContractError> {
    +        extend_instance_ttl(&e);
    +        let total_managed_funds = fetch_total_managed_funds(&e);
    +        Ok(calculate_asset_amounts_per_vault_shares(&e, vault_shares, &total_managed_funds)?)
    +    }
    +
    +    fn get_fees(e: Env) -> (u32, u32) {
    +        extend_instance_ttl(&e);
    +        let defindex_protocol_fee = fetch_defindex_fee(&e);
    +        let vault_fee = get_vault_fee(&e);
    +        (defindex_protocol_fee, vault_fee)
    +    }
    +
    +    fn collect_fees(e: Env) -> Result<(), ContractError> {
    +        extend_instance_ttl(&e);
    +        collect_fees(&e)
         }
     }
     
    @@ -1030,11 +1286,12 @@
         /// # Arguments:
         /// * `e` - The environment.
         /// * `caller` - The address initiating the change (must be the manager or emergency manager).
    -    /// * `fee_receiver` - The new fee receiver address.
    +    /// * `vault_fee_receiver` - The new fee receiver address.
         ///
         /// # Returns:
         /// * `()` - No return value.
         fn set_fee_receiver(e: Env, caller: Address, new_fee_receiver: Address) {
    +        extend_instance_ttl(&e);
             let access_control = AccessControl::new(&e);
             access_control.set_fee_receiver(&caller, &new_fee_receiver);
     
    @@ -1049,6 +1306,7 @@
         /// # Returns:
         /// * `Result<Address, ContractError>` - The fee receiver address if successful, otherwise returns a ContractError.
         fn get_fee_receiver(e: Env) -> Result<Address, ContractError> {
    +        extend_instance_ttl(&e);
             let access_control = AccessControl::new(&e);
             access_control.get_fee_receiver()
         }
    @@ -1064,6 +1322,7 @@
         /// # Returns:
         /// * `()` - No return value.
         fn set_manager(e: Env, manager: Address) {
    +        extend_instance_ttl(&e);
             let access_control = AccessControl::new(&e);
             access_control.set_manager(&manager);
     
    @@ -1078,6 +1337,7 @@
         /// # Returns:
         /// * `Result<Address, ContractError>` - The manager address if successful, otherwise returns a ContractError.
         fn get_manager(e: Env) -> Result<Address, ContractError> {
    +        extend_instance_ttl(&e);
             let access_control = AccessControl::new(&e);
             access_control.get_manager()
         }
    @@ -1093,6 +1353,7 @@
         /// # Returns:
         /// * `()` - No return value.
         fn set_emergency_manager(e: Env, emergency_manager: Address) {
    +        extend_instance_ttl(&e);
             let access_control = AccessControl::new(&e);
             access_control.set_emergency_manager(&emergency_manager);
     
    @@ -1114,41 +1375,127 @@
     
     #[contractimpl]
     impl VaultManagementTrait for DeFindexVault {
    -    /// Invests the vault's idle funds into the specified strategies.
    -    /// 
    +    /// Executes the investment of the vault's idle funds based on the specified asset allocations.
    +    /// This function allows partial investments by providing an optional allocation for each asset,
    +    /// and it ensures proper authorization and validation checks before proceeding with investments.
    +    ///
    +    /// # Arguments
    +    /// * `e` - The current environment reference.
    +    /// * `asset_investments` - A vector of optional `AssetInvestmentAllocation` structures, where each element
    +    ///   represents an allocation for a specific asset. The vector must match the number of vault assets in length.
    +    ///
    +    /// # Returns
    +    /// * `Result<(), ContractError>` - Returns `Ok(())` if the investments are successful or a `ContractError`
    +    ///   if any issue occurs during validation or execution.
    +    ///
    +    /// # Function Flow
    +    /// 1. **Extend Instance TTL**: Extends the contract instance's time-to-live to keep the instance active.
    +    /// 2. **Check Initialization**: Verifies that the vault is properly initialized before proceeding.
    +    /// 3. **Access Control**: Ensures the caller has the `Manager` role required to initiate investments.
    +    /// 4. **Asset Count Validation**: Verifies that the length of the `asset_investments` vector matches
    +    ///    the number of assets managed by the vault. If they don't match, a `WrongInvestmentLength` error is returned.
    +    /// 5. **Investment Execution**: Calls the `check_and_execute_investments` function to perform the investment
    +    ///    after validating the inputs and ensuring correct execution flows for each asset allocation.
    +    ///
    +    /// # Errors
    +    /// * Returns `ContractError::WrongInvestmentLength` if the length of `asset_investments` does not match the vault assets.
    +    /// * Returns `ContractError` if access control validation fails or if investment execution encounters an issue.
    +    ///
    +    /// # Security
    +    /// - Only addresses with the `Manager` role can call this function, ensuring restricted access to managing investments.
    +    fn invest(
    +        e: Env,
    +        asset_investments: Vec<Option<AssetInvestmentAllocation>>,
    +    ) -> Result<(), ContractError> {
    +        extend_instance_ttl(&e);
    +        check_initialized(&e)?;
    +
    +        // Access control: ensure caller has the required manager role
    +        let access_control = AccessControl::new(&e);
    +        access_control.require_role(&RolesDataKey::Manager);
    +
    +        let assets = get_assets(&e);
    +
    +        // Ensure the length of `asset_investments` matches the number of vault assets
    +        if asset_investments.len() != assets.len() {
    +            panic_with_error!(&e, ContractError::WrongInvestmentLength);
    +        }
    +
    +        // Check and execute investments for each asset allocation
    +        check_and_execute_investments(e, assets, asset_investments)?;
    +
    +        Ok(())
    +    }
    +
    +    /// Rebalances the vault by executing a series of instructions.
    +    ///
         /// # Arguments:
         /// * `e` - The environment.
    -    /// * `investment` - A vector of `Investment` structs representing the amount to invest in each strategy.
    -    /// * `caller` - The address of the caller.
    -    /// 
    +    /// * `instructions` - A vector of `Instruction` structs representing actions (withdraw, invest, swap, zapper) to be taken.
    +    ///
         /// # Returns:
         /// * `Result<(), ContractError>` - Ok if successful, otherwise returns a ContractError.
    -    fn invest(e: Env, investments: Vec<Investment>) -> Result<(), ContractError> {
    +    fn rebalance(e: Env, instructions: Vec<Instruction>) -> Result<(), ContractError> {
    +        extend_instance_ttl(&e);
             check_initialized(&e)?;
    -    
    +
             let access_control = AccessControl::new(&e);
             access_control.require_role(&RolesDataKey::Manager);
    -        e.current_contract_address().require_auth();
    -    
    -        // Get the current idle funds for all assets
    -        let idle_funds = fetch_current_idle_funds(&e);
    -    
    -        // Prepare investments based on current idle funds
    -        // This checks if the total investment exceeds the idle funds
    -        prepare_investment(&e, investments.clone(), idle_funds)?;
    -    
    -        // Now proceed with the actual investments if all checks passed
    -        execute_investment(&e, investments)?;
    -
    -        // auto invest mockup
    -        // if auto_invest {
    -        //     let idle_funds = fetch_current_idle_funds(&e);
    -            
    -        //     // Prepare investments based on current ratios of invested funds
    -        //     let investments = calculate_investments_based_on_ratios(&e);
    -        //     prepare_investment(&e, investments.clone(), idle_funds)?;
    -        //     execute_investment(&e, investments)?;
    -        // }
    -        Ok(())
    +
    +        if instructions.is_empty() {
    +            panic_with_error!(&e, ContractError::NoInstructions);
    +        }
    +
    +        for instruction in instructions.iter() {
    +            match instruction.action {
    +                ActionType::Withdraw => match (&instruction.strategy, &instruction.amount) {
    +                    (Some(strategy_address), Some(amount)) => {
    +                        withdraw_from_strategy(&e, strategy_address, amount)?;
    +                    }
    +                    _ => return Err(ContractError::MissingInstructionData),
    +                },
    +                ActionType::Invest => match (&instruction.strategy, &instruction.amount) {
    +                    (Some(strategy_address), Some(amount)) => {
    +                        let asset_address = get_strategy_asset(&e, strategy_address)?;
    +                        invest_in_strategy(&e, &asset_address.address, strategy_address, amount)?;
    +                    }
    +                    _ => return Err(ContractError::MissingInstructionData),
    +                },
    +                ActionType::SwapExactIn => match &instruction.swap_details_exact_in {
    +                    OptionalSwapDetailsExactIn::Some(swap_details) => {
    +                        internal_swap_exact_tokens_for_tokens(
    +                            &e,
    +                            &swap_details.token_in,
    +                            &swap_details.token_out,
    +                            &swap_details.amount_in,
    +                            &swap_details.amount_out_min,
    +                            &swap_details.distribution,
    +                            &swap_details.deadline,
    +                        )?;
    +                    }
    +                    _ => return Err(ContractError::MissingInstructionData),
    +                },
    +                ActionType::SwapExactOut => match &instruction.swap_details_exact_out {
    +                    OptionalSwapDetailsExactOut::Some(swap_details) => {
    +                        internal_swap_tokens_for_exact_tokens(
    +                            &e,
    +                            &swap_details.token_in,
    +                            &swap_details.token_out,
    +                            &swap_details.amount_out,
    +                            &swap_details.amount_in_max,
    +                            &swap_details.distribution,
    +                            &swap_details.deadline,
    +                        )?;
    +                    }
    +                    _ => return Err(ContractError::MissingInstructionData),
    +                },
    +                ActionType::Zapper => {
    +                    // TODO: Implement Zapper instructions
    +                }
    +            }
    +        }
    +
    +        Ok(())
         }
    -}
    \ No newline at end of file +} +
    \ No newline at end of file diff --git a/apps/rust_docs/src/defindex_vault/models.rs.html b/apps/rust_docs/src/defindex_vault/models.rs.html index 38a78887..21044279 100644 --- a/apps/rust_docs/src/defindex_vault/models.rs.html +++ b/apps/rust_docs/src/defindex_vault/models.rs.html @@ -1,4 +1,4 @@ -models.rs - source
    1
    +models.rs - source
    1
     2
     3
     4
    @@ -23,28 +23,167 @@
     23
     24
     25
    +26
    +27
    +28
    +29
    +30
    +31
    +32
    +33
    +34
    +35
    +36
    +37
    +38
    +39
    +40
    +41
    +42
    +43
    +44
    +45
    +46
    +47
    +48
    +49
    +50
    +51
    +52
    +53
    +54
    +55
    +56
    +57
    +58
    +59
    +60
    +61
    +62
    +63
    +64
    +65
    +66
    +67
    +68
    +69
    +70
    +71
    +72
    +73
    +74
    +75
    +76
    +77
    +78
    +79
    +80
    +81
    +82
    +83
    +84
    +85
    +86
    +87
    +88
    +89
    +90
    +91
    +92
    +93
    +94
     
    use soroban_sdk::{contracttype, Address, String, Vec};
     
    +// Investment Allocation in Strategies
    +#[contracttype]
    +#[derive(Clone, Debug, Eq, PartialEq)]
    +pub struct StrategyAllocation {
    +    pub strategy_address: Address,
    +    pub amount: i128,
    +}
    +
    +// Current Asset Investment Allocation
    +#[contracttype]
    +#[derive(Clone, Debug, Eq, PartialEq)]
    +pub struct CurrentAssetInvestmentAllocation {
    +    pub asset: Address,
    +    pub total_amount: i128,
    +    pub idle_amount: i128,
    +    pub invested_amount: i128,
    +    pub strategy_allocations: Vec<StrategyAllocation>,
    +}
    +
     #[contracttype]
     #[derive(Clone, Debug, Eq, PartialEq)]
    -pub struct Strategy {
    -    pub address: Address,
    -    pub name: String,
    -    pub paused: bool,
    -    pub ratio: i128,
    +pub struct AssetInvestmentAllocation {
    +    pub asset: Address,
    +    pub strategy_allocations: Vec<Option<StrategyAllocation>>,
    +}
    +//
    +#[contracttype]
    +#[derive(Clone, Debug, Eq, PartialEq)]
    +pub struct Instruction {
    +    pub action: ActionType,
    +    pub strategy: Option<Address>,
    +    pub amount: Option<i128>,
    +    pub swap_details_exact_in: OptionalSwapDetailsExactIn,
    +    pub swap_details_exact_out: OptionalSwapDetailsExactOut,
    +    // pub zapper_instructions: Option<Vec<ZapperInstruction>>,
    +}
    +
    +#[contracttype]
    +#[derive(Clone, Debug, Eq, PartialEq, Copy)]
    +pub enum ActionType {
    +    Withdraw = 0,
    +    Invest = 1,
    +    SwapExactIn = 2,
    +    SwapExactOut = 3,
    +    Zapper = 4,
     }
     
     #[contracttype]
     #[derive(Clone, Debug, Eq, PartialEq)]
    -pub struct AssetAllocation {
    -    pub address: Address,
    -    pub ratio: i128,
    -    pub strategies: Vec<Strategy>,
    +pub struct SwapDetailsExactIn {
    +    pub token_in: Address,
    +    pub token_out: Address,
    +    pub amount_in: i128,
    +    pub amount_out_min: i128,
    +    pub distribution: Vec<DexDistribution>,
    +    pub deadline: u64,
     }
     
     #[contracttype]
     #[derive(Clone, Debug, Eq, PartialEq)]
    -pub struct Investment {
    -    pub strategy: Address,
    -    pub amount: i128,
    -}
    \ No newline at end of file +pub struct SwapDetailsExactOut { + pub token_in: Address, + pub token_out: Address, + pub amount_out: i128, + pub amount_in_max: i128, + pub distribution: Vec<DexDistribution>, + pub deadline: u64, +} + +#[contracttype] +#[derive(Clone, Debug, Eq, PartialEq)] +pub struct DexDistribution { + pub protocol_id: String, + pub path: Vec<Address>, + pub parts: u32, +} + +// Workaround for Option<SwapDetails> as it is not supported by the contracttype macro +#[contracttype] +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum OptionalSwapDetailsExactIn { + Some(SwapDetailsExactIn), + None, +} + +// Workaround for Option<SwapDetails> as it is not supported by the contracttype macro +#[contracttype] +#[derive(Clone, Debug, Eq, PartialEq)] +pub enum OptionalSwapDetailsExactOut { + Some(SwapDetailsExactOut), + None, +} +
    \ No newline at end of file diff --git a/apps/rust_docs/src/defindex_vault/storage.rs.html b/apps/rust_docs/src/defindex_vault/storage.rs.html index 2025afc9..0800f774 100644 --- a/apps/rust_docs/src/defindex_vault/storage.rs.html +++ b/apps/rust_docs/src/defindex_vault/storage.rs.html @@ -1,4 +1,4 @@ -storage.rs - source
    1
    +storage.rs - source
    1
     2
     3
     4
    @@ -94,28 +94,65 @@
     94
     95
     96
    +97
    +98
    +99
    +100
    +101
    +102
    +103
    +104
    +105
    +106
    +107
    +108
    +109
    +110
    +111
    +112
    +113
    +114
    +115
     
    use soroban_sdk::{contracttype, Address, Env, Vec};
     
    -use crate::models::AssetAllocation;
    +use common::models::AssetStrategySet;
    +
    +const DAY_IN_LEDGERS: u32 = 17280;
    +const INSTANCE_BUMP_AMOUNT: u32 = 30 * DAY_IN_LEDGERS;
    +const INSTANCE_LIFETIME_THRESHOLD: u32 = INSTANCE_BUMP_AMOUNT - DAY_IN_LEDGERS;
    +
    +pub fn extend_instance_ttl(e: &Env) {
    +    e.storage()
    +        .instance()
    +        .extend_ttl(INSTANCE_LIFETIME_THRESHOLD, INSTANCE_BUMP_AMOUNT);
    +}
    +
     
     #[derive(Clone)]
     #[contracttype]
     enum DataKey {
    -    AssetAllocation(u32),      // AssetAllocation Addresse by index
    -    TotalAssets,     // Total number of tokens
    -    DeFindexReceiver,
    +    AssetStrategySet(u32), // AssetStrategySet Addresse by index
    +    TotalAssets,          // Total number of tokens
    +    DeFindexProtocolFeeReceiver,
         Factory,
         LastFeeAssessment,
    -    VaultShare,
    +    VaultFee,
     }
     
    +
    +
     // Assets Management
    -pub fn set_asset(e: &Env, index: u32, asset: &AssetAllocation) {
    -    e.storage().instance().set(&DataKey::AssetAllocation(index), asset);
    +pub fn set_asset(e: &Env, index: u32, asset: &AssetStrategySet) {
    +    e.storage()
    +        .instance()
    +        .set(&DataKey::AssetStrategySet(index), asset);
     }
     
    -pub fn get_asset(e: &Env, index: u32) -> AssetAllocation {
    -    e.storage().instance().get(&DataKey::AssetAllocation(index)).unwrap()
    +pub fn get_asset(e: &Env, index: u32) -> AssetStrategySet {
    +    e.storage()
    +        .instance()
    +        .get(&DataKey::AssetStrategySet(index))
    +        .unwrap()
     }
     
     pub fn set_total_assets(e: &Env, n: u32) {
    @@ -126,7 +163,7 @@
         e.storage().instance().get(&DataKey::TotalAssets).unwrap()
     }
     
    -pub fn get_assets(e: &Env) -> Vec<AssetAllocation> {
    +pub fn get_assets(e: &Env) -> Vec<AssetStrategySet> {
         let total_assets = get_total_assets(e);
         let mut assets = Vec::new(e);
         for i in 0..total_assets {
    @@ -136,31 +173,26 @@
     }
     
     // DeFindex Fee Receiver
    -pub fn set_defindex_receiver(e: &Env, address: &Address) {
    +pub fn set_defindex_protocol_fee_receiver(e: &Env, address: &Address) {
         e.storage()
             .instance()
    -        .set(&DataKey::DeFindexReceiver, address);
    +        .set(&DataKey::DeFindexProtocolFeeReceiver, address);
     }
     
    -pub fn get_defindex_receiver(e: &Env) -> Address {
    +pub fn get_defindex_protocol_fee_receiver(e: &Env) -> Address {
         e.storage()
             .instance()
    -        .get(&DataKey::DeFindexReceiver)
    +        .get(&DataKey::DeFindexProtocolFeeReceiver)
             .unwrap()
     }
     
     // DeFindex Factory
     pub fn set_factory(e: &Env, address: &Address) {
    -    e.storage()
    -        .instance()
    -        .set(&DataKey::Factory, address);
    +    e.storage().instance().set(&DataKey::Factory, address);
     }
     
     pub fn get_factory(e: &Env) -> Address {
    -    e.storage()
    -        .instance()
    -        .get(&DataKey::Factory)
    -        .unwrap()
    +    e.storage().instance().get(&DataKey::Factory).unwrap()
     }
     
     // Last Fee Assesment
    @@ -174,20 +206,26 @@
         e.storage()
             .instance()
             .get(&DataKey::LastFeeAssessment)
    -        .unwrap()
    +        .unwrap_or_else(|| {
    +            let timestamp = &e.ledger().timestamp();
    +            e.storage()
    +                .instance()
    +                .set(&DataKey::LastFeeAssessment, timestamp);
    +            timestamp.clone()
    +        })
     }
     
     // Vault Share
    -pub fn set_vault_share(e: &Env, vault_share: &u32) {
    +pub fn set_vault_fee(e: &Env, vault_fee: &u32) {
         e.storage()
             .instance()
    -        .set(&DataKey::VaultShare, vault_share);
    +        .set(&DataKey::VaultFee, vault_fee);
     }
     
    -pub fn get_vault_share(e: &Env) -> u32 {
    +pub fn get_vault_fee(e: &Env) -> u32 {
         e.storage()
             .instance()
    -        .get(&DataKey::VaultShare)
    +        .get(&DataKey::VaultFee)
             .unwrap()
     }
     
    \ No newline at end of file diff --git a/apps/rust_docs/src/defindex_vault/strategies.rs.html b/apps/rust_docs/src/defindex_vault/strategies.rs.html index 48e41ce2..54c1712d 100644 --- a/apps/rust_docs/src/defindex_vault/strategies.rs.html +++ b/apps/rust_docs/src/defindex_vault/strategies.rs.html @@ -1,4 +1,4 @@ -strategies.rs - source
    1
    +strategies.rs - source
    1
     2
     3
     4
    @@ -103,21 +103,101 @@
     103
     104
     105
    +106
    +107
    +108
    +109
    +110
    +111
    +112
    +113
    +114
    +115
    +116
    +117
    +118
    +119
    +120
    +121
    +122
    +123
    +124
    +125
    +126
    +127
    +128
    +129
    +130
    +131
    +132
    +133
    +134
    +135
    +136
    +137
    +138
    +139
    +140
    +141
    +142
    +143
    +144
    +145
    +146
    +147
    +148
    +149
    +150
    +151
    +152
    +153
    +154
    +155
    +156
    +157
    +158
    +159
    +160
    +161
    +162
    +163
    +164
    +165
    +166
    +167
    +168
    +169
    +170
    +171
     
    use defindex_strategy_core::DeFindexStrategyClient;
    -use soroban_sdk::{Env, Address};
    +use soroban_sdk::{Address, Env, vec, IntoVal, Symbol};
    +use soroban_sdk::auth::{ContractContext, InvokerContractAuthEntry, SubContractInvocation};
     
    -use crate::{models::{AssetAllocation, Strategy}, storage::{get_asset, get_assets, get_total_assets, set_asset}, ContractError};
    +
    +use crate::{
    +    storage::{get_asset, get_assets, get_total_assets, set_asset},
    +    ContractError,
    +};
    +
    +use common::models::{AssetStrategySet, Strategy};
     
     pub fn get_strategy_client(e: &Env, address: Address) -> DeFindexStrategyClient {
         DeFindexStrategyClient::new(&e, &address)
     }
     
     /// Finds the asset corresponding to the given strategy address.
    -pub fn get_strategy_asset(e: &Env, strategy_address: &Address) -> Result<AssetAllocation, ContractError> {
    +pub fn get_strategy_asset(
    +    e: &Env,
    +    strategy_address: &Address,
    +) -> Result<AssetStrategySet, ContractError> {
         let assets = get_assets(e);
     
         for asset in assets.iter() {
    -        if asset.strategies.iter().any(|strategy| &strategy.address == strategy_address) {
    +        if asset
    +            .strategies
    +            .iter()
    +            .any(|strategy| &strategy.address == strategy_address)
    +        {
                 return Ok(asset);
             }
         }
    @@ -125,21 +205,27 @@
         Err(ContractError::StrategyNotFound)
     }
     
    -/// Finds the AssetAllocation corresponding to the given asset address.
    -pub fn get_asset_allocation_from_address(e: &Env, asset_address: Address) -> Result<AssetAllocation, ContractError> {
    -    let assets = get_assets(e);
    +// /// Finds the AssetStrategySet corresponding to the given asset address.
    +// pub fn get_asset_allocation_from_address(
    +//     e: &Env,
    +//     asset_address: Address,
    +// ) -> Result<AssetStrategySet, ContractError> {
    +//     let assets = get_assets(e);
     
    -    for asset in assets.iter() {
    -        if asset.address == asset_address {
    -            return Ok(asset);
    -        }
    -    }
    +//     for asset in assets.iter() {
    +//         if asset.address == asset_address {
    +//             return Ok(asset);
    +//         }
    +//     }
     
    -    Err(ContractError::AssetNotFound)
    -}
    +//     Err(ContractError::AssetNotFound)
    +// }
     
    -/// Finds the strategy struct corresponding to the given strategy address within the given asset.
    -pub fn get_strategy_struct(strategy_address: &Address, asset: &AssetAllocation) -> Result<Strategy, ContractError> {
    +/// Finds the strategy struct corresponding to the given strategy address within the given asset.
    +pub fn get_strategy_struct(
    +    strategy_address: &Address,
    +    asset: &AssetStrategySet,
    +) -> Result<Strategy, ContractError> {
         asset
             .strategies
             .iter()
    @@ -207,4 +293,51 @@
     
         // If no strategy is found, return an error
         Err(ContractError::StrategyNotFound)
    -}
    \ No newline at end of file +} + +pub fn withdraw_from_strategy( + e: &Env, + strategy_address: &Address, + amount: &i128, +) -> Result<(), ContractError> { + let strategy_client = get_strategy_client(e, strategy_address.clone()); + + match strategy_client.try_withdraw(amount, &e.current_contract_address()) { + Ok(Ok(_)) => Ok(()), + Ok(Err(_)) | Err(_) => Err(ContractError::StrategyWithdrawError), + } +} + +pub fn invest_in_strategy( + e: &Env, + asset_address: &Address, + strategy_address: &Address, + amount: &i128, +) -> Result<(), ContractError> { + + // Now we will handle funds on behalf of the contract, not the caller (manager or user) + + e.authorize_as_current_contract(vec![ + &e, + InvokerContractAuthEntry::Contract(SubContractInvocation { + context: ContractContext { + contract: asset_address.clone(), + fn_name: Symbol::new(&e, "transfer"), + args: ( + e.current_contract_address(), + strategy_address, + amount.clone()).into_val(e), + + }, + sub_invocations: vec![&e], + }), + ]); + + + let strategy_client = get_strategy_client(&e, strategy_address.clone()); + + strategy_client.deposit(amount, &e.current_contract_address()); + + Ok(()) +} +
    \ No newline at end of file diff --git a/apps/rust_docs/src/defindex_vault/token/allowance.rs.html b/apps/rust_docs/src/defindex_vault/token/allowance.rs.html index d3455bdd..c3b53626 100644 --- a/apps/rust_docs/src/defindex_vault/token/allowance.rs.html +++ b/apps/rust_docs/src/defindex_vault/token/allowance.rs.html @@ -1,4 +1,4 @@ -allowance.rs - source
    1
    +allowance.rs - source
    1
     2
     3
     4
    diff --git a/apps/rust_docs/src/defindex_vault/token/balance.rs.html b/apps/rust_docs/src/defindex_vault/token/balance.rs.html
    index 4074548f..b75002ae 100644
    --- a/apps/rust_docs/src/defindex_vault/token/balance.rs.html
    +++ b/apps/rust_docs/src/defindex_vault/token/balance.rs.html
    @@ -1,4 +1,4 @@
    -balance.rs - source
    1
    +balance.rs - source
    1
     2
     3
     4
    @@ -38,8 +38,10 @@
     38
     39
     40
    +41
     
    use crate::token::storage_types::{DataKey, BALANCE_BUMP_AMOUNT, BALANCE_LIFETIME_THRESHOLD};
    -use soroban_sdk::{Address, Env};
    +use crate::ContractError;
    +use soroban_sdk::{Address, Env, panic_with_error};
     
     pub fn read_balance(e: &Env, addr: Address) -> i128 {
         let key = DataKey::Balance(addr);
    @@ -74,7 +76,7 @@
     pub fn spend_balance(e: &Env, addr: Address, amount: i128) {
         let balance = read_balance(e, addr.clone());
         if balance < amount {
    -        panic!("insufficient balance");
    +        panic_with_error!(&e, ContractError::InsufficientBalance);
         }
         write_balance(e, addr, balance - amount);
     }
    diff --git a/apps/rust_docs/src/defindex_vault/token/contract.rs.html b/apps/rust_docs/src/defindex_vault/token/contract.rs.html
    index fe98cce9..a59ef0b6 100644
    --- a/apps/rust_docs/src/defindex_vault/token/contract.rs.html
    +++ b/apps/rust_docs/src/defindex_vault/token/contract.rs.html
    @@ -1,4 +1,4 @@
    -contract.rs - source
    1
    +contract.rs - source
    1
     2
     3
     4
    @@ -150,12 +150,6 @@
     150
     151
     152
    -153
    -154
    -155
    -156
    -157
    -158
     
    //! This contract demonstrates a sample implementation of the Soroban token
     //! interface.
     use crate::token::allowance::{read_allowance, spend_allowance, write_allowance};
    @@ -169,6 +163,7 @@
     use soroban_sdk::token::{self, Interface as _};
     use soroban_sdk::{contract, contractimpl, Address, Env, String};
     use soroban_token_sdk::TokenUtils;
    +use crate::ContractError;
     
     fn check_nonnegative_amount(amount: i128) {
         if amount < 0 {
    @@ -212,13 +207,6 @@
         pub fn total_supply(e: Env) -> i128 {
             read_total_supply(&e)
         }
    -
    -    #[cfg(test)]
    -    pub fn get_allowance(e: Env, from: Address, spender: Address) -> Option<AllowanceValue> {
    -        let key = DataKey::Allowance(AllowanceDataKey { from, spender });
    -        let allowance = e.storage().temporary().get::<_, AllowanceValue>(&key);
    -        allowance
    -    }
     }
     
     #[contractimpl]
    diff --git a/apps/rust_docs/src/defindex_vault/token/metadata.rs.html b/apps/rust_docs/src/defindex_vault/token/metadata.rs.html
    index 2d561d84..53e165e2 100644
    --- a/apps/rust_docs/src/defindex_vault/token/metadata.rs.html
    +++ b/apps/rust_docs/src/defindex_vault/token/metadata.rs.html
    @@ -1,4 +1,4 @@
    -metadata.rs - source
    1
    +metadata.rs - source
    1
     2
     3
     4
    diff --git a/apps/rust_docs/src/defindex_vault/token/mod.rs.html b/apps/rust_docs/src/defindex_vault/token/mod.rs.html
    index 0f4c4db7..b660868a 100644
    --- a/apps/rust_docs/src/defindex_vault/token/mod.rs.html
    +++ b/apps/rust_docs/src/defindex_vault/token/mod.rs.html
    @@ -1,4 +1,4 @@
    -mod.rs - source
    1
    +mod.rs - source
    1
     2
     3
     4
    @@ -21,7 +21,7 @@
     mod total_supply;
     
     pub use contract::VaultToken;
    -pub use contract::VaultTokenClient;
    -pub use contract::{internal_burn, internal_mint};
    +// pub use contract::VaultTokenClient;
    +pub use contract::{internal_burn, internal_mint};
     pub use metadata::write_metadata;
     
    \ No newline at end of file diff --git a/apps/rust_docs/src/defindex_vault/token/storage_types.rs.html b/apps/rust_docs/src/defindex_vault/token/storage_types.rs.html index a1f90d28..511fe0f9 100644 --- a/apps/rust_docs/src/defindex_vault/token/storage_types.rs.html +++ b/apps/rust_docs/src/defindex_vault/token/storage_types.rs.html @@ -1,4 +1,4 @@ -storage_types.rs - source
    1
    +storage_types.rs - source
    1
     2
     3
     4
    diff --git a/apps/rust_docs/src/defindex_vault/token/total_supply.rs.html b/apps/rust_docs/src/defindex_vault/token/total_supply.rs.html
    index 94867ce3..b3062e29 100644
    --- a/apps/rust_docs/src/defindex_vault/token/total_supply.rs.html
    +++ b/apps/rust_docs/src/defindex_vault/token/total_supply.rs.html
    @@ -1,4 +1,4 @@
    -total_supply.rs - source
    1
    +total_supply.rs - source
    1
     2
     3
     4
    diff --git a/apps/rust_docs/src/defindex_vault/utils.rs.html b/apps/rust_docs/src/defindex_vault/utils.rs.html
    index 53f152a2..32207785 100644
    --- a/apps/rust_docs/src/defindex_vault/utils.rs.html
    +++ b/apps/rust_docs/src/defindex_vault/utils.rs.html
    @@ -1,4 +1,4 @@
    -utils.rs - source
    1
    +utils.rs - source
    1
     2
     3
     4
    @@ -254,12 +254,39 @@
     254
     255
     256
    +257
    +258
    +259
    +260
    +261
    +262
    +263
    +264
    +265
    +266
    +267
    +268
    +269
    +270
    +271
    +272
    +273
    +274
    +275
    +276
    +277
     
    use soroban_sdk::{panic_with_error, Address, Env, Map, Vec};
     
     use crate::{
    -    access::{AccessControl, AccessControlTrait, RolesDataKey}, funds::{fetch_invested_funds_for_asset, fetch_invested_funds_for_strategy, fetch_total_managed_funds}, models::AssetAllocation, token::VaultToken, ContractError
    -
    +    models::{CurrentAssetInvestmentAllocation},
    +    access::{AccessControl, AccessControlTrait, RolesDataKey},
    +    funds::{
    +        fetch_total_managed_funds,
    +    },
    +    token::VaultToken,
    +    ContractError,
     };
    +use common::models::AssetStrategySet;
     
     pub const DAY_IN_LEDGERS: u32 = 17280;
     
    @@ -288,89 +315,122 @@
         }
     }
     
    -/// From an amount, calculates how much to withdraw from each strategy;
    -/// returns a map of strategy address to token amount
    -pub fn calculate_withdrawal_amounts(
    -    e: &Env,
    -    amount: i128,
    -    asset: AssetAllocation,
    -) -> Map<Address, i128> {
    -    let mut withdrawal_amounts = Map::<Address, i128>::new(e);
    +// /// From an amount, calculates how much to withdraw from each strategy;
    +// /// returns a map of strategy address to token amount
    +// pub fn calculate_withdrawal_amounts(
    +//     e: &Env,
    +//     amount: i128,
    +//     asset: AssetStrategySet,
    +// ) -> Map<Address, i128> {
    +//     let mut withdrawal_amounts = Map::<Address, i128>::new(e);
     
    -    let total_invested_in_strategies: i128 = fetch_invested_funds_for_asset(&e, &asset);
    +//     let (total_invested_in_strategies, _) = fetch_invested_funds_for_asset(&e, &asset);
     
    -    for strategy in asset.strategies.iter() {
    -        // TODO: if strategy is paused but still holds assets on it shouldnt we withdraw them?
    -        if strategy.paused {
    -            continue;
    -        }
    +//     for strategy in asset.strategies.iter() {
    +//         // TODO: if strategy is paused but still holds assets on it shouldnt we withdraw them?
    +//         if strategy.paused {
    +//             continue;
    +//         }
     
    -        let strategy_invested_funds = fetch_invested_funds_for_strategy(e, &strategy.address);
    +//         let strategy_invested_funds = fetch_invested_funds_for_strategy(e, &strategy.address);
     
    -        let strategy_share_of_withdrawal = (amount * strategy_invested_funds) / total_invested_in_strategies;
    +//         let strategy_share_of_withdrawal =
    +//             (amount * strategy_invested_funds) / total_invested_in_strategies;
     
    -        withdrawal_amounts.set(strategy.address.clone(), strategy_share_of_withdrawal);
    -    }
    +//         withdrawal_amounts.set(strategy.address.clone(), strategy_share_of_withdrawal);
    +//     }
     
    -    withdrawal_amounts
    -}
    +//     withdrawal_amounts
    +// }
     
    -pub fn calculate_asset_amounts_for_dftokens(
    +/// Calculates the corresponding amounts of each asset per given number of vault shares.
    +/// This function takes the number of vault shares (`shares_amount`) and computes how much of each asset in the vault
    +/// corresponds to those shares, based on the total managed funds and the total supply of vault shares.
    +///
    +/// # Arguments
    +/// * `env` - Reference to the current environment.
    +/// * `shares_amount` - The number of vault shares for which the equivalent asset amounts are being calculated.
    +///
    +/// # Returns
    +/// * `Map<Address, i128>` - A map of asset addresses to their respective amounts, proportional to the `shares_amount`.
    +///
    +/// # Errors
    +/// * Panics with `ContractError::ArithmeticError` if there are any issues with multiplication or division,
    +///   such as overflow or division by zero.
    +pub fn calculate_asset_amounts_per_vault_shares(
         env: &Env,
    -    df_token_amount: i128,
    -) -> Map<Address, i128> {
    -    let mut asset_amounts: Map<Address, i128> = Map::new(&env);
    -    let total_supply = VaultToken::total_supply(env.clone());
    -    let total_managed_funds = fetch_total_managed_funds(&env);
    -
    -    // Iterate over each asset and calculate the corresponding amount based on df_token_amount
    -    for (asset_address, amount) in total_managed_funds.iter() {
    -        let asset_amount = (amount * df_token_amount) / total_supply;
    -        asset_amounts.set(asset_address.clone(), asset_amount);
    -    }
    +    shares_amount: i128,
    +    total_managed_funds: &Map<Address, CurrentAssetInvestmentAllocation>,
    +) -> Result<Map<Address, i128>, ContractError> {
    +    let mut asset_amounts: Map<Address, i128> = Map::new(env);
     
    -    asset_amounts
    -}
    +    // Fetch the total supply of vault shares and the total managed funds for each asset
    +    let total_shares_supply = VaultToken::total_supply(env.clone());
     
    -pub fn calculate_dftokens_from_asset_amounts(
    -    env: &Env,
    -    asset_amounts: Map<Address, i128>, // The input asset amounts
    -) -> Result<i128, ContractError> {
    -    let total_supply = VaultToken::total_supply(env.clone()); // Total dfToken supply
    -    let total_managed_funds = fetch_total_managed_funds(&env); // Fetch all managed assets
    -
    -    // Initialize the minimum dfTokens corresponding to each asset
    -    let mut min_df_tokens: Option<i128> = None;
    -
    -    // Iterate over each asset in the input map
    -    for (asset_address, input_amount) in asset_amounts.iter() {
    -        // Get the total managed amount for this asset
    -        let managed_amount = total_managed_funds.get(asset_address.clone()).unwrap_or(0);
    -
    -        // Ensure the managed amount is not zero to prevent division by zero
    -        if managed_amount == 0 {
    -            return Err(ContractError::InsufficientManagedFunds);
    -        }
    -
    -        // Calculate the dfTokens corresponding to this asset's amount
    -        let df_tokens_for_asset = (input_amount * total_supply) / managed_amount;
    +    // if shares amount over total supply, return error AmountOverTotalSupply
    +    if shares_amount > total_shares_supply {
    +        return Err(ContractError::AmountOverTotalSupply);
    +    }
     
    -        // If this is the first asset or if the calculated df_tokens_for_asset is smaller, update the minimum df_tokens
    -        if let Some(current_min_df_tokens) = min_df_tokens {
    -            min_df_tokens = Some(current_min_df_tokens.min(df_tokens_for_asset));
    -        } else {
    -            min_df_tokens = Some(df_tokens_for_asset);
    -        }
    +    // Iterate over each asset and calculate the corresponding amount based on shares_amount
    +    for (asset_address, current_asset_allocation) in total_managed_funds.iter() {
    +        // Calculate the proportional asset amount per the given number of shares
    +        let asset_amount = if total_shares_supply != 0 {
    +            current_asset_allocation.total_amount
    +                .checked_mul(shares_amount)
    +                .ok_or(ContractError::ArithmeticError)?
    +                .checked_div(total_shares_supply)
    +                .ok_or(ContractError::ArithmeticError)?
    +        } else {
    +            return Err(ContractError::AmountOverTotalSupply);
    +        };
    +
    +        // Set the calculated asset amount for the given asset address
    +        asset_amounts.set(asset_address.clone(), asset_amount);
         }
     
    -    // Return the minimum dfTokens across all assets
    -    min_df_tokens.ok_or(ContractError::NoAssetsProvided)
    +    return Ok(asset_amounts);
     }
     
    -pub fn calculate_optimal_amounts_and_shares_with_enforced_asset(
    +// pub fn calculate_dftokens_from_asset_amounts(
    +//     env: &Env,
    +//     asset_amounts: Map<Address, i128>, // The input asset amounts
    +//     total_managed_funds: Map<Address, i128>, // The total managed funds for each asset
    +// ) -> Result<i128, ContractError> {
    +//     let total_supply = VaultToken::total_supply(env.clone()); // Total dfToken supply
    +
    +//     // Initialize the minimum dfTokens corresponding to each asset
    +//     let mut min_df_tokens: Option<i128> = None;
    +
    +//     // Iterate over each asset in the input map
    +//     for (asset_address, input_amount) in asset_amounts.iter() {
    +//         // Get the total managed amount for this asset
    +//         let managed_amount = total_managed_funds.get(asset_address.clone()).unwrap_or(0);
    +
    +//         // Ensure the managed amount is not zero to prevent division by zero
    +//         if managed_amount == 0 {
    +//             return Err(ContractError::InsufficientManagedFunds);
    +//         }
    +
    +//         // Calculate the dfTokens corresponding to this asset's amount
    +//         let df_tokens_for_asset = (input_amount * total_supply) / managed_amount;
    +
    +//         // If this is the first asset or if the calculated df_tokens_for_asset is smaller, update the minimum df_tokens
    +//         if let Some(current_min_df_tokens) = min_df_tokens {
    +//             min_df_tokens = Some(current_min_df_tokens.min(df_tokens_for_asset));
    +//         } else {
    +//             min_df_tokens = Some(df_tokens_for_asset);
    +//         }
    +//     }
    +
    +//     // Return the minimum dfTokens across all assets
    +//     min_df_tokens.ok_or(ContractError::NoAssetsProvided)
    +// }
    +
    +pub fn calculate_optimal_amounts_and_shares_with_enforced_asset(
         e: &Env,
    -    total_managed_funds: &Map<Address, i128>,
    -    assets: &Vec<AssetAllocation>,
    +    total_managed_funds: &Map<Address, CurrentAssetInvestmentAllocation>,
    +    assets: &Vec<AssetStrategySet>,
         amounts_desired: &Vec<i128>,
         i: &u32,
     ) -> (Vec<i128>, i128) {
    @@ -378,48 +438,57 @@
         // we need the total amount managed by this vault in order for the deposit to be proportional
         // reserve (total manage funds) of the asset we are enforcing
         let reserve_target = total_managed_funds
    -        .get(assets.get(*i).unwrap().address)
    -        .unwrap(); // i128
    +        .get(assets.get(*i).unwrap_or_else(|| panic_with_error!(&e, ContractError::WrongAmountsLength)).address)
    +        .unwrap_or_else(|| panic_with_error!(&e, ContractError::WrongAmountsLength))
    +        .total_amount;
    +
    +    // If reserve target is zero, we cannot calculate the optimal amounts
         if reserve_target == 0 {
    -        // return sum of amounts desired as shares
    -        return (amounts_desired.clone(), amounts_desired.iter().sum()); // first shares will be equal to the first amounts_desired
    -                                                                        // TODO, this amounts desired might be too little?
    -                                                                        // this might be the first deposit... in this case, the ratio will be enforced by the first depositor
    -                                                                        // TODO: might happen that the reserve_target is zero because everything is in one asset!?
    -                                                                        // in this case we ned to check the ratio
    -        // TODO VERY DANGEROUS.
    -    }
    -    let amount_desired_target = amounts_desired.get(*i).unwrap(); // i128
    -
    -    let mut optimal_amounts = Vec::new(e);
    -
    -    for (j, (_asset_address, reserve)) in total_managed_funds.iter().enumerate() {
    +        panic_with_error!(&e, ContractError::InsufficientManagedFunds);
    +    }
    +
    +    let amount_desired_target = amounts_desired.get(*i).unwrap_or_else(|| panic_with_error!(&e, ContractError::WrongAmountsLength));
    +
    +    let mut optimal_amounts = Vec::new(e);
    +    
    +    for (j, asset) in assets.iter().enumerate() {
             if j == (*i as usize) {
                 optimal_amounts.push_back(amount_desired_target);
             } else {
    -            // amount = amount_desired_target * reserve[j] / reserve_target
    -            // factor is (amount_desired_target  / reserve_target;)
    -            let amount = reserve * amount_desired_target / reserve_target;
    -            optimal_amounts.push_back(amount);
    +            let reserve = total_managed_funds
    +                            .get(asset.address).unwrap_or_else(|| panic_with_error!(&e, ContractError::WrongAmountsLength))
    +                            .total_amount;
    +            let amount = reserve.checked_mul(amount_desired_target)
    +                .unwrap_or_else(|| panic_with_error!(&e, ContractError::ArithmeticError))
    +                .checked_div(reserve_target)
    +                .unwrap_or_else(|| panic_with_error!(&e, ContractError::ArithmeticError));
    +            optimal_amounts.push_back(amount);  
             }
         }
    +
         //TODO: calculate the shares to mint = total_supply * amount_desired_target  / reserve_target
    -    let shares_to_mint = VaultToken::total_supply(e.clone()) * amount_desired_target / reserve_target;
    +    let shares_to_mint =
    +        VaultToken::total_supply(e.clone())
    +        .checked_mul(amount_desired_target)
    +        .unwrap_or_else(|| panic_with_error!(&e, ContractError::ArithmeticError))
    +        .checked_div(reserve_target)
    +        .unwrap_or_else(|| panic_with_error!(&e, ContractError::ArithmeticError));
    +        
         (optimal_amounts, shares_to_mint)
     }
     /// Calculates the optimal amounts to deposit for a set of assets, along with the shares to mint.
     /// This function iterates over a list of assets and checks if the desired deposit amounts
     /// match the optimal deposit strategy, based on current managed funds and asset ratios.
    -/// 
    +///
     /// If the desired amount for a given asset cannot be achieved due to constraints (e.g., it's below the minimum amount),
     /// the function attempts to find an optimal solution by adjusting the amounts of subsequent assets.
    -/// 
    +///
     /// # Arguments
     /// * `e` - The current environment.
     /// * `assets` - A vector of assets for which deposits are being calculated.
     /// * `amounts_desired` - A vector of desired amounts for each asset.
     /// * `amounts_min` - A vector of minimum amounts for each asset, below which deposits are not allowed.
    -/// 
    +///
     /// # Returns
     /// A tuple containing:
     /// * A vector of optimal amounts to deposit for each asset.
    @@ -434,79 +503,53 @@
     /// be replaced with proper error handling.
     pub fn calculate_deposit_amounts_and_shares_to_mint(
         e: &Env,
    -    assets: &Vec<AssetAllocation>,
    +    assets: &Vec<AssetStrategySet>,
         amounts_desired: &Vec<i128>,
         amounts_min: &Vec<i128>,
    -) -> (Vec<i128>, i128) {
    +) -> Result<(Vec<i128>, i128), ContractError> {
         // Retrieve the total managed funds for each asset as a Map<Address, i128>.
    -    let total_managed_funds = fetch_total_managed_funds(e); 
    -
    -    // Iterate over each asset in the assets vector.
    -    for i in 0..assets.len() {
    -        // Calculate the optimal amounts and the number of shares to mint for the given asset at index `i`.
    -        let (optimal_amounts, shares_to_mint) =
    -            calculate_optimal_amounts_and_shares_with_enforced_asset(
    -                &e,
    -                &total_managed_funds,
    -                &assets,
    -                &amounts_desired,
    -                &i,
    -            );
    -
    -        // Flag to skip the current asset if necessary.
    -        let mut should_skip = false;
    -
    -        // Check if the calculated optimal amounts meet the desired or minimum requirements.
    -        for j in i + 1..assets.len() {
    -            // If the optimal amount for asset[j] is less than the desired amount,
    -            // but at least greater than the minimum amount, it is acceptable.
    -            if optimal_amounts.get(j).unwrap() <= amounts_desired.get(j).unwrap() {
    -                // If the optimal amount is below the minimum, we cannot proceed with this asset.
    -                if optimal_amounts.get(j).unwrap() < amounts_min.get(j).unwrap() {
    -                    panic!("insufficient amount"); // TODO: Replace panic with an error return.
    +    let total_managed_funds = fetch_total_managed_funds(e);
    +
    +    for i in 0..assets.len() {
    +        // Calculate the optimal amounts and shares to mint for asset `i`.
    +        let (optimal_amounts, shares_to_mint) = calculate_optimal_amounts_and_shares_with_enforced_asset(
    +            &e,
    +            &total_managed_funds,
    +            &assets,
    +            &amounts_desired,
    +            &i,
    +        );
    +
    +        let mut should_skip = false;
    +
    +        for j in i + 1..assets.len() {
    +            // Retrieve the desired and minimum amounts, returning an error if unavailable.
    +            let desired_amount = amounts_desired.get(j).ok_or(ContractError::WrongAmountsLength)?;
    +            let min_amount = amounts_min.get(j).ok_or(ContractError::WrongAmountsLength)?;
    +            let optimal_amount = optimal_amounts.get(j).ok_or(ContractError::WrongAmountsLength)?;
    +
    +            // Check if optimal amount meets the desired or minimum requirements.
    +            if optimal_amount <= desired_amount {
    +                if optimal_amount < min_amount {
    +                    return Err(ContractError::InsufficientAmount); // Insufficient amount error.
                     }
    -            } else {
    -                // If the optimal amount exceeds the desired amount, we skip the current asset {i}.
    +            } else { // if not, we should try the next asset as enforced asset
                     should_skip = true;
    -
    -                // If we've reached the last asset and still don't find a solution, throw an error.
    -                if j == assets.len() - 1 {
    -                    panic!("didn't find optimal amounts"); // TODO: Replace panic with an error return.
    +                // If we have already analized all assets as enforced (i), return an error.
    +                if i == assets.len() - 1 {
    +                    return Err(ContractError::NoOptimalAmounts); // probably enforcing 0? We should never reach this point
                     }
                     break;
                 }
             }
     
    -        // If we should skip this asset, continue to the next one.
    -        if should_skip {
    -            continue;
    -        } else {
    -            // Return the calculated optimal amounts and shares to mint.
    -            return (optimal_amounts, shares_to_mint);
    +        // If valid amounts found, return the results; otherwise, skip to the next asset.
    +        if !should_skip {
    +            return Ok((optimal_amounts, shares_to_mint));
             }
         }
     
    -    // If no solution was found after iterating through all assets, throw an error.
    -    panic!("didn't find optimal amounts");
    +    // Return an error if no valid deposit configuration is found.
    +    Err(ContractError::NoOptimalAmounts)
     }
    -
    -// Calculates the amounts to invest in each strategy based on the current ratio of invested funds.
    -// The function returns a Vec<Investment> where each element contains a strategy address and the amount to be invested.
    -//
    -// # Parameters
    -// - `e`: The environment object, containing all relevant contract data.
    -//
    -// # Returns
    -// A Vec of `Investment` structs, each containing a strategy address and the calculated amount to invest.
    -// pub fn calculate_investments_based_on_ratios(
    -//     e: &Env,
    -// ) -> Result<Vec<Investment>, ContractError> {
    -//     // i should get all managed funds
    -//     let total_managed_funds = get_total_managed_funds(e);
    -
    -    
    -//     // Create a vector to store the investment amounts for each strategy
    -//     let mut investments: Vec<Investment> = Vec::new(e);
    -
    -//     Ok(investments)
    -// }
    \ No newline at end of file +
    \ No newline at end of file diff --git a/apps/rust_docs/static.files/main-921df33f47b8780c.js b/apps/rust_docs/static.files/main-921df33f47b8780c.js new file mode 100644 index 00000000..c3155548 --- /dev/null +++ b/apps/rust_docs/static.files/main-921df33f47b8780c.js @@ -0,0 +1,11 @@ +"use strict";window.RUSTDOC_TOOLTIP_HOVER_MS=300;window.RUSTDOC_TOOLTIP_HOVER_EXIT_MS=450;function resourcePath(basename,extension){return getVar("root-path")+basename+getVar("resource-suffix")+extension}function hideMain(){addClass(document.getElementById(MAIN_ID),"hidden")}function showMain(){removeClass(document.getElementById(MAIN_ID),"hidden")}function blurHandler(event,parentElem,hideCallback){if(!parentElem.contains(document.activeElement)&&!parentElem.contains(event.relatedTarget)){hideCallback()}}window.rootPath=getVar("root-path");window.currentCrate=getVar("current-crate");function setMobileTopbar(){const mobileTopbar=document.querySelector(".mobile-topbar");const locationTitle=document.querySelector(".sidebar h2.location");if(mobileTopbar){const mobileTitle=document.createElement("h2");mobileTitle.className="location";if(hasClass(document.querySelector(".rustdoc"),"crate")){mobileTitle.innerHTML=`Crate ${window.currentCrate}`}else if(locationTitle){mobileTitle.innerHTML=locationTitle.innerHTML}mobileTopbar.appendChild(mobileTitle)}}function getVirtualKey(ev){if("key"in ev&&typeof ev.key!=="undefined"){return ev.key}const c=ev.charCode||ev.keyCode;if(c===27){return"Escape"}return String.fromCharCode(c)}const MAIN_ID="main-content";const SETTINGS_BUTTON_ID="settings-menu";const ALTERNATIVE_DISPLAY_ID="alternative-display";const NOT_DISPLAYED_ID="not-displayed";const HELP_BUTTON_ID="help-button";function getSettingsButton(){return document.getElementById(SETTINGS_BUTTON_ID)}function getHelpButton(){return document.getElementById(HELP_BUTTON_ID)}function getNakedUrl(){return window.location.href.split("?")[0].split("#")[0]}function insertAfter(newNode,referenceNode){referenceNode.parentNode.insertBefore(newNode,referenceNode.nextSibling)}function getOrCreateSection(id,classes){let el=document.getElementById(id);if(!el){el=document.createElement("section");el.id=id;el.className=classes;insertAfter(el,document.getElementById(MAIN_ID))}return el}function getAlternativeDisplayElem(){return getOrCreateSection(ALTERNATIVE_DISPLAY_ID,"content hidden")}function getNotDisplayedElem(){return getOrCreateSection(NOT_DISPLAYED_ID,"hidden")}function switchDisplayedElement(elemToDisplay){const el=getAlternativeDisplayElem();if(el.children.length>0){getNotDisplayedElem().appendChild(el.firstElementChild)}if(elemToDisplay===null){addClass(el,"hidden");showMain();return}el.appendChild(elemToDisplay);hideMain();removeClass(el,"hidden")}function browserSupportsHistoryApi(){return window.history&&typeof window.history.pushState==="function"}function preLoadCss(cssUrl){const link=document.createElement("link");link.href=cssUrl;link.rel="preload";link.as="style";document.getElementsByTagName("head")[0].appendChild(link)}(function(){const isHelpPage=window.location.pathname.endsWith("/help.html");function loadScript(url,errorCallback){const script=document.createElement("script");script.src=url;if(errorCallback!==undefined){script.onerror=errorCallback}document.head.append(script)}getSettingsButton().onclick=event=>{if(event.ctrlKey||event.altKey||event.metaKey){return}window.hideAllModals(false);addClass(getSettingsButton(),"rotate");event.preventDefault();loadScript(getVar("static-root-path")+getVar("settings-js"));setTimeout(()=>{const themes=getVar("themes").split(",");for(const theme of themes){if(theme!==""){preLoadCss(getVar("root-path")+theme+".css")}}},0)};window.searchState={loadingText:"Loading search results...",input:document.getElementsByClassName("search-input")[0],outputElement:()=>{let el=document.getElementById("search");if(!el){el=document.createElement("section");el.id="search";getNotDisplayedElem().appendChild(el)}return el},title:document.title,titleBeforeSearch:document.title,timeout:null,currentTab:0,focusedByTab:[null,null,null],clearInputTimeout:()=>{if(searchState.timeout!==null){clearTimeout(searchState.timeout);searchState.timeout=null}},isDisplayed:()=>searchState.outputElement().parentElement.id===ALTERNATIVE_DISPLAY_ID,focus:()=>{searchState.input.focus()},defocus:()=>{searchState.input.blur()},showResults:search=>{if(search===null||typeof search==="undefined"){search=searchState.outputElement()}switchDisplayedElement(search);searchState.mouseMovedAfterSearch=false;document.title=searchState.title},removeQueryParameters:()=>{document.title=searchState.titleBeforeSearch;if(browserSupportsHistoryApi()){history.replaceState(null,"",getNakedUrl()+window.location.hash)}},hideResults:()=>{switchDisplayedElement(null);searchState.removeQueryParameters()},getQueryStringParams:()=>{const params={};window.location.search.substring(1).split("&").map(s=>{const pair=s.split("=").map(x=>x.replace(/\+/g," "));params[decodeURIComponent(pair[0])]=typeof pair[1]==="undefined"?null:decodeURIComponent(pair[1])});return params},setup:()=>{const search_input=searchState.input;if(!searchState.input){return}let searchLoaded=false;function sendSearchForm(){document.getElementsByClassName("search-form")[0].submit()}function loadSearch(){if(!searchLoaded){searchLoaded=true;loadScript(getVar("static-root-path")+getVar("search-js"),sendSearchForm);loadScript(resourcePath("search-index",".js"),sendSearchForm)}}search_input.addEventListener("focus",()=>{search_input.origPlaceholder=search_input.placeholder;search_input.placeholder="Type your search here.";loadSearch()});if(search_input.value!==""){loadSearch()}const params=searchState.getQueryStringParams();if(params.search!==undefined){searchState.setLoadingSearch();loadSearch()}},setLoadingSearch:()=>{const search=searchState.outputElement();search.innerHTML="

    "+searchState.loadingText+"

    ";searchState.showResults(search)},descShards:new Map(),loadDesc:async function({descShard,descIndex}){if(descShard.promise===null){descShard.promise=new Promise((resolve,reject)=>{descShard.resolve=resolve;const ds=descShard;const fname=`${ds.crate}-desc-${ds.shard}-`;const url=resourcePath(`search.desc/${descShard.crate}/${fname}`,".js",);loadScript(url,reject)})}const list=await descShard.promise;return list[descIndex]},loadedDescShard:function(crate,shard,data){this.descShards.get(crate)[shard].resolve(data.split("\n"))},};const toggleAllDocsId="toggle-all-docs";let savedHash="";function handleHashes(ev){if(ev!==null&&searchState.isDisplayed()&&ev.newURL){switchDisplayedElement(null);const hash=ev.newURL.slice(ev.newURL.indexOf("#")+1);if(browserSupportsHistoryApi()){history.replaceState(null,"",getNakedUrl()+window.location.search+"#"+hash)}const elem=document.getElementById(hash);if(elem){elem.scrollIntoView()}}const pageId=window.location.hash.replace(/^#/,"");if(savedHash!==pageId){savedHash=pageId;if(pageId!==""){expandSection(pageId)}}if(savedHash.startsWith("impl-")){const splitAt=savedHash.indexOf("/");if(splitAt!==-1){const implId=savedHash.slice(0,splitAt);const assocId=savedHash.slice(splitAt+1);const implElems=document.querySelectorAll(`details > summary > section[id^="${implId}"]`,);onEachLazy(implElems,implElem=>{const numbered=/^(.+?)-([0-9]+)$/.exec(implElem.id);if(implElem.id!==implId&&(!numbered||numbered[1]!==implId)){return false}return onEachLazy(implElem.parentElement.parentElement.querySelectorAll(`[id^="${assocId}"]`),item=>{const numbered=/^(.+?)-([0-9]+)$/.exec(item.id);if(item.id===assocId||(numbered&&numbered[1]===assocId)){openParentDetails(item);item.scrollIntoView();setTimeout(()=>{window.location.replace("#"+item.id)},0);return true}},)})}}}function onHashChange(ev){hideSidebar();handleHashes(ev)}function openParentDetails(elem){while(elem){if(elem.tagName==="DETAILS"){elem.open=true}elem=elem.parentNode}}function expandSection(id){openParentDetails(document.getElementById(id))}function handleEscape(ev){searchState.clearInputTimeout();searchState.hideResults();ev.preventDefault();searchState.defocus();window.hideAllModals(true)}function handleShortcut(ev){const disableShortcuts=getSettingValue("disable-shortcuts")==="true";if(ev.ctrlKey||ev.altKey||ev.metaKey||disableShortcuts){return}if(document.activeElement.tagName==="INPUT"&&document.activeElement.type!=="checkbox"&&document.activeElement.type!=="radio"){switch(getVirtualKey(ev)){case"Escape":handleEscape(ev);break}}else{switch(getVirtualKey(ev)){case"Escape":handleEscape(ev);break;case"s":case"S":case"/":ev.preventDefault();searchState.focus();break;case"+":ev.preventDefault();expandAllDocs();break;case"-":ev.preventDefault();collapseAllDocs();break;case"?":showHelp();break;default:break}}}document.addEventListener("keypress",handleShortcut);document.addEventListener("keydown",handleShortcut);function addSidebarItems(){if(!window.SIDEBAR_ITEMS){return}const sidebar=document.getElementsByClassName("sidebar-elems")[0];function block(shortty,id,longty){const filtered=window.SIDEBAR_ITEMS[shortty];if(!filtered){return}const modpath=hasClass(document.querySelector(".rustdoc"),"mod")?"../":"";const h3=document.createElement("h3");h3.innerHTML=`${longty}`;const ul=document.createElement("ul");ul.className="block "+shortty;for(const name of filtered){let path;if(shortty==="mod"){path=`${modpath}${name}/index.html`}else{path=`${modpath}${shortty}.${name}.html`}let current_page=document.location.href.toString();if(current_page.endsWith("/")){current_page+="index.html"}const link=document.createElement("a");link.href=path;link.textContent=name;const li=document.createElement("li");if(link.href===current_page){li.classList.add("current")}li.appendChild(link);ul.appendChild(li)}sidebar.appendChild(h3);sidebar.appendChild(ul)}if(sidebar){block("primitive","primitives","Primitive Types");block("mod","modules","Modules");block("macro","macros","Macros");block("struct","structs","Structs");block("enum","enums","Enums");block("constant","constants","Constants");block("static","static","Statics");block("trait","traits","Traits");block("fn","functions","Functions");block("type","types","Type Aliases");block("union","unions","Unions");block("foreigntype","foreign-types","Foreign Types");block("keyword","keywords","Keywords");block("attr","attributes","Attribute Macros");block("derive","derives","Derive Macros");block("traitalias","trait-aliases","Trait Aliases")}}window.register_implementors=imp=>{const implementors=document.getElementById("implementors-list");const synthetic_implementors=document.getElementById("synthetic-implementors-list");const inlined_types=new Set();const TEXT_IDX=0;const SYNTHETIC_IDX=1;const TYPES_IDX=2;if(synthetic_implementors){onEachLazy(synthetic_implementors.getElementsByClassName("impl"),el=>{const aliases=el.getAttribute("data-aliases");if(!aliases){return}aliases.split(",").forEach(alias=>{inlined_types.add(alias)})})}let currentNbImpls=implementors.getElementsByClassName("impl").length;const traitName=document.querySelector(".main-heading h1 > .trait").textContent;const baseIdName="impl-"+traitName+"-";const libs=Object.getOwnPropertyNames(imp);const script=document.querySelector("script[data-ignore-extern-crates]");const ignoreExternCrates=new Set((script?script.getAttribute("data-ignore-extern-crates"):"").split(","),);for(const lib of libs){if(lib===window.currentCrate||ignoreExternCrates.has(lib)){continue}const structs=imp[lib];struct_loop:for(const struct of structs){const list=struct[SYNTHETIC_IDX]?synthetic_implementors:implementors;if(struct[SYNTHETIC_IDX]){for(const struct_type of struct[TYPES_IDX]){if(inlined_types.has(struct_type)){continue struct_loop}inlined_types.add(struct_type)}}const code=document.createElement("h3");code.innerHTML=struct[TEXT_IDX];addClass(code,"code-header");onEachLazy(code.getElementsByTagName("a"),elem=>{const href=elem.getAttribute("href");if(href&&!href.startsWith("#")&&!/^(?:[a-z+]+:)?\/\//.test(href)){elem.setAttribute("href",window.rootPath+href)}});const currentId=baseIdName+currentNbImpls;const anchor=document.createElement("a");anchor.href="#"+currentId;addClass(anchor,"anchor");const display=document.createElement("div");display.id=currentId;addClass(display,"impl");display.appendChild(anchor);display.appendChild(code);list.appendChild(display);currentNbImpls+=1}}};if(window.pending_implementors){window.register_implementors(window.pending_implementors)}window.register_type_impls=imp=>{if(!imp||!imp[window.currentCrate]){return}window.pending_type_impls=null;const idMap=new Map();let implementations=document.getElementById("implementations-list");let trait_implementations=document.getElementById("trait-implementations-list");let trait_implementations_header=document.getElementById("trait-implementations");const script=document.querySelector("script[data-self-path]");const selfPath=script?script.getAttribute("data-self-path"):null;const mainContent=document.querySelector("#main-content");const sidebarSection=document.querySelector(".sidebar section");let methods=document.querySelector(".sidebar .block.method");let associatedTypes=document.querySelector(".sidebar .block.associatedtype");let associatedConstants=document.querySelector(".sidebar .block.associatedconstant");let sidebarTraitList=document.querySelector(".sidebar .block.trait-implementation");for(const impList of imp[window.currentCrate]){const types=impList.slice(2);const text=impList[0];const isTrait=impList[1]!==0;const traitName=impList[1];if(types.indexOf(selfPath)===-1){continue}let outputList=isTrait?trait_implementations:implementations;if(outputList===null){const outputListName=isTrait?"Trait Implementations":"Implementations";const outputListId=isTrait?"trait-implementations-list":"implementations-list";const outputListHeaderId=isTrait?"trait-implementations":"implementations";const outputListHeader=document.createElement("h2");outputListHeader.id=outputListHeaderId;outputListHeader.innerText=outputListName;outputList=document.createElement("div");outputList.id=outputListId;if(isTrait){const link=document.createElement("a");link.href=`#${outputListHeaderId}`;link.innerText="Trait Implementations";const h=document.createElement("h3");h.appendChild(link);trait_implementations=outputList;trait_implementations_header=outputListHeader;sidebarSection.appendChild(h);sidebarTraitList=document.createElement("ul");sidebarTraitList.className="block trait-implementation";sidebarSection.appendChild(sidebarTraitList);mainContent.appendChild(outputListHeader);mainContent.appendChild(outputList)}else{implementations=outputList;if(trait_implementations){mainContent.insertBefore(outputListHeader,trait_implementations_header);mainContent.insertBefore(outputList,trait_implementations_header)}else{const mainContent=document.querySelector("#main-content");mainContent.appendChild(outputListHeader);mainContent.appendChild(outputList)}}}const template=document.createElement("template");template.innerHTML=text;onEachLazy(template.content.querySelectorAll("a"),elem=>{const href=elem.getAttribute("href");if(href&&!href.startsWith("#")&&!/^(?:[a-z+]+:)?\/\//.test(href)){elem.setAttribute("href",window.rootPath+href)}});onEachLazy(template.content.querySelectorAll("[id]"),el=>{let i=0;if(idMap.has(el.id)){i=idMap.get(el.id)}else if(document.getElementById(el.id)){i=1;while(document.getElementById(`${el.id}-${2 * i}`)){i=2*i}while(document.getElementById(`${el.id}-${i}`)){i+=1}}if(i!==0){const oldHref=`#${el.id}`;const newHref=`#${el.id}-${i}`;el.id=`${el.id}-${i}`;onEachLazy(template.content.querySelectorAll("a[href]"),link=>{if(link.getAttribute("href")===oldHref){link.href=newHref}})}idMap.set(el.id,i+1)});const templateAssocItems=template.content.querySelectorAll("section.tymethod, "+"section.method, section.associatedtype, section.associatedconstant");if(isTrait){const li=document.createElement("li");const a=document.createElement("a");a.href=`#${template.content.querySelector(".impl").id}`;a.textContent=traitName;li.appendChild(a);sidebarTraitList.append(li)}else{onEachLazy(templateAssocItems,item=>{let block=hasClass(item,"associatedtype")?associatedTypes:(hasClass(item,"associatedconstant")?associatedConstants:(methods));if(!block){const blockTitle=hasClass(item,"associatedtype")?"Associated Types":(hasClass(item,"associatedconstant")?"Associated Constants":("Methods"));const blockClass=hasClass(item,"associatedtype")?"associatedtype":(hasClass(item,"associatedconstant")?"associatedconstant":("method"));const blockHeader=document.createElement("h3");const blockLink=document.createElement("a");blockLink.href="#implementations";blockLink.innerText=blockTitle;blockHeader.appendChild(blockLink);block=document.createElement("ul");block.className=`block ${blockClass}`;const insertionReference=methods||sidebarTraitList;if(insertionReference){const insertionReferenceH=insertionReference.previousElementSibling;sidebarSection.insertBefore(blockHeader,insertionReferenceH);sidebarSection.insertBefore(block,insertionReferenceH)}else{sidebarSection.appendChild(blockHeader);sidebarSection.appendChild(block)}if(hasClass(item,"associatedtype")){associatedTypes=block}else if(hasClass(item,"associatedconstant")){associatedConstants=block}else{methods=block}}const li=document.createElement("li");const a=document.createElement("a");a.innerText=item.id.split("-")[0].split(".")[1];a.href=`#${item.id}`;li.appendChild(a);block.appendChild(li)})}outputList.appendChild(template.content)}for(const list of[methods,associatedTypes,associatedConstants,sidebarTraitList]){if(!list){continue}const newChildren=Array.prototype.slice.call(list.children);newChildren.sort((a,b)=>{const aI=a.innerText;const bI=b.innerText;return aIbI?1:0});list.replaceChildren(...newChildren)}};if(window.pending_type_impls){window.register_type_impls(window.pending_type_impls)}function addSidebarCrates(){if(!window.ALL_CRATES){return}const sidebarElems=document.getElementsByClassName("sidebar-elems")[0];if(!sidebarElems){return}const h3=document.createElement("h3");h3.innerHTML="Crates";const ul=document.createElement("ul");ul.className="block crate";for(const crate of window.ALL_CRATES){const link=document.createElement("a");link.href=window.rootPath+crate+"/index.html";link.textContent=crate;const li=document.createElement("li");if(window.rootPath!=="./"&&crate===window.currentCrate){li.className="current"}li.appendChild(link);ul.appendChild(li)}sidebarElems.appendChild(h3);sidebarElems.appendChild(ul)}function expandAllDocs(){const innerToggle=document.getElementById(toggleAllDocsId);removeClass(innerToggle,"will-expand");onEachLazy(document.getElementsByClassName("toggle"),e=>{if(!hasClass(e,"type-contents-toggle")&&!hasClass(e,"more-examples-toggle")){e.open=true}});innerToggle.title="collapse all docs";innerToggle.children[0].innerText="\u2212"}function collapseAllDocs(){const innerToggle=document.getElementById(toggleAllDocsId);addClass(innerToggle,"will-expand");onEachLazy(document.getElementsByClassName("toggle"),e=>{if(e.parentNode.id!=="implementations-list"||(!hasClass(e,"implementors-toggle")&&!hasClass(e,"type-contents-toggle"))){e.open=false}});innerToggle.title="expand all docs";innerToggle.children[0].innerText="+"}function toggleAllDocs(){const innerToggle=document.getElementById(toggleAllDocsId);if(!innerToggle){return}if(hasClass(innerToggle,"will-expand")){expandAllDocs()}else{collapseAllDocs()}}(function(){const toggles=document.getElementById(toggleAllDocsId);if(toggles){toggles.onclick=toggleAllDocs}const hideMethodDocs=getSettingValue("auto-hide-method-docs")==="true";const hideImplementations=getSettingValue("auto-hide-trait-implementations")==="true";const hideLargeItemContents=getSettingValue("auto-hide-large-items")!=="false";function setImplementorsTogglesOpen(id,open){const list=document.getElementById(id);if(list!==null){onEachLazy(list.getElementsByClassName("implementors-toggle"),e=>{e.open=open})}}if(hideImplementations){setImplementorsTogglesOpen("trait-implementations-list",false);setImplementorsTogglesOpen("blanket-implementations-list",false)}onEachLazy(document.getElementsByClassName("toggle"),e=>{if(!hideLargeItemContents&&hasClass(e,"type-contents-toggle")){e.open=true}if(hideMethodDocs&&hasClass(e,"method-toggle")){e.open=false}})}());window.rustdoc_add_line_numbers_to_examples=()=>{onEachLazy(document.getElementsByClassName("rust-example-rendered"),x=>{const parent=x.parentNode;const line_numbers=parent.querySelectorAll(".example-line-numbers");if(line_numbers.length>0){return}const count=x.textContent.split("\n").length;const elems=[];for(let i=0;i{onEachLazy(document.getElementsByClassName("rust-example-rendered"),x=>{const parent=x.parentNode;const line_numbers=parent.querySelectorAll(".example-line-numbers");for(const node of line_numbers){parent.removeChild(node)}})};if(getSettingValue("line-numbers")==="true"){window.rustdoc_add_line_numbers_to_examples()}function showSidebar(){window.hideAllModals(false);const sidebar=document.getElementsByClassName("sidebar")[0];addClass(sidebar,"shown")}function hideSidebar(){const sidebar=document.getElementsByClassName("sidebar")[0];removeClass(sidebar,"shown")}window.addEventListener("resize",()=>{if(window.CURRENT_TOOLTIP_ELEMENT){const base=window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE;const force_visible=base.TOOLTIP_FORCE_VISIBLE;hideTooltip(false);if(force_visible){showTooltip(base);base.TOOLTIP_FORCE_VISIBLE=true}}});const mainElem=document.getElementById(MAIN_ID);if(mainElem){mainElem.addEventListener("click",hideSidebar)}onEachLazy(document.querySelectorAll("a[href^='#']"),el=>{el.addEventListener("click",()=>{expandSection(el.hash.slice(1));hideSidebar()})});onEachLazy(document.querySelectorAll(".toggle > summary:not(.hideme)"),el=>{el.addEventListener("click",e=>{if(e.target.tagName!=="SUMMARY"&&e.target.tagName!=="A"){e.preventDefault()}})});function showTooltip(e){const notable_ty=e.getAttribute("data-notable-ty");if(!window.NOTABLE_TRAITS&¬able_ty){const data=document.getElementById("notable-traits-data");if(data){window.NOTABLE_TRAITS=JSON.parse(data.innerText)}else{throw new Error("showTooltip() called with notable without any notable traits!")}}if(window.CURRENT_TOOLTIP_ELEMENT&&window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE===e){clearTooltipHoverTimeout(window.CURRENT_TOOLTIP_ELEMENT);return}window.hideAllModals(false);const wrapper=document.createElement("div");if(notable_ty){wrapper.innerHTML="
    "+window.NOTABLE_TRAITS[notable_ty]+"
    "}else{if(e.getAttribute("title")!==null){e.setAttribute("data-title",e.getAttribute("title"));e.removeAttribute("title")}if(e.getAttribute("data-title")!==null){const titleContent=document.createElement("div");titleContent.className="content";titleContent.appendChild(document.createTextNode(e.getAttribute("data-title")));wrapper.appendChild(titleContent)}}wrapper.className="tooltip popover";const focusCatcher=document.createElement("div");focusCatcher.setAttribute("tabindex","0");focusCatcher.onfocus=hideTooltip;wrapper.appendChild(focusCatcher);const pos=e.getBoundingClientRect();wrapper.style.top=(pos.top+window.scrollY+pos.height)+"px";wrapper.style.left=0;wrapper.style.right="auto";wrapper.style.visibility="hidden";document.body.appendChild(wrapper);const wrapperPos=wrapper.getBoundingClientRect();const finalPos=pos.left+window.scrollX-wrapperPos.width+24;if(finalPos>0){wrapper.style.left=finalPos+"px"}else{wrapper.style.setProperty("--popover-arrow-offset",(wrapperPos.right-pos.right+4)+"px",)}wrapper.style.visibility="";window.CURRENT_TOOLTIP_ELEMENT=wrapper;window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE=e;clearTooltipHoverTimeout(window.CURRENT_TOOLTIP_ELEMENT);wrapper.onpointerenter=ev=>{if(ev.pointerType!=="mouse"){return}clearTooltipHoverTimeout(e)};wrapper.onpointerleave=ev=>{if(ev.pointerType!=="mouse"){return}if(!e.TOOLTIP_FORCE_VISIBLE&&!e.contains(ev.relatedTarget)){setTooltipHoverTimeout(e,false);addClass(wrapper,"fade-out")}}}function setTooltipHoverTimeout(element,show){clearTooltipHoverTimeout(element);if(!show&&!window.CURRENT_TOOLTIP_ELEMENT){return}if(show&&window.CURRENT_TOOLTIP_ELEMENT){return}if(window.CURRENT_TOOLTIP_ELEMENT&&window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE!==element){return}element.TOOLTIP_HOVER_TIMEOUT=setTimeout(()=>{if(show){showTooltip(element)}else if(!element.TOOLTIP_FORCE_VISIBLE){hideTooltip(false)}},show?window.RUSTDOC_TOOLTIP_HOVER_MS:window.RUSTDOC_TOOLTIP_HOVER_EXIT_MS)}function clearTooltipHoverTimeout(element){if(element.TOOLTIP_HOVER_TIMEOUT!==undefined){removeClass(window.CURRENT_TOOLTIP_ELEMENT,"fade-out");clearTimeout(element.TOOLTIP_HOVER_TIMEOUT);delete element.TOOLTIP_HOVER_TIMEOUT}}function tooltipBlurHandler(event){if(window.CURRENT_TOOLTIP_ELEMENT&&!window.CURRENT_TOOLTIP_ELEMENT.contains(document.activeElement)&&!window.CURRENT_TOOLTIP_ELEMENT.contains(event.relatedTarget)&&!window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.contains(document.activeElement)&&!window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.contains(event.relatedTarget)){setTimeout(()=>hideTooltip(false),0)}}function hideTooltip(focus){if(window.CURRENT_TOOLTIP_ELEMENT){if(window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.TOOLTIP_FORCE_VISIBLE){if(focus){window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.focus()}window.CURRENT_TOOLTIP_ELEMENT.TOOLTIP_BASE.TOOLTIP_FORCE_VISIBLE=false}document.body.removeChild(window.CURRENT_TOOLTIP_ELEMENT);clearTooltipHoverTimeout(window.CURRENT_TOOLTIP_ELEMENT);window.CURRENT_TOOLTIP_ELEMENT=null}}onEachLazy(document.getElementsByClassName("tooltip"),e=>{e.onclick=()=>{e.TOOLTIP_FORCE_VISIBLE=e.TOOLTIP_FORCE_VISIBLE?false:true;if(window.CURRENT_TOOLTIP_ELEMENT&&!e.TOOLTIP_FORCE_VISIBLE){hideTooltip(true)}else{showTooltip(e);window.CURRENT_TOOLTIP_ELEMENT.setAttribute("tabindex","0");window.CURRENT_TOOLTIP_ELEMENT.focus();window.CURRENT_TOOLTIP_ELEMENT.onblur=tooltipBlurHandler}return false};e.onpointerenter=ev=>{if(ev.pointerType!=="mouse"){return}setTooltipHoverTimeout(e,true)};e.onpointermove=ev=>{if(ev.pointerType!=="mouse"){return}setTooltipHoverTimeout(e,true)};e.onpointerleave=ev=>{if(ev.pointerType!=="mouse"){return}if(!e.TOOLTIP_FORCE_VISIBLE&&window.CURRENT_TOOLTIP_ELEMENT&&!window.CURRENT_TOOLTIP_ELEMENT.contains(ev.relatedTarget)){setTooltipHoverTimeout(e,false);addClass(window.CURRENT_TOOLTIP_ELEMENT,"fade-out")}}});const sidebar_menu_toggle=document.getElementsByClassName("sidebar-menu-toggle")[0];if(sidebar_menu_toggle){sidebar_menu_toggle.addEventListener("click",()=>{const sidebar=document.getElementsByClassName("sidebar")[0];if(!hasClass(sidebar,"shown")){showSidebar()}else{hideSidebar()}})}function helpBlurHandler(event){blurHandler(event,getHelpButton(),window.hidePopoverMenus)}function buildHelpMenu(){const book_info=document.createElement("span");const channel=getVar("channel");book_info.className="top";book_info.innerHTML=`You can find more information in \ +the rustdoc book.`;const shortcuts=[["?","Show this help dialog"],["S / /","Focus the search field"],["↑","Move up in search results"],["↓","Move down in search results"],["← / →","Switch result tab (when results focused)"],["⏎","Go to active search result"],["+","Expand all sections"],["-","Collapse all sections"],].map(x=>"
    "+x[0].split(" ").map((y,index)=>((index&1)===0?""+y+"":" "+y+" ")).join("")+"
    "+x[1]+"
    ").join("");const div_shortcuts=document.createElement("div");addClass(div_shortcuts,"shortcuts");div_shortcuts.innerHTML="

    Keyboard Shortcuts

    "+shortcuts+"
    ";const infos=[`For a full list of all search features, take a look here.`,"Prefix searches with a type followed by a colon (e.g., fn:) to \ + restrict the search to a given item kind.","Accepted kinds are: fn, mod, struct, \ + enum, trait, type, macro, \ + and const.","Search functions by type signature (e.g., vec -> usize or \ + -> vec or String, enum:Cow -> bool)","You can look for items with an exact name by putting double quotes around \ + your request: \"string\"","Look for functions that accept or return \ + slices and \ + arrays by writing \ + square brackets (e.g., -> [u8] or [] -> Option)","Look for items inside another one by searching for a path: vec::Vec",].map(x=>"

    "+x+"

    ").join("");const div_infos=document.createElement("div");addClass(div_infos,"infos");div_infos.innerHTML="

    Search Tricks

    "+infos;const rustdoc_version=document.createElement("span");rustdoc_version.className="bottom";const rustdoc_version_code=document.createElement("code");rustdoc_version_code.innerText="rustdoc "+getVar("rustdoc-version");rustdoc_version.appendChild(rustdoc_version_code);const container=document.createElement("div");if(!isHelpPage){container.className="popover"}container.id="help";container.style.display="none";const side_by_side=document.createElement("div");side_by_side.className="side-by-side";side_by_side.appendChild(div_shortcuts);side_by_side.appendChild(div_infos);container.appendChild(book_info);container.appendChild(side_by_side);container.appendChild(rustdoc_version);if(isHelpPage){const help_section=document.createElement("section");help_section.appendChild(container);document.getElementById("main-content").appendChild(help_section);container.style.display="block"}else{const help_button=getHelpButton();help_button.appendChild(container);container.onblur=helpBlurHandler;help_button.onblur=helpBlurHandler;help_button.children[0].onblur=helpBlurHandler}return container}window.hideAllModals=switchFocus=>{hideSidebar();window.hidePopoverMenus();hideTooltip(switchFocus)};window.hidePopoverMenus=()=>{onEachLazy(document.querySelectorAll(".search-form .popover"),elem=>{elem.style.display="none"})};function getHelpMenu(buildNeeded){let menu=getHelpButton().querySelector(".popover");if(!menu&&buildNeeded){menu=buildHelpMenu()}return menu}function showHelp(){getHelpButton().querySelector("a").focus();const menu=getHelpMenu(true);if(menu.style.display==="none"){window.hideAllModals();menu.style.display=""}}if(isHelpPage){showHelp();document.querySelector(`#${HELP_BUTTON_ID} > a`).addEventListener("click",event=>{const target=event.target;if(target.tagName!=="A"||target.parentElement.id!==HELP_BUTTON_ID||event.ctrlKey||event.altKey||event.metaKey){return}event.preventDefault()})}else{document.querySelector(`#${HELP_BUTTON_ID} > a`).addEventListener("click",event=>{const target=event.target;if(target.tagName!=="A"||target.parentElement.id!==HELP_BUTTON_ID||event.ctrlKey||event.altKey||event.metaKey){return}event.preventDefault();const menu=getHelpMenu(true);const shouldShowHelp=menu.style.display==="none";if(shouldShowHelp){showHelp()}else{window.hidePopoverMenus()}})}setMobileTopbar();addSidebarItems();addSidebarCrates();onHashChange(null);window.addEventListener("hashchange",onHashChange);searchState.setup()}());(function(){const SIDEBAR_MIN=100;const SIDEBAR_MAX=500;const RUSTDOC_MOBILE_BREAKPOINT=700;const BODY_MIN=400;const SIDEBAR_VANISH_THRESHOLD=SIDEBAR_MIN/2;const sidebarButton=document.getElementById("sidebar-button");if(sidebarButton){sidebarButton.addEventListener("click",e=>{removeClass(document.documentElement,"hide-sidebar");updateLocalStorage("hide-sidebar","false");if(document.querySelector(".rustdoc.src")){window.rustdocToggleSrcSidebar()}e.preventDefault()})}let currentPointerId=null;let desiredSidebarSize=null;let pendingSidebarResizingFrame=false;const resizer=document.querySelector(".sidebar-resizer");const sidebar=document.querySelector(".sidebar");if(!resizer||!sidebar){return}const isSrcPage=hasClass(document.body,"src");function hideSidebar(){if(isSrcPage){window.rustdocCloseSourceSidebar();updateLocalStorage("src-sidebar-width",null);document.documentElement.style.removeProperty("--src-sidebar-width");sidebar.style.removeProperty("--src-sidebar-width");resizer.style.removeProperty("--src-sidebar-width")}else{addClass(document.documentElement,"hide-sidebar");updateLocalStorage("hide-sidebar","true");updateLocalStorage("desktop-sidebar-width",null);document.documentElement.style.removeProperty("--desktop-sidebar-width");sidebar.style.removeProperty("--desktop-sidebar-width");resizer.style.removeProperty("--desktop-sidebar-width")}}function showSidebar(){if(isSrcPage){window.rustdocShowSourceSidebar()}else{removeClass(document.documentElement,"hide-sidebar");updateLocalStorage("hide-sidebar","false")}}function changeSidebarSize(size){if(isSrcPage){updateLocalStorage("src-sidebar-width",size);sidebar.style.setProperty("--src-sidebar-width",size+"px");resizer.style.setProperty("--src-sidebar-width",size+"px")}else{updateLocalStorage("desktop-sidebar-width",size);sidebar.style.setProperty("--desktop-sidebar-width",size+"px");resizer.style.setProperty("--desktop-sidebar-width",size+"px")}}function isSidebarHidden(){return isSrcPage?!hasClass(document.documentElement,"src-sidebar-expanded"):hasClass(document.documentElement,"hide-sidebar")}function resize(e){if(currentPointerId===null||currentPointerId!==e.pointerId){return}e.preventDefault();const pos=e.clientX-3;if(pos=SIDEBAR_MIN){if(isSidebarHidden()){showSidebar()}const constrainedPos=Math.min(pos,window.innerWidth-BODY_MIN,SIDEBAR_MAX);changeSidebarSize(constrainedPos);desiredSidebarSize=constrainedPos;if(pendingSidebarResizingFrame!==false){clearTimeout(pendingSidebarResizingFrame)}pendingSidebarResizingFrame=setTimeout(()=>{if(currentPointerId===null||pendingSidebarResizingFrame===false){return}pendingSidebarResizingFrame=false;document.documentElement.style.setProperty("--resizing-sidebar-width",desiredSidebarSize+"px",)},100)}}window.addEventListener("resize",()=>{if(window.innerWidth=(window.innerWidth-BODY_MIN)){changeSidebarSize(window.innerWidth-BODY_MIN)}else if(desiredSidebarSize!==null&&desiredSidebarSize>SIDEBAR_MIN){changeSidebarSize(desiredSidebarSize)}});function stopResize(e){if(currentPointerId===null){return}if(e){e.preventDefault()}desiredSidebarSize=sidebar.getBoundingClientRect().width;removeClass(resizer,"active");window.removeEventListener("pointermove",resize,false);window.removeEventListener("pointerup",stopResize,false);removeClass(document.documentElement,"sidebar-resizing");document.documentElement.style.removeProperty("--resizing-sidebar-width");if(resizer.releasePointerCapture){resizer.releasePointerCapture(currentPointerId);currentPointerId=null}}function initResize(e){if(currentPointerId!==null||e.altKey||e.ctrlKey||e.metaKey||e.button!==0){return}if(resizer.setPointerCapture){resizer.setPointerCapture(e.pointerId);if(!resizer.hasPointerCapture(e.pointerId)){resizer.releasePointerCapture(e.pointerId);return}currentPointerId=e.pointerId}window.hideAllModals(false);e.preventDefault();window.addEventListener("pointermove",resize,false);window.addEventListener("pointercancel",stopResize,false);window.addEventListener("pointerup",stopResize,false);addClass(resizer,"active");addClass(document.documentElement,"sidebar-resizing");const pos=e.clientX-sidebar.offsetLeft-3;document.documentElement.style.setProperty("--resizing-sidebar-width",pos+"px");desiredSidebarSize=null}resizer.addEventListener("pointerdown",initResize,false)}());(function(){function copyContentToClipboard(content){const el=document.createElement("textarea");el.value=content;el.setAttribute("readonly","");el.style.position="absolute";el.style.left="-9999px";document.body.appendChild(el);el.select();document.execCommand("copy");document.body.removeChild(el)}function copyButtonAnimation(button){button.classList.add("clicked");if(button.reset_button_timeout!==undefined){window.clearTimeout(button.reset_button_timeout)}button.reset_button_timeout=window.setTimeout(()=>{button.reset_button_timeout=undefined;button.classList.remove("clicked")},1000)}const but=document.getElementById("copy-path");if(!but){return}but.onclick=()=>{const parent=but.parentElement;const path=[];onEach(parent.childNodes,child=>{if(child.tagName==="A"){path.push(child.textContent)}});copyContentToClipboard(path.join("::"));copyButtonAnimation(but)};function copyCode(codeElem){if(!codeElem){return}copyContentToClipboard(codeElem.textContent)}function getExampleWrap(event){let elem=event.target;while(!hasClass(elem,"example-wrap")){if(elem===document.body||elem.tagName==="A"||elem.tagName==="BUTTON"||hasClass(elem,"docblock")){return null}elem=elem.parentElement}return elem}function addCopyButton(event){const elem=getExampleWrap(event);if(elem===null){return}elem.removeEventListener("mouseover",addCopyButton);const parent=document.createElement("div");parent.className="button-holder";const runButton=elem.querySelector(".test-arrow");if(runButton!==null){parent.appendChild(runButton)}elem.appendChild(parent);const copyButton=document.createElement("button");copyButton.className="copy-button";copyButton.title="Copy code to clipboard";copyButton.addEventListener("click",()=>{copyCode(elem.querySelector("pre > code"));copyButtonAnimation(copyButton)});parent.appendChild(copyButton)}function showHideCodeExampleButtons(event){const elem=getExampleWrap(event);if(elem===null){return}let buttons=elem.querySelector(".button-holder");if(buttons===null){addCopyButton(event);buttons=elem.querySelector(".button-holder");if(buttons===null){return}}buttons.classList.toggle("keep-visible")}onEachLazy(document.querySelectorAll(".docblock .example-wrap"),elem=>{elem.addEventListener("mouseover",addCopyButton);elem.addEventListener("click",showHideCodeExampleButtons)})}()) \ No newline at end of file diff --git a/apps/rust_docs/static.files/noscript-3b12f09e550e0385.css b/apps/rust_docs/static.files/noscript-3b12f09e550e0385.css new file mode 100644 index 00000000..befe4163 --- /dev/null +++ b/apps/rust_docs/static.files/noscript-3b12f09e550e0385.css @@ -0,0 +1 @@ + #main-content .attributes{margin-left:0 !important;}#copy-path,#sidebar-button,.sidebar-resizer{display:none !important;}nav.sub{display:none;}.src .sidebar{display:none;}.notable-traits{display:none;}:root,:root:not([data-theme]){--main-background-color:white;--main-color:black;--settings-input-color:#2196f3;--settings-input-border-color:#717171;--settings-button-color:#000;--settings-button-border-focus:#717171;--sidebar-background-color:#f5f5f5;--sidebar-background-color-hover:#e0e0e0;--code-block-background-color:#f5f5f5;--scrollbar-track-background-color:#dcdcdc;--scrollbar-thumb-background-color:rgba(36,37,39,0.6);--scrollbar-color:rgba(36,37,39,0.6) #d9d9d9;--headings-border-bottom-color:#ddd;--border-color:#e0e0e0;--button-background-color:#fff;--right-side-color:grey;--code-attribute-color:#999;--toggles-color:#999;--toggle-filter:none;--mobile-sidebar-menu-filter:none;--search-input-focused-border-color:#66afe9;--copy-path-button-color:#999;--copy-path-img-filter:invert(50%);--copy-path-img-hover-filter:invert(35%);--codeblock-error-hover-color:rgb(255,0,0);--codeblock-error-color:rgba(255,0,0,.5);--codeblock-ignore-hover-color:rgb(255,142,0);--codeblock-ignore-color:rgba(255,142,0,.6);--warning-border-color:#ff8e00;--type-link-color:#ad378a;--trait-link-color:#6e4fc9;--assoc-item-link-color:#3873ad;--function-link-color:#ad7c37;--macro-link-color:#068000;--keyword-link-color:#3873ad;--mod-link-color:#3873ad;--link-color:#3873ad;--sidebar-link-color:#356da4;--sidebar-current-link-background-color:#fff;--search-result-link-focus-background-color:#ccc;--search-result-border-color:#aaa3;--search-color:#000;--search-error-code-background-color:#d0cccc;--search-results-alias-color:#000;--search-results-grey-color:#999;--search-tab-title-count-color:#888;--search-tab-button-not-selected-border-top-color:#e6e6e6;--search-tab-button-not-selected-background:#e6e6e6;--search-tab-button-selected-border-top-color:#0089ff;--search-tab-button-selected-background:#fff;--settings-menu-filter:none;--stab-background-color:#fff5d6;--stab-code-color:#000;--code-highlight-kw-color:#8959a8;--code-highlight-kw-2-color:#4271ae;--code-highlight-lifetime-color:#b76514;--code-highlight-prelude-color:#4271ae;--code-highlight-prelude-val-color:#c82829;--code-highlight-number-color:#718c00;--code-highlight-string-color:#718c00;--code-highlight-literal-color:#c82829;--code-highlight-attribute-color:#c82829;--code-highlight-self-color:#c82829;--code-highlight-macro-color:#3e999f;--code-highlight-question-mark-color:#ff9011;--code-highlight-comment-color:#8e908c;--code-highlight-doc-comment-color:#4d4d4c;--src-line-numbers-span-color:#c67e2d;--src-line-number-highlighted-background-color:#fdffd3;--target-background-color:#fdffd3;--target-border-color:#ad7c37;--kbd-color:#000;--kbd-background:#fafbfc;--kbd-box-shadow-color:#c6cbd1;--rust-logo-filter:initial;--crate-search-div-filter:invert(100%) sepia(0%) saturate(4223%) hue-rotate(289deg) brightness(114%) contrast(76%);--crate-search-div-hover-filter:invert(44%) sepia(18%) saturate(23%) hue-rotate(317deg) brightness(96%) contrast(93%);--crate-search-hover-border:#717171;--src-sidebar-background-selected:#fff;--src-sidebar-background-hover:#e0e0e0;--table-alt-row-background-color:#f5f5f5;--codeblock-link-background:#eee;--scrape-example-toggle-line-background:#ccc;--scrape-example-toggle-line-hover-background:#999;--scrape-example-code-line-highlight:#fcffd6;--scrape-example-code-line-highlight-focus:#f6fdb0;--scrape-example-help-border-color:#555;--scrape-example-help-color:#333;--scrape-example-help-hover-border-color:#000;--scrape-example-help-hover-color:#000;--scrape-example-code-wrapper-background-start:rgba(255,255,255,1);--scrape-example-code-wrapper-background-end:rgba(255,255,255,0);--sidebar-resizer-hover:hsl(207,90%,66%);--sidebar-resizer-active:hsl(207,90%,54%);}@media (prefers-color-scheme:dark){:root,:root:not([data-theme]){--main-background-color:#353535;--main-color:#ddd;--settings-input-color:#2196f3;--settings-input-border-color:#999;--settings-button-color:#000;--settings-button-border-focus:#ffb900;--sidebar-background-color:#505050;--sidebar-background-color-hover:#676767;--code-block-background-color:#2A2A2A;--scrollbar-track-background-color:#717171;--scrollbar-thumb-background-color:rgba(32,34,37,.6);--scrollbar-color:rgba(32,34,37,.6) #5a5a5a;--headings-border-bottom-color:#d2d2d2;--border-color:#e0e0e0;--button-background-color:#f0f0f0;--right-side-color:grey;--code-attribute-color:#999;--toggles-color:#999;--toggle-filter:invert(100%);--mobile-sidebar-menu-filter:invert(100%);--search-input-focused-border-color:#008dfd;--copy-path-button-color:#999;--copy-path-img-filter:invert(50%);--copy-path-img-hover-filter:invert(65%);--codeblock-error-hover-color:rgb(255,0,0);--codeblock-error-color:rgba(255,0,0,.5);--codeblock-ignore-hover-color:rgb(255,142,0);--codeblock-ignore-color:rgba(255,142,0,.6);--warning-border-color:#ff8e00;--type-link-color:#2dbfb8;--trait-link-color:#b78cf2;--assoc-item-link-color:#d2991d;--function-link-color:#2bab63;--macro-link-color:#09bd00;--keyword-link-color:#d2991d;--mod-link-color:#d2991d;--link-color:#d2991d;--sidebar-link-color:#fdbf35;--sidebar-current-link-background-color:#444;--search-result-link-focus-background-color:#616161;--search-result-border-color:#aaa3;--search-color:#111;--search-error-code-background-color:#484848;--search-results-alias-color:#fff;--search-results-grey-color:#ccc;--search-tab-title-count-color:#888;--search-tab-button-not-selected-border-top-color:#252525;--search-tab-button-not-selected-background:#252525;--search-tab-button-selected-border-top-color:#0089ff;--search-tab-button-selected-background:#353535;--stab-background-color:#314559;--stab-code-color:#e6e1cf;--code-highlight-kw-color:#ab8ac1;--code-highlight-kw-2-color:#769acb;--code-highlight-lifetime-color:#d97f26;--code-highlight-prelude-color:#769acb;--code-highlight-prelude-val-color:#ee6868;--code-highlight-number-color:#83a300;--code-highlight-string-color:#83a300;--code-highlight-literal-color:#ee6868;--code-highlight-attribute-color:#ee6868;--code-highlight-self-color:#ee6868;--code-highlight-macro-color:#3e999f;--code-highlight-question-mark-color:#ff9011;--code-highlight-comment-color:#8d8d8b;--code-highlight-doc-comment-color:#8ca375;--src-line-numbers-span-color:#3b91e2;--src-line-number-highlighted-background-color:#0a042f;--target-background-color:#494a3d;--target-border-color:#bb7410;--kbd-color:#000;--kbd-background:#fafbfc;--kbd-box-shadow-color:#c6cbd1;--rust-logo-filter:drop-shadow(1px 0 0px #fff) drop-shadow(0 1px 0 #fff) drop-shadow(-1px 0 0 #fff) drop-shadow(0 -1px 0 #fff);--crate-search-div-filter:invert(94%) sepia(0%) saturate(721%) hue-rotate(255deg) brightness(90%) contrast(90%);--crate-search-div-hover-filter:invert(69%) sepia(60%) saturate(6613%) hue-rotate(184deg) brightness(100%) contrast(91%);--crate-search-hover-border:#2196f3;--src-sidebar-background-selected:#333;--src-sidebar-background-hover:#444;--table-alt-row-background-color:#2a2a2a;--codeblock-link-background:#333;--scrape-example-toggle-line-background:#999;--scrape-example-toggle-line-hover-background:#c5c5c5;--scrape-example-code-line-highlight:#5b3b01;--scrape-example-code-line-highlight-focus:#7c4b0f;--scrape-example-help-border-color:#aaa;--scrape-example-help-color:#eee;--scrape-example-help-hover-border-color:#fff;--scrape-example-help-hover-color:#fff;--scrape-example-code-wrapper-background-start:rgba(53,53,53,1);--scrape-example-code-wrapper-background-end:rgba(53,53,53,0);--sidebar-resizer-hover:hsl(207,30%,54%);--sidebar-resizer-active:hsl(207,90%,54%);}} \ No newline at end of file diff --git a/apps/rust_docs/static.files/rustdoc-492a78a4a87dcc01.css b/apps/rust_docs/static.files/rustdoc-492a78a4a87dcc01.css new file mode 100644 index 00000000..e9199f95 --- /dev/null +++ b/apps/rust_docs/static.files/rustdoc-492a78a4a87dcc01.css @@ -0,0 +1,47 @@ + :root{--nav-sub-mobile-padding:8px;--search-typename-width:6.75rem;--desktop-sidebar-width:200px;--src-sidebar-width:300px;--desktop-sidebar-z-index:100;--sidebar-elems-left-padding:24px;--clipboard-image:url('data:image/svg+xml,\ +\ +\ +');--copy-path-height:34px;--copy-path-width:33px;--checkmark-image:url('data:image/svg+xml,\ +\ +');--button-left-margin:4px;--button-border-radius:2px;}@font-face {font-family:'Fira Sans';font-style:normal;font-weight:400;src:local('Fira Sans'),url("FiraSans-Regular-018c141bf0843ffd.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Fira Sans';font-style:normal;font-weight:500;src:local('Fira Sans Medium'),url("FiraSans-Medium-8f9a781e4970d388.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Serif 4';font-style:normal;font-weight:400;src:local('Source Serif 4'),url("SourceSerif4-Regular-46f98efaafac5295.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Serif 4';font-style:italic;font-weight:400;src:local('Source Serif 4 Italic'),url("SourceSerif4-It-acdfaf1a8af734b1.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Serif 4';font-style:normal;font-weight:700;src:local('Source Serif 4 Bold'),url("SourceSerif4-Bold-a2c9cd1067f8b328.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Code Pro';font-style:normal;font-weight:400;src:url("SourceCodePro-Regular-562dcc5011b6de7d.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Code Pro';font-style:italic;font-weight:400;src:url("SourceCodePro-It-1cc31594bf4f1f79.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'Source Code Pro';font-style:normal;font-weight:600;src:url("SourceCodePro-Semibold-d899c5a5c4aeb14a.ttf.woff2") format("woff2");font-display:swap;}@font-face {font-family:'NanumBarunGothic';src:url("NanumBarunGothic-0f09457c7a19b7c6.ttf.woff2") format("woff2");font-display:swap;unicode-range:U+AC00-D7AF,U+1100-11FF,U+3130-318F,U+A960-A97F,U+D7B0-D7FF;}*{box-sizing:border-box;}body{font:1rem/1.5 "Source Serif 4",NanumBarunGothic,serif;margin:0;position:relative;overflow-wrap:break-word;overflow-wrap:anywhere;font-feature-settings:"kern","liga";background-color:var(--main-background-color);color:var(--main-color);}h1{font-size:1.5rem;}h2{font-size:1.375rem;}h3{font-size:1.25rem;}h1,h2,h3,h4,h5,h6{font-weight:500;}h1,h2,h3,h4{margin:25px 0 15px 0;padding-bottom:6px;}.docblock h3,.docblock h4,h5,h6{margin:15px 0 5px 0;}.docblock>h2:first-child,.docblock>h3:first-child,.docblock>h4:first-child,.docblock>h5:first-child,.docblock>h6:first-child{margin-top:0;}.main-heading h1{margin:0;padding:0;flex-grow:1;overflow-wrap:break-word;overflow-wrap:anywhere;}.main-heading{display:flex;flex-wrap:wrap;padding-bottom:6px;margin-bottom:15px;}.content h2,.top-doc .docblock>h3,.top-doc .docblock>h4{border-bottom:1px solid var(--headings-border-bottom-color);}h1,h2{line-height:1.25;padding-top:3px;padding-bottom:9px;}h3.code-header{font-size:1.125rem;}h4.code-header{font-size:1rem;}.code-header{font-weight:600;margin:0;padding:0;white-space:pre-wrap;}#crate-search,h1,h2,h3,h4,h5,h6,.sidebar,.mobile-topbar,.search-input,.search-results .result-name,.item-name>a,.out-of-band,span.since,a.src,#help-button>a,summary.hideme,.scraped-example-list,ul.all-items{font-family:"Fira Sans",Arial,NanumBarunGothic,sans-serif;}#toggle-all-docs,a.anchor,.section-header a,#src-sidebar a,.rust a,.sidebar h2 a,.sidebar h3 a,.mobile-topbar h2 a,h1 a,.search-results a,.stab,.result-name i{color:var(--main-color);}span.enum,a.enum,span.struct,a.struct,span.union,a.union,span.primitive,a.primitive,span.type,a.type,span.foreigntype,a.foreigntype{color:var(--type-link-color);}span.trait,a.trait,span.traitalias,a.traitalias{color:var(--trait-link-color);}span.associatedtype,a.associatedtype,span.constant,a.constant,span.static,a.static{color:var(--assoc-item-link-color);}span.fn,a.fn,span.method,a.method,span.tymethod,a.tymethod{color:var(--function-link-color);}span.attr,a.attr,span.derive,a.derive,span.macro,a.macro{color:var(--macro-link-color);}span.mod,a.mod{color:var(--mod-link-color);}span.keyword,a.keyword{color:var(--keyword-link-color);}a{color:var(--link-color);text-decoration:none;}ol,ul{padding-left:24px;}ul ul,ol ul,ul ol,ol ol{margin-bottom:.625em;}p,.docblock>.warning{margin:0 0 .75em 0;}p:last-child,.docblock>.warning:last-child{margin:0;}button{padding:1px 6px;cursor:pointer;}button#toggle-all-docs{padding:0;background:none;border:none;-webkit-appearance:none;opacity:1;}.rustdoc{display:flex;flex-direction:row;flex-wrap:nowrap;}main{position:relative;flex-grow:1;padding:10px 15px 40px 45px;min-width:0;}.src main{padding:15px;}.width-limiter{max-width:960px;margin-right:auto;}details:not(.toggle) summary{margin-bottom:.6em;}code,pre,.code-header{font-family:"Source Code Pro",monospace;}.docblock code,.docblock-short code{border-radius:3px;padding:0 0.125em;}.docblock pre code,.docblock-short pre code{padding:0;}pre{padding:14px;line-height:1.5;}pre.item-decl{overflow-x:auto;}.item-decl .type-contents-toggle{contain:initial;}.src .content pre{padding:20px;}.rustdoc.src .example-wrap pre.src-line-numbers{padding:20px 0 20px 4px;}img{max-width:100%;}.logo-container{line-height:0;display:block;}.rust-logo{filter:var(--rust-logo-filter);}.sidebar{font-size:0.875rem;flex:0 0 var(--desktop-sidebar-width);width:var(--desktop-sidebar-width);overflow-y:scroll;overscroll-behavior:contain;position:sticky;height:100vh;top:0;left:0;z-index:var(--desktop-sidebar-z-index);}.rustdoc.src .sidebar{flex-basis:50px;width:50px;border-right:1px solid;overflow-x:hidden;overflow-y:hidden;}.hide-sidebar .sidebar,.hide-sidebar .sidebar-resizer{display:none;}.sidebar-resizer{touch-action:none;width:9px;cursor:col-resize;z-index:calc(var(--desktop-sidebar-z-index) + 1);position:fixed;height:100%;left:calc(var(--desktop-sidebar-width) + 1px);}.rustdoc.src .sidebar-resizer{left:49px;}.src-sidebar-expanded .src .sidebar-resizer{left:var(--src-sidebar-width);}.sidebar-resizing{-moz-user-select:none;-webkit-user-select:none;-ms-user-select:none;user-select:none;}.sidebar-resizing*{cursor:col-resize !important;}.sidebar-resizing .sidebar{position:fixed;}.sidebar-resizing>body{padding-left:var(--resizing-sidebar-width);}.sidebar-resizer:hover,.sidebar-resizer:active,.sidebar-resizer:focus,.sidebar-resizer.active{width:10px;margin:0;left:var(--desktop-sidebar-width);border-left:solid 1px var(--sidebar-resizer-hover);}.src-sidebar-expanded .rustdoc.src .sidebar-resizer:hover,.src-sidebar-expanded .rustdoc.src .sidebar-resizer:active,.src-sidebar-expanded .rustdoc.src .sidebar-resizer:focus,.src-sidebar-expanded .rustdoc.src .sidebar-resizer.active{left:calc(var(--src-sidebar-width) - 1px);}@media (pointer:coarse){.sidebar-resizer{display:none !important;}}.sidebar-resizer.active{padding:0 140px;width:2px;margin-left:-140px;border-left:none;}.sidebar-resizer.active:before{border-left:solid 2px var(--sidebar-resizer-active);display:block;height:100%;content:"";}.sidebar,.mobile-topbar,.sidebar-menu-toggle,#src-sidebar{background-color:var(--sidebar-background-color);}.src .sidebar>*{visibility:hidden;}.src-sidebar-expanded .src .sidebar{overflow-y:auto;flex-basis:var(--src-sidebar-width);width:var(--src-sidebar-width);}.src-sidebar-expanded .src .sidebar>*{visibility:visible;}#all-types{margin-top:1em;}*{scrollbar-width:initial;scrollbar-color:var(--scrollbar-color);}.sidebar{scrollbar-width:thin;scrollbar-color:var(--scrollbar-color);}::-webkit-scrollbar{width:12px;}.sidebar::-webkit-scrollbar{width:8px;}::-webkit-scrollbar-track{-webkit-box-shadow:inset 0;background-color:var(--scrollbar-track-background-color);}.sidebar::-webkit-scrollbar-track{background-color:var(--scrollbar-track-background-color);}::-webkit-scrollbar-thumb,.sidebar::-webkit-scrollbar-thumb{background-color:var(--scrollbar-thumb-background-color);}.hidden{display:none !important;}.logo-container>img{height:48px;width:48px;}ul.block,.block li{padding:0;margin:0;list-style:none;}.sidebar-elems a,.sidebar>h2 a{display:block;padding:0.25rem;margin-right:0.25rem;border-left:solid var(--sidebar-elems-left-padding) transparent;margin-left:calc(-0.25rem - var(--sidebar-elems-left-padding));background-clip:border-box;}.sidebar h2{text-wrap:balance;overflow-wrap:anywhere;padding:0;margin:0.7rem 0;}.sidebar h3{text-wrap:balance;overflow-wrap:anywhere;font-size:1.125rem;padding:0;margin:0;}.sidebar-elems,.sidebar>.version,.sidebar>h2{padding-left:var(--sidebar-elems-left-padding);}.sidebar a{color:var(--sidebar-link-color);}.sidebar .current,.sidebar .current a,.sidebar-crate a.logo-container:hover+h2 a,.sidebar a:hover:not(.logo-container){background-color:var(--sidebar-current-link-background-color);}.sidebar-elems .block{margin-bottom:2em;}.sidebar-elems .block li a{white-space:nowrap;text-overflow:ellipsis;overflow:hidden;}.sidebar-crate{display:flex;align-items:center;justify-content:center;margin:14px 32px 1rem;row-gap:10px;column-gap:32px;flex-wrap:wrap;}.sidebar-crate h2{flex-grow:1;margin:0 -8px;align-self:start;}.sidebar-crate .logo-container{margin:0 calc(-16px - var(--sidebar-elems-left-padding));padding:0 var(--sidebar-elems-left-padding);text-align:center;}.sidebar-crate .logo-container img{margin-top:-16px;border-top:solid 16px transparent;box-sizing:content-box;position:relative;background-clip:border-box;z-index:1;}.sidebar-crate h2 a{display:block;border-left:solid var(--sidebar-elems-left-padding) transparent;background-clip:border-box;margin:0 calc(-24px + 0.25rem) 0 calc(-0.2rem - var(--sidebar-elems-left-padding));padding:calc((16px - 0.57rem ) / 2 ) 0.25rem;padding-left:0.2rem;}.sidebar-crate h2 .version{display:block;font-weight:normal;font-size:1rem;overflow-wrap:break-word;}.sidebar-crate+.version{margin-top:-1rem;margin-bottom:1rem;}.mobile-topbar{display:none;}.rustdoc .example-wrap{display:flex;position:relative;margin-bottom:10px;}.rustdoc .example-wrap>pre{border-radius:6px;}.rustdoc .example-wrap:last-child{margin-bottom:0px;}.rustdoc .example-wrap pre{margin:0;flex-grow:1;}.rustdoc:not(.src) .example-wrap pre{overflow:auto hidden;}.rustdoc .example-wrap pre.example-line-numbers,.rustdoc .example-wrap pre.src-line-numbers{flex-grow:0;min-width:fit-content;overflow:initial;text-align:right;-webkit-user-select:none;user-select:none;padding:14px 8px;color:var(--src-line-numbers-span-color);}.rustdoc .example-wrap pre.src-line-numbers{padding:14px 0;}.src-line-numbers a,.src-line-numbers span{color:var(--src-line-numbers-span-color);padding:0 8px;}.src-line-numbers :target{background-color:transparent;border-right:none;padding:0 8px;}.src-line-numbers .line-highlighted{background-color:var(--src-line-number-highlighted-background-color);}.search-loading{text-align:center;}.docblock-short{overflow-wrap:break-word;overflow-wrap:anywhere;}.docblock :not(pre)>code,.docblock-short code{white-space:pre-wrap;}.top-doc .docblock h2{font-size:1.375rem;}.top-doc .docblock h3{font-size:1.25rem;}.top-doc .docblock h4,.top-doc .docblock h5{font-size:1.125rem;}.top-doc .docblock h6{font-size:1rem;}.docblock h5{font-size:1rem;}.docblock h6{font-size:0.875rem;}.docblock{margin-left:24px;position:relative;}.docblock>:not(.more-examples-toggle):not(.example-wrap){max-width:100%;overflow-x:auto;}.out-of-band{flex-grow:0;font-size:1.125rem;}.docblock code,.docblock-short code,pre,.rustdoc.src .example-wrap{background-color:var(--code-block-background-color);}#main-content{position:relative;}.docblock table{margin:.5em 0;border-collapse:collapse;}.docblock table td,.docblock table th{padding:.5em;border:1px solid var(--border-color);}.docblock table tbody tr:nth-child(2n){background:var(--table-alt-row-background-color);}.docblock .stab,.docblock-short .stab{display:inline-block;}div.where{white-space:pre-wrap;font-size:0.875rem;}.item-info{display:block;margin-left:24px;}.item-info code{font-size:0.875rem;}#main-content>.item-info{margin-left:0;}nav.sub{flex-grow:1;flex-flow:row nowrap;margin:4px 0 25px 0;display:flex;align-items:center;}.search-form{position:relative;display:flex;height:34px;flex-grow:1;}.src nav.sub{margin:0 0 15px 0;}.section-header{display:block;position:relative;}.section-header:hover>.anchor,.impl:hover>.anchor,.trait-impl:hover>.anchor,.variant:hover>.anchor{display:initial;}.anchor{display:none;position:absolute;left:-0.5em;background:none !important;}.anchor.field{left:-5px;}.section-header>.anchor{left:-15px;padding-right:8px;}h2.section-header>.anchor{padding-right:6px;}a.doc-anchor{color:var(--main-color);display:none;position:absolute;left:-17px;padding-right:10px;padding-left:3px;}*:hover>.doc-anchor{display:block;}.top-doc>.docblock>*:first-child>.doc-anchor{display:none !important;}.main-heading a:hover,.example-wrap .rust a:hover,.all-items a:hover,.docblock a:not(.scrape-help):not(.tooltip):hover:not(.doc-anchor),.docblock-short a:not(.scrape-help):not(.tooltip):hover,.item-info a{text-decoration:underline;}.crate.block li.current a{font-weight:500;}table,.item-table{overflow-wrap:break-word;}.item-table{display:table;padding:0;margin:0;width:100%;}.item-table>li{display:table-row;}.item-table>li>div{display:table-cell;}.item-table>li>.item-name{padding-right:1.25rem;}.search-results-title{margin-top:0;white-space:nowrap;display:flex;align-items:baseline;}#crate-search-div{position:relative;min-width:5em;}#crate-search{min-width:115px;padding:0 23px 0 4px;max-width:100%;text-overflow:ellipsis;border:1px solid var(--border-color);border-radius:4px;outline:none;cursor:pointer;-moz-appearance:none;-webkit-appearance:none;text-indent:0.01px;background-color:var(--main-background-color);color:inherit;line-height:1.5;font-weight:500;}#crate-search:hover,#crate-search:focus{border-color:var(--crate-search-hover-border);}#crate-search-div::after{pointer-events:none;width:100%;height:100%;position:absolute;top:0;left:0;content:"";background-repeat:no-repeat;background-size:20px;background-position:calc(100% - 2px) 56%;background-image:url('data:image/svg+xml, \ + ');filter:var(--crate-search-div-filter);}#crate-search-div:hover::after,#crate-search-div:focus-within::after{filter:var(--crate-search-div-hover-filter);}#crate-search>option{font-size:1rem;}.search-input{-webkit-appearance:none;outline:none;border:1px solid var(--border-color);border-radius:2px;padding:8px;font-size:1rem;flex-grow:1;background-color:var(--button-background-color);color:var(--search-color);}.search-input:focus{border-color:var(--search-input-focused-border-color);}.search-results{display:none;}.search-results.active{display:block;}.search-results>a{display:flex;margin-left:2px;margin-right:2px;border-bottom:1px solid var(--search-result-border-color);gap:1em;}.search-results>a>div.desc{white-space:nowrap;text-overflow:ellipsis;overflow:hidden;flex:2;}.search-results a:hover,.search-results a:focus{background-color:var(--search-result-link-focus-background-color);}.search-results .result-name{display:flex;align-items:center;justify-content:start;flex:3;}.search-results .result-name .alias{color:var(--search-results-alias-color);}.search-results .result-name .grey{color:var(--search-results-grey-color);}.search-results .result-name .typename{color:var(--search-results-grey-color);font-size:0.875rem;width:var(--search-typename-width);}.search-results .result-name .path{word-break:break-all;max-width:calc(100% - var(--search-typename-width));display:inline-block;}.search-results .result-name .path>*{display:inline;}.popover{position:absolute;top:100%;right:0;z-index:calc(var(--desktop-sidebar-z-index) + 1);margin-top:7px;border-radius:3px;border:1px solid var(--border-color);background-color:var(--main-background-color);color:var(--main-color);--popover-arrow-offset:11px;}.popover::before{content:'';position:absolute;right:var(--popover-arrow-offset);border:solid var(--border-color);border-width:1px 1px 0 0;background-color:var(--main-background-color);padding:4px;transform:rotate(-45deg);top:-5px;}.setting-line{margin:1.2em 0.6em;}.setting-radio input,.setting-check input{margin-right:0.3em;height:1.2rem;width:1.2rem;border:2px solid var(--settings-input-border-color);outline:none;-webkit-appearance:none;cursor:pointer;}.setting-radio input{border-radius:50%;}.setting-radio span,.setting-check span{padding-bottom:1px;}.setting-radio{margin-top:0.1em;margin-bottom:0.1em;min-width:3.8em;padding:0.3em;display:inline-flex;align-items:center;cursor:pointer;}.setting-radio+.setting-radio{margin-left:0.5em;}.setting-check{margin-right:20px;display:flex;align-items:center;cursor:pointer;}.setting-radio input:checked{box-shadow:inset 0 0 0 3px var(--main-background-color);background-color:var(--settings-input-color);}.setting-check input:checked{background-color:var(--settings-input-color);border-width:1px;content:url('data:image/svg+xml,\ + \ + ');}.setting-radio input:focus,.setting-check input:focus{box-shadow:0 0 1px 1px var(--settings-input-color);}.setting-radio input:checked:focus{box-shadow:inset 0 0 0 3px var(--main-background-color),0 0 2px 2px var(--settings-input-color);}.setting-radio input:hover,.setting-check input:hover{border-color:var(--settings-input-color) !important;}#help.popover{max-width:600px;--popover-arrow-offset:48px;}#help dt{float:left;clear:left;margin-right:0.5rem;}#help span.top,#help span.bottom{text-align:center;display:block;font-size:1.125rem;}#help span.top{margin:10px 0;border-bottom:1px solid var(--border-color);padding-bottom:4px;margin-bottom:6px;}#help span.bottom{clear:both;border-top:1px solid var(--border-color);}.side-by-side>div{width:50%;float:left;padding:0 20px 20px 17px;}.item-info .stab{display:block;padding:3px;margin-bottom:5px;}.item-name .stab{margin-left:0.3125em;}.stab{padding:0 2px;font-size:0.875rem;font-weight:normal;color:var(--main-color);background-color:var(--stab-background-color);width:fit-content;white-space:pre-wrap;border-radius:3px;display:inline;vertical-align:baseline;}.stab.portability>code{background:none;color:var(--stab-code-color);}.stab .emoji,.item-info .stab::before{font-size:1.25rem;}.stab .emoji{margin-right:0.3rem;}.item-info .stab::before{content:"\0";width:0;display:inline-block;color:transparent;}.emoji{text-shadow:1px 0 0 black,-1px 0 0 black,0 1px 0 black,0 -1px 0 black;}.since{font-weight:normal;font-size:initial;}.rightside{padding-left:12px;float:right;}.rightside:not(a),.out-of-band{color:var(--right-side-color);}pre.rust{tab-size:4;-moz-tab-size:4;}pre.rust .kw{color:var(--code-highlight-kw-color);}pre.rust .kw-2{color:var(--code-highlight-kw-2-color);}pre.rust .lifetime{color:var(--code-highlight-lifetime-color);}pre.rust .prelude-ty{color:var(--code-highlight-prelude-color);}pre.rust .prelude-val{color:var(--code-highlight-prelude-val-color);}pre.rust .string{color:var(--code-highlight-string-color);}pre.rust .number{color:var(--code-highlight-number-color);}pre.rust .bool-val{color:var(--code-highlight-literal-color);}pre.rust .self{color:var(--code-highlight-self-color);}pre.rust .attr{color:var(--code-highlight-attribute-color);}pre.rust .macro,pre.rust .macro-nonterminal{color:var(--code-highlight-macro-color);}pre.rust .question-mark{font-weight:bold;color:var(--code-highlight-question-mark-color);}pre.rust .comment{color:var(--code-highlight-comment-color);}pre.rust .doccomment{color:var(--code-highlight-doc-comment-color);}.rustdoc.src .example-wrap pre.rust a{background:var(--codeblock-link-background);}.example-wrap.compile_fail,.example-wrap.should_panic{border-left:2px solid var(--codeblock-error-color);}.ignore.example-wrap{border-left:2px solid var(--codeblock-ignore-color);}.example-wrap.compile_fail:hover,.example-wrap.should_panic:hover{border-left:2px solid var(--codeblock-error-hover-color);}.example-wrap.ignore:hover{border-left:2px solid var(--codeblock-ignore-hover-color);}.example-wrap.compile_fail .tooltip,.example-wrap.should_panic .tooltip{color:var(--codeblock-error-color);}.example-wrap.ignore .tooltip{color:var(--codeblock-ignore-color);}.example-wrap.compile_fail:hover .tooltip,.example-wrap.should_panic:hover .tooltip{color:var(--codeblock-error-hover-color);}.example-wrap.ignore:hover .tooltip{color:var(--codeblock-ignore-hover-color);}.example-wrap .tooltip{position:absolute;display:block;left:-25px;top:5px;margin:0;line-height:1;}.example-wrap.compile_fail .tooltip,.example-wrap.should_panic .tooltip,.example-wrap.ignore .tooltip{font-weight:bold;font-size:1.25rem;}.content .docblock .warning{border-left:2px solid var(--warning-border-color);padding:14px;position:relative;overflow-x:visible !important;}.content .docblock .warning::before{color:var(--warning-border-color);content:"ⓘ";position:absolute;left:-25px;top:5px;font-weight:bold;font-size:1.25rem;}.top-doc>.docblock>.warning:first-child::before{top:20px;}.example-wrap>a.test-arrow,.example-wrap .button-holder{visibility:hidden;position:absolute;top:4px;right:4px;z-index:1;}a.test-arrow{height:var(--copy-path-height);padding:6px 4px 0 11px;}a.test-arrow::before{content:url('data:image/svg+xml,');}.example-wrap .button-holder{display:flex;}@media not (pointer:coarse){.example-wrap:hover>a.test-arrow,.example-wrap:hover>.button-holder{visibility:visible;}}.example-wrap .button-holder.keep-visible{visibility:visible;}.example-wrap .button-holder .copy-button,.example-wrap .test-arrow{background:var(--main-background-color);cursor:pointer;border-radius:var(--button-border-radius);height:var(--copy-path-height);width:var(--copy-path-width);}.example-wrap .button-holder .copy-button{margin-left:var(--button-left-margin);padding:2px 0 0 4px;border:0;}.example-wrap .button-holder .copy-button::before,.example-wrap .test-arrow::before{filter:var(--copy-path-img-filter);}.example-wrap .button-holder .copy-button::before{content:var(--clipboard-image);}.example-wrap .button-holder .copy-button:hover::before,.example-wrap .test-arrow:hover::before{filter:var(--copy-path-img-hover-filter);}.example-wrap .button-holder .copy-button.clicked::before{content:var(--checkmark-image);padding-right:5px;}.code-attribute{font-weight:300;color:var(--code-attribute-color);}.item-spacer{width:100%;height:12px;display:block;}.out-of-band>span.since{font-size:1.25rem;}.sub-variant h4{font-size:1rem;font-weight:400;margin-top:0;margin-bottom:0;}.sub-variant{margin-left:24px;margin-bottom:40px;}.sub-variant>.sub-variant-field{margin-left:24px;}@keyframes targetfadein{from{background-color:var(--main-background-color);}10%{background-color:var(--target-border-color);}to{background-color:var(--target-background-color);}}:target{padding-right:3px;background-color:var(--target-background-color);border-right:3px solid var(--target-border-color);animation:0.65s cubic-bezier(0,0,0.1,1.0) 0.1s targetfadein;}.code-header a.tooltip{color:inherit;margin-right:15px;position:relative;}.code-header a.tooltip:hover{color:var(--link-color);}a.tooltip:hover::after{position:absolute;top:calc(100% - 10px);left:-15px;right:-15px;height:20px;content:"\00a0";}.fade-out{opacity:0;transition:opacity 0.45s cubic-bezier(0,0,0.1,1.0);}.popover.tooltip .content{margin:0.25em 0.5em;}.popover.tooltip .content pre,.popover.tooltip .content code{background:transparent;margin:0;padding:0;font-size:1.25rem;white-space:pre-wrap;}.popover.tooltip .content>h3:first-child{margin:0 0 5px 0;}.search-failed{text-align:center;margin-top:20px;display:none;}.search-failed.active{display:block;}.search-failed>ul{text-align:left;max-width:570px;margin-left:auto;margin-right:auto;}#search-tabs{display:flex;flex-direction:row;gap:1px;margin-bottom:4px;}#search-tabs button{text-align:center;font-size:1.125rem;border:0;border-top:2px solid;flex:1;line-height:1.5;color:inherit;}#search-tabs button:not(.selected){background-color:var(--search-tab-button-not-selected-background);border-top-color:var(--search-tab-button-not-selected-border-top-color);}#search-tabs button:hover,#search-tabs button.selected{background-color:var(--search-tab-button-selected-background);border-top-color:var(--search-tab-button-selected-border-top-color);}#search-tabs .count{font-size:1rem;font-variant-numeric:tabular-nums;color:var(--search-tab-title-count-color);}#search .error code{border-radius:3px;background-color:var(--search-error-code-background-color);}.search-corrections{font-weight:normal;}#src-sidebar{width:100%;overflow:auto;}#src-sidebar div.files>a:hover,details.dir-entry summary:hover,#src-sidebar div.files>a:focus,details.dir-entry summary:focus{background-color:var(--src-sidebar-background-hover);}#src-sidebar div.files>a.selected{background-color:var(--src-sidebar-background-selected);}.src-sidebar-title{position:sticky;top:0;display:flex;padding:8px 8px 0 48px;margin-bottom:7px;background:var(--sidebar-background-color);border-bottom:1px solid var(--border-color);}#settings-menu,#help-button{margin-left:var(--button-left-margin);display:flex;}#sidebar-button{display:none;line-height:0;}.hide-sidebar #sidebar-button,.src #sidebar-button{display:flex;margin-right:4px;position:fixed;left:6px;height:34px;width:34px;background-color:var(--main-background-color);z-index:1;}.src #sidebar-button{left:8px;z-index:calc(var(--desktop-sidebar-z-index) + 1);}.hide-sidebar .src #sidebar-button{position:static;}#settings-menu>a,#help-button>a,#sidebar-button>a{display:flex;align-items:center;justify-content:center;background-color:var(--button-background-color);border:1px solid var(--border-color);border-radius:var(--button-border-radius);color:var(--settings-button-color);font-size:20px;width:33px;}#settings-menu>a:hover,#settings-menu>a:focus,#help-button>a:hover,#help-button>a:focus,#sidebar-button>a:hover,#sidebar-button>a:focus{border-color:var(--settings-button-border-focus);}#settings-menu>a{line-height:0;font-size:0;}#settings-menu>a:before{content:url('data:image/svg+xml,\ + ');width:22px;height:22px;filter:var(--settings-menu-filter);}#sidebar-button>a:before{content:url('data:image/svg+xml,\ + \ + \ + ');width:22px;height:22px;}#copy-path{color:var(--copy-path-button-color);background:var(--main-background-color);height:var(--copy-path-height);width:var(--copy-path-width);margin-left:10px;padding:0;padding-left:2px;border:0;font-size:0;}#copy-path::before{filter:var(--copy-path-img-filter);content:var(--clipboard-image);}#copy-path:hover::before{filter:var(--copy-path-img-hover-filter);}#copy-path.clicked::before{content:var(--checkmark-image);}@keyframes rotating{from{transform:rotate(0deg);}to{transform:rotate(360deg);}}#settings-menu.rotate>a img{animation:rotating 2s linear infinite;}kbd{display:inline-block;padding:3px 5px;font:15px monospace;line-height:10px;vertical-align:middle;border:solid 1px var(--border-color);border-radius:3px;color:var(--kbd-color);background-color:var(--kbd-background);box-shadow:inset 0 -1px 0 var(--kbd-box-shadow-color);}ul.all-items>li{list-style:none;}details.dir-entry{padding-left:4px;}details.dir-entry>summary{margin:0 0 0 -4px;padding:0 0 0 4px;cursor:pointer;}details.dir-entry div.folders,details.dir-entry div.files{padding-left:23px;}details.dir-entry a{display:block;}details.toggle{contain:layout;position:relative;}details.toggle>summary.hideme{cursor:pointer;font-size:1rem;}details.toggle>summary{list-style:none;outline:none;}details.toggle>summary::-webkit-details-marker,details.toggle>summary::marker{display:none;}details.toggle>summary.hideme>span{margin-left:9px;}details.toggle>summary::before{background:url('data:image/svg+xml,') no-repeat top left;content:"";cursor:pointer;width:16px;height:16px;display:inline-block;vertical-align:middle;opacity:.5;filter:var(--toggle-filter);}details.toggle>summary.hideme>span,.more-examples-toggle summary,.more-examples-toggle .hide-more{color:var(--toggles-color);}details.toggle>summary::after{content:"Expand";overflow:hidden;width:0;height:0;position:absolute;}details.toggle>summary.hideme::after{content:"";}details.toggle>summary:focus::before,details.toggle>summary:hover::before{opacity:1;}details.toggle>summary:focus-visible::before{outline:1px dotted #000;outline-offset:1px;}details.non-exhaustive{margin-bottom:8px;}details.toggle>summary.hideme::before{position:relative;}details.toggle>summary:not(.hideme)::before{position:absolute;left:-24px;top:4px;}.impl-items>details.toggle>summary:not(.hideme)::before{position:absolute;left:-24px;}details.toggle[open] >summary.hideme{position:absolute;}details.toggle[open] >summary.hideme>span{display:none;}details.toggle[open] >summary::before{background:url('data:image/svg+xml,') no-repeat top left;}details.toggle[open] >summary::after{content:"Collapse";}.docblock summary>*{display:inline-block;}.docblock>.example-wrap:first-child .tooltip{margin-top:16px;}.src #sidebar-button>a:before,.sidebar-menu-toggle:before{content:url('data:image/svg+xml,\ + ');opacity:0.75;}.sidebar-menu-toggle:hover:before,.sidebar-menu-toggle:active:before,.sidebar-menu-toggle:focus:before{opacity:1;}.src #sidebar-button>a:before{content:url('data:image/svg+xml,\ + \ + \ + ');opacity:0.75;}@media (max-width:850px){#search-tabs .count{display:block;}}@media (max-width:700px){*[id]{scroll-margin-top:45px;}.rustdoc{display:block;}main{padding-left:15px;padding-top:0px;}.main-heading{flex-direction:column;}.out-of-band{text-align:left;margin-left:initial;padding:initial;}.out-of-band .since::before{content:"Since ";}.sidebar .logo-container,.sidebar .location,.sidebar-resizer{display:none;}.sidebar{position:fixed;top:45px;left:-1000px;z-index:11;height:calc(100vh - 45px);width:200px;}.src main,.rustdoc.src .sidebar{top:0;padding:0;height:100vh;border:0;}.src .search-form{margin-left:40px;}.hide-sidebar .search-form{margin-left:32px;}.hide-sidebar .src .search-form{margin-left:0;}.sidebar.shown,.src-sidebar-expanded .src .sidebar,.rustdoc:not(.src) .sidebar:focus-within{left:0;}.mobile-topbar h2{padding-bottom:0;margin:auto 0.5em auto auto;overflow:hidden;font-size:24px;white-space:nowrap;text-overflow:ellipsis;}.mobile-topbar .logo-container>img{max-width:35px;max-height:35px;margin:5px 0 5px 20px;}.mobile-topbar{display:flex;flex-direction:row;position:sticky;z-index:10;font-size:2rem;height:45px;width:100%;left:0;top:0;}.hide-sidebar .mobile-topbar{display:none;}.sidebar-menu-toggle{width:45px;border:none;line-height:0;}.hide-sidebar .sidebar-menu-toggle{display:none;}.sidebar-elems{margin-top:1em;}.anchor{display:none !important;}#main-content>details.toggle>summary::before,#main-content>div>details.toggle>summary::before{left:-11px;}#copy-path,#help-button{display:none;}#sidebar-button>a:before{content:url('data:image/svg+xml,\ + \ + \ + ');width:22px;height:22px;}.sidebar-menu-toggle:before{filter:var(--mobile-sidebar-menu-filter);}.sidebar-menu-toggle:hover{background:var(--main-background-color);}.item-table,.item-row,.item-table>li,.item-table>li>div,.search-results>a,.search-results>a>div{display:block;}.search-results>a{padding:5px 0px;}.search-results>a>div.desc,.item-table>li>div.desc{padding-left:2em;}.search-results .result-name{display:block;}.search-results .result-name .typename{width:initial;margin-right:0;}.search-results .result-name .typename,.search-results .result-name .path{display:inline;}.src-sidebar-expanded .src .sidebar{position:fixed;max-width:100vw;width:100vw;}.src .src-sidebar-title{padding-top:0;}details.toggle:not(.top-doc)>summary{margin-left:10px;}.impl-items>details.toggle>summary:not(.hideme)::before,#main-content>details.toggle:not(.top-doc)>summary::before,#main-content>div>details.toggle>summary::before{left:-11px;}.impl-items>.item-info{margin-left:34px;}.src nav.sub{margin:0;padding:var(--nav-sub-mobile-padding);}}@media (min-width:701px){.scraped-example-title{position:absolute;z-index:10;background:var(--main-background-color);bottom:8px;right:5px;padding:2px 4px;box-shadow:0 0 4px var(--main-background-color);}.item-table>li>.item-name{width:33%;}.item-table>li>div{overflow-wrap:anywhere;}}@media print{nav.sidebar,nav.sub,.out-of-band,a.src,#copy-path,details.toggle[open] >summary::before,details.toggle>summary::before,details.toggle.top-doc>summary{display:none;}.docblock{margin-left:0;}main{padding:10px;}}@media (max-width:464px){.docblock{margin-left:12px;}.docblock code{overflow-wrap:break-word;overflow-wrap:anywhere;}nav.sub{flex-direction:column;}.search-form{align-self:stretch;}}.variant,.implementors-toggle>summary,.impl,#implementors-list>.docblock,.impl-items>section,.impl-items>.toggle>summary,.methods>section,.methods>.toggle>summary{margin-bottom:0.75em;}.variants>.docblock,.implementors-toggle>.docblock,.impl-items>.toggle[open]:not(:last-child),.methods>.toggle[open]:not(:last-child),.implementors-toggle[open]:not(:last-child){margin-bottom:2em;}#trait-implementations-list .impl-items>.toggle:not(:last-child),#synthetic-implementations-list .impl-items>.toggle:not(:last-child),#blanket-implementations-list .impl-items>.toggle:not(:last-child){margin-bottom:1em;}.scraped-example-list .scrape-help{margin-left:10px;padding:0 4px;font-weight:normal;font-size:12px;position:relative;bottom:1px;border:1px solid var(--scrape-example-help-border-color);border-radius:50px;color:var(--scrape-example-help-color);}.scraped-example-list .scrape-help:hover{border-color:var(--scrape-example-help-hover-border-color);color:var(--scrape-example-help-hover-color);}.scraped-example{position:relative;}.scraped-example .code-wrapper{position:relative;display:flex;flex-direction:row;flex-wrap:wrap;width:100%;}.scraped-example:not(.expanded) .code-wrapper{max-height:calc(1.5em * 5 + 10px);}.scraped-example:not(.expanded) .code-wrapper pre{overflow-y:hidden;padding-bottom:0;max-height:calc(1.5em * 5 + 10px);}.more-scraped-examples .scraped-example:not(.expanded) .code-wrapper,.more-scraped-examples .scraped-example:not(.expanded) .code-wrapper pre{max-height:calc(1.5em * 10 + 10px);}.scraped-example .code-wrapper .next,.scraped-example .code-wrapper .prev,.scraped-example .code-wrapper .expand{color:var(--main-color);position:absolute;top:0.25em;z-index:1;padding:0;background:none;border:none;-webkit-appearance:none;opacity:1;}.scraped-example .code-wrapper .prev{right:2.25em;}.scraped-example .code-wrapper .next{right:1.25em;}.scraped-example .code-wrapper .expand{right:0.25em;}.scraped-example:not(.expanded) .code-wrapper::before,.scraped-example:not(.expanded) .code-wrapper::after{content:" ";width:100%;height:5px;position:absolute;z-index:1;}.scraped-example:not(.expanded) .code-wrapper::before{top:0;background:linear-gradient(to bottom,var(--scrape-example-code-wrapper-background-start),var(--scrape-example-code-wrapper-background-end));}.scraped-example:not(.expanded) .code-wrapper::after{bottom:0;background:linear-gradient(to top,var(--scrape-example-code-wrapper-background-start),var(--scrape-example-code-wrapper-background-end));}.scraped-example .code-wrapper .example-wrap{width:100%;overflow-y:hidden;margin-bottom:0;}.scraped-example:not(.expanded) .code-wrapper .example-wrap{overflow-x:hidden;}.scraped-example .example-wrap .rust span.highlight{background:var(--scrape-example-code-line-highlight);}.scraped-example .example-wrap .rust span.highlight.focus{background:var(--scrape-example-code-line-highlight-focus);}.more-examples-toggle{max-width:calc(100% + 25px);margin-top:10px;margin-left:-25px;}.more-examples-toggle .hide-more{margin-left:25px;cursor:pointer;}.more-scraped-examples{margin-left:25px;position:relative;}.toggle-line{position:absolute;top:5px;bottom:0;right:calc(100% + 10px);padding:0 4px;cursor:pointer;}.toggle-line-inner{min-width:2px;height:100%;background:var(--scrape-example-toggle-line-background);}.toggle-line:hover .toggle-line-inner{background:var(--scrape-example-toggle-line-hover-background);}.more-scraped-examples .scraped-example,.example-links{margin-top:20px;}.more-scraped-examples .scraped-example:first-child{margin-top:5px;}.example-links ul{margin-bottom:0;}:root[data-theme="light"],:root:not([data-theme]){--main-background-color:white;--main-color:black;--settings-input-color:#2196f3;--settings-input-border-color:#717171;--settings-button-color:#000;--settings-button-border-focus:#717171;--sidebar-background-color:#f5f5f5;--sidebar-background-color-hover:#e0e0e0;--code-block-background-color:#f5f5f5;--scrollbar-track-background-color:#dcdcdc;--scrollbar-thumb-background-color:rgba(36,37,39,0.6);--scrollbar-color:rgba(36,37,39,0.6) #d9d9d9;--headings-border-bottom-color:#ddd;--border-color:#e0e0e0;--button-background-color:#fff;--right-side-color:grey;--code-attribute-color:#999;--toggles-color:#999;--toggle-filter:none;--mobile-sidebar-menu-filter:none;--search-input-focused-border-color:#66afe9;--copy-path-button-color:#999;--copy-path-img-filter:invert(50%);--copy-path-img-hover-filter:invert(35%);--codeblock-error-hover-color:rgb(255,0,0);--codeblock-error-color:rgba(255,0,0,.5);--codeblock-ignore-hover-color:rgb(255,142,0);--codeblock-ignore-color:rgba(255,142,0,.6);--warning-border-color:#ff8e00;--type-link-color:#ad378a;--trait-link-color:#6e4fc9;--assoc-item-link-color:#3873ad;--function-link-color:#ad7c37;--macro-link-color:#068000;--keyword-link-color:#3873ad;--mod-link-color:#3873ad;--link-color:#3873ad;--sidebar-link-color:#356da4;--sidebar-current-link-background-color:#fff;--search-result-link-focus-background-color:#ccc;--search-result-border-color:#aaa3;--search-color:#000;--search-error-code-background-color:#d0cccc;--search-results-alias-color:#000;--search-results-grey-color:#999;--search-tab-title-count-color:#888;--search-tab-button-not-selected-border-top-color:#e6e6e6;--search-tab-button-not-selected-background:#e6e6e6;--search-tab-button-selected-border-top-color:#0089ff;--search-tab-button-selected-background:#fff;--settings-menu-filter:none;--stab-background-color:#fff5d6;--stab-code-color:#000;--code-highlight-kw-color:#8959a8;--code-highlight-kw-2-color:#4271ae;--code-highlight-lifetime-color:#b76514;--code-highlight-prelude-color:#4271ae;--code-highlight-prelude-val-color:#c82829;--code-highlight-number-color:#718c00;--code-highlight-string-color:#718c00;--code-highlight-literal-color:#c82829;--code-highlight-attribute-color:#c82829;--code-highlight-self-color:#c82829;--code-highlight-macro-color:#3e999f;--code-highlight-question-mark-color:#ff9011;--code-highlight-comment-color:#8e908c;--code-highlight-doc-comment-color:#4d4d4c;--src-line-numbers-span-color:#c67e2d;--src-line-number-highlighted-background-color:#fdffd3;--target-background-color:#fdffd3;--target-border-color:#ad7c37;--kbd-color:#000;--kbd-background:#fafbfc;--kbd-box-shadow-color:#c6cbd1;--rust-logo-filter:initial;--crate-search-div-filter:invert(100%) sepia(0%) saturate(4223%) hue-rotate(289deg) brightness(114%) contrast(76%);--crate-search-div-hover-filter:invert(44%) sepia(18%) saturate(23%) hue-rotate(317deg) brightness(96%) contrast(93%);--crate-search-hover-border:#717171;--src-sidebar-background-selected:#fff;--src-sidebar-background-hover:#e0e0e0;--table-alt-row-background-color:#f5f5f5;--codeblock-link-background:#eee;--scrape-example-toggle-line-background:#ccc;--scrape-example-toggle-line-hover-background:#999;--scrape-example-code-line-highlight:#fcffd6;--scrape-example-code-line-highlight-focus:#f6fdb0;--scrape-example-help-border-color:#555;--scrape-example-help-color:#333;--scrape-example-help-hover-border-color:#000;--scrape-example-help-hover-color:#000;--scrape-example-code-wrapper-background-start:rgba(255,255,255,1);--scrape-example-code-wrapper-background-end:rgba(255,255,255,0);--sidebar-resizer-hover:hsl(207,90%,66%);--sidebar-resizer-active:hsl(207,90%,54%);}:root[data-theme="dark"]{--main-background-color:#353535;--main-color:#ddd;--settings-input-color:#2196f3;--settings-input-border-color:#999;--settings-button-color:#000;--settings-button-border-focus:#ffb900;--sidebar-background-color:#505050;--sidebar-background-color-hover:#676767;--code-block-background-color:#2A2A2A;--scrollbar-track-background-color:#717171;--scrollbar-thumb-background-color:rgba(32,34,37,.6);--scrollbar-color:rgba(32,34,37,.6) #5a5a5a;--headings-border-bottom-color:#d2d2d2;--border-color:#e0e0e0;--button-background-color:#f0f0f0;--right-side-color:grey;--code-attribute-color:#999;--toggles-color:#999;--toggle-filter:invert(100%);--mobile-sidebar-menu-filter:invert(100%);--search-input-focused-border-color:#008dfd;--copy-path-button-color:#999;--copy-path-img-filter:invert(50%);--copy-path-img-hover-filter:invert(65%);--codeblock-error-hover-color:rgb(255,0,0);--codeblock-error-color:rgba(255,0,0,.5);--codeblock-ignore-hover-color:rgb(255,142,0);--codeblock-ignore-color:rgba(255,142,0,.6);--warning-border-color:#ff8e00;--type-link-color:#2dbfb8;--trait-link-color:#b78cf2;--assoc-item-link-color:#d2991d;--function-link-color:#2bab63;--macro-link-color:#09bd00;--keyword-link-color:#d2991d;--mod-link-color:#d2991d;--link-color:#d2991d;--sidebar-link-color:#fdbf35;--sidebar-current-link-background-color:#444;--search-result-link-focus-background-color:#616161;--search-result-border-color:#aaa3;--search-color:#111;--search-error-code-background-color:#484848;--search-results-alias-color:#fff;--search-results-grey-color:#ccc;--search-tab-title-count-color:#888;--search-tab-button-not-selected-border-top-color:#252525;--search-tab-button-not-selected-background:#252525;--search-tab-button-selected-border-top-color:#0089ff;--search-tab-button-selected-background:#353535;--settings-menu-filter:none;--stab-background-color:#314559;--stab-code-color:#e6e1cf;--code-highlight-kw-color:#ab8ac1;--code-highlight-kw-2-color:#769acb;--code-highlight-lifetime-color:#d97f26;--code-highlight-prelude-color:#769acb;--code-highlight-prelude-val-color:#ee6868;--code-highlight-number-color:#83a300;--code-highlight-string-color:#83a300;--code-highlight-literal-color:#ee6868;--code-highlight-attribute-color:#ee6868;--code-highlight-self-color:#ee6868;--code-highlight-macro-color:#3e999f;--code-highlight-question-mark-color:#ff9011;--code-highlight-comment-color:#8d8d8b;--code-highlight-doc-comment-color:#8ca375;--src-line-numbers-span-color:#3b91e2;--src-line-number-highlighted-background-color:#0a042f;--target-background-color:#494a3d;--target-border-color:#bb7410;--kbd-color:#000;--kbd-background:#fafbfc;--kbd-box-shadow-color:#c6cbd1;--rust-logo-filter:drop-shadow(1px 0 0px #fff) drop-shadow(0 1px 0 #fff) drop-shadow(-1px 0 0 #fff) drop-shadow(0 -1px 0 #fff);--crate-search-div-filter:invert(94%) sepia(0%) saturate(721%) hue-rotate(255deg) brightness(90%) contrast(90%);--crate-search-div-hover-filter:invert(69%) sepia(60%) saturate(6613%) hue-rotate(184deg) brightness(100%) contrast(91%);--crate-search-hover-border:#2196f3;--src-sidebar-background-selected:#333;--src-sidebar-background-hover:#444;--table-alt-row-background-color:#2a2a2a;--codeblock-link-background:#333;--scrape-example-toggle-line-background:#999;--scrape-example-toggle-line-hover-background:#c5c5c5;--scrape-example-code-line-highlight:#5b3b01;--scrape-example-code-line-highlight-focus:#7c4b0f;--scrape-example-help-border-color:#aaa;--scrape-example-help-color:#eee;--scrape-example-help-hover-border-color:#fff;--scrape-example-help-hover-color:#fff;--scrape-example-code-wrapper-background-start:rgba(53,53,53,1);--scrape-example-code-wrapper-background-end:rgba(53,53,53,0);--sidebar-resizer-hover:hsl(207,30%,54%);--sidebar-resizer-active:hsl(207,90%,54%);}:root[data-theme="ayu"]{--main-background-color:#0f1419;--main-color:#c5c5c5;--settings-input-color:#ffb454;--settings-input-border-color:#999;--settings-button-color:#fff;--settings-button-border-focus:#e0e0e0;--sidebar-background-color:#14191f;--sidebar-background-color-hover:rgba(70,70,70,0.33);--code-block-background-color:#191f26;--scrollbar-track-background-color:transparent;--scrollbar-thumb-background-color:#5c6773;--scrollbar-color:#5c6773 #24292f;--headings-border-bottom-color:#5c6773;--border-color:#5c6773;--button-background-color:#141920;--right-side-color:grey;--code-attribute-color:#999;--toggles-color:#999;--toggle-filter:invert(100%);--mobile-sidebar-menu-filter:invert(100%);--search-input-focused-border-color:#5c6773;--copy-path-button-color:#fff;--copy-path-img-filter:invert(70%);--copy-path-img-hover-filter:invert(100%);--codeblock-error-hover-color:rgb(255,0,0);--codeblock-error-color:rgba(255,0,0,.5);--codeblock-ignore-hover-color:rgb(255,142,0);--codeblock-ignore-color:rgba(255,142,0,.6);--warning-border-color:#ff8e00;--type-link-color:#ffa0a5;--trait-link-color:#39afd7;--assoc-item-link-color:#39afd7;--function-link-color:#fdd687;--macro-link-color:#a37acc;--keyword-link-color:#39afd7;--mod-link-color:#39afd7;--link-color:#39afd7;--sidebar-link-color:#53b1db;--sidebar-current-link-background-color:transparent;--search-result-link-focus-background-color:#3c3c3c;--search-result-border-color:#aaa3;--search-color:#fff;--search-error-code-background-color:#4f4c4c;--search-results-alias-color:#c5c5c5;--search-results-grey-color:#999;--search-tab-title-count-color:#888;--search-tab-button-not-selected-border-top-color:none;--search-tab-button-not-selected-background:transparent !important;--search-tab-button-selected-border-top-color:none;--search-tab-button-selected-background:#141920 !important;--settings-menu-filter:invert(100%);--stab-background-color:#314559;--stab-code-color:#e6e1cf;--code-highlight-kw-color:#ff7733;--code-highlight-kw-2-color:#ff7733;--code-highlight-lifetime-color:#ff7733;--code-highlight-prelude-color:#69f2df;--code-highlight-prelude-val-color:#ff7733;--code-highlight-number-color:#b8cc52;--code-highlight-string-color:#b8cc52;--code-highlight-literal-color:#ff7733;--code-highlight-attribute-color:#e6e1cf;--code-highlight-self-color:#36a3d9;--code-highlight-macro-color:#a37acc;--code-highlight-question-mark-color:#ff9011;--code-highlight-comment-color:#788797;--code-highlight-doc-comment-color:#a1ac88;--src-line-numbers-span-color:#5c6773;--src-line-number-highlighted-background-color:rgba(255,236,164,0.06);--target-background-color:rgba(255,236,164,0.06);--target-border-color:rgba(255,180,76,0.85);--kbd-color:#c5c5c5;--kbd-background:#314559;--kbd-box-shadow-color:#5c6773;--rust-logo-filter:drop-shadow(1px 0 0px #fff) drop-shadow(0 1px 0 #fff) drop-shadow(-1px 0 0 #fff) drop-shadow(0 -1px 0 #fff);--crate-search-div-filter:invert(41%) sepia(12%) saturate(487%) hue-rotate(171deg) brightness(94%) contrast(94%);--crate-search-div-hover-filter:invert(98%) sepia(12%) saturate(81%) hue-rotate(343deg) brightness(113%) contrast(76%);--crate-search-hover-border:#e0e0e0;--src-sidebar-background-selected:#14191f;--src-sidebar-background-hover:#14191f;--table-alt-row-background-color:#191f26;--codeblock-link-background:#333;--scrape-example-toggle-line-background:#999;--scrape-example-toggle-line-hover-background:#c5c5c5;--scrape-example-code-line-highlight:#5b3b01;--scrape-example-code-line-highlight-focus:#7c4b0f;--scrape-example-help-border-color:#aaa;--scrape-example-help-color:#eee;--scrape-example-help-hover-border-color:#fff;--scrape-example-help-hover-color:#fff;--scrape-example-code-wrapper-background-start:rgba(15,20,25,1);--scrape-example-code-wrapper-background-end:rgba(15,20,25,0);--sidebar-resizer-hover:hsl(34,50%,33%);--sidebar-resizer-active:hsl(34,100%,66%);}:root[data-theme="ayu"] h1,:root[data-theme="ayu"] h2,:root[data-theme="ayu"] h3,:root[data-theme="ayu"] h4,:where(:root[data-theme="ayu"]) h1 a,:root[data-theme="ayu"] .sidebar h2 a,:root[data-theme="ayu"] .sidebar h3 a{color:#fff;}:root[data-theme="ayu"] .docblock code{color:#ffb454;}:root[data-theme="ayu"] .docblock a>code{color:#39AFD7 !important;}:root[data-theme="ayu"] .code-header,:root[data-theme="ayu"] .docblock pre>code,:root[data-theme="ayu"] pre,:root[data-theme="ayu"] pre>code,:root[data-theme="ayu"] .item-info code,:root[data-theme="ayu"] .rustdoc.source .example-wrap{color:#e6e1cf;}:root[data-theme="ayu"] .sidebar .current,:root[data-theme="ayu"] .sidebar .current a,:root[data-theme="ayu"] .sidebar a:hover,:root[data-theme="ayu"] #src-sidebar div.files>a:hover,:root[data-theme="ayu"] details.dir-entry summary:hover,:root[data-theme="ayu"] #src-sidebar div.files>a:focus,:root[data-theme="ayu"] details.dir-entry summary:focus,:root[data-theme="ayu"] #src-sidebar div.files>a.selected{color:#ffb44c;}:root[data-theme="ayu"] .sidebar-elems .location{color:#ff7733;}:root[data-theme="ayu"] .src-line-numbers .line-highlighted{color:#708090;padding-right:7px;border-right:1px solid #ffb44c;}:root[data-theme="ayu"] .search-results a:hover,:root[data-theme="ayu"] .search-results a:focus{color:#fff !important;background-color:#3c3c3c;}:root[data-theme="ayu"] .search-results a{color:#0096cf;}:root[data-theme="ayu"] .search-results a div.desc{color:#c5c5c5;}:root[data-theme="ayu"] .result-name .primitive>i,:root[data-theme="ayu"] .result-name .keyword>i{color:#788797;}:root[data-theme="ayu"] #search-tabs>button.selected{border-bottom:1px solid #ffb44c !important;border-top:none;}:root[data-theme="ayu"] #search-tabs>button:not(.selected){border:none;background-color:transparent !important;}:root[data-theme="ayu"] #search-tabs>button:hover{border-bottom:1px solid rgba(242,151,24,0.3);}:root[data-theme="ayu"] #settings-menu>a img,:root[data-theme="ayu"] #sidebar-button>a:before{filter:invert(100);} \ No newline at end of file diff --git a/apps/rust_docs/static.files/search-a99f1315e7cc5121.js b/apps/rust_docs/static.files/search-a99f1315e7cc5121.js new file mode 100644 index 00000000..aee0fc77 --- /dev/null +++ b/apps/rust_docs/static.files/search-a99f1315e7cc5121.js @@ -0,0 +1,5 @@ +"use strict";if(!Array.prototype.toSpliced){Array.prototype.toSpliced=function(){const me=this.slice();Array.prototype.splice.apply(me,arguments);return me}}(function(){const itemTypes=["keyword","primitive","mod","externcrate","import","struct","enum","fn","type","static","trait","impl","tymethod","method","structfield","variant","macro","associatedtype","constant","associatedconstant","union","foreigntype","existential","attr","derive","traitalias","generic",];const TY_GENERIC=itemTypes.indexOf("generic");const TY_IMPORT=itemTypes.indexOf("import");const ROOT_PATH=typeof window!=="undefined"?window.rootPath:"../";const UNBOXING_LIMIT=5;const REGEX_IDENT=/\p{ID_Start}\p{ID_Continue}*|_\p{ID_Continue}+/uy;const REGEX_INVALID_TYPE_FILTER=/[^a-z]/ui;const MAX_RESULTS=200;const NO_TYPE_FILTER=-1;const editDistanceState={current:[],prev:[],prevPrev:[],calculate:function calculate(a,b,limit){if(a.lengthlimit){return limit+1}while(b.length>0&&b[0]===a[0]){a=a.substring(1);b=b.substring(1)}while(b.length>0&&b[b.length-1]===a[a.length-1]){a=a.substring(0,a.length-1);b=b.substring(0,b.length-1)}if(b.length===0){return minDist}const aLength=a.length;const bLength=b.length;for(let i=0;i<=bLength;++i){this.current[i]=0;this.prev[i]=i;this.prevPrev[i]=Number.MAX_VALUE}for(let i=1;i<=aLength;++i){this.current[0]=i;const aIdx=i-1;for(let j=1;j<=bLength;++j){const bIdx=j-1;const substitutionCost=a[aIdx]===b[bIdx]?0:1;this.current[j]=Math.min(this.prev[j]+1,this.current[j-1]+1,this.prev[j-1]+substitutionCost,);if((i>1)&&(j>1)&&(a[aIdx]===b[bIdx-1])&&(a[aIdx-1]===b[bIdx])){this.current[j]=Math.min(this.current[j],this.prevPrev[j-2]+1,)}}const prevPrevTmp=this.prevPrev;this.prevPrev=this.prev;this.prev=this.current;this.current=prevPrevTmp}const distance=this.prev[bLength];return distance<=limit?distance:(limit+1)},};function editDistance(a,b,limit){return editDistanceState.calculate(a,b,limit)}function isEndCharacter(c){return"=,>-])".indexOf(c)!==-1}function isSeparatorCharacter(c){return c===","||c==="="}function isReturnArrow(parserState){return parserState.userQuery.slice(parserState.pos,parserState.pos+2)==="->"}function skipWhitespace(parserState){while(parserState.pos0){const c=parserState.userQuery[pos-1];if(c===lookingFor){return true}else if(c!==" "){break}pos-=1}return false}function isLastElemGeneric(elems,parserState){return(elems.length>0&&elems[elems.length-1].generics.length>0)||prevIs(parserState,">")}function getFilteredNextElem(query,parserState,elems,isInGenerics){const start=parserState.pos;if(parserState.userQuery[parserState.pos]===":"&&!isPathStart(parserState)){throw["Expected type filter before ",":"]}getNextElem(query,parserState,elems,isInGenerics);if(parserState.userQuery[parserState.pos]===":"&&!isPathStart(parserState)){if(parserState.typeFilter!==null){throw["Unexpected ",":"," (expected path after type filter ",parserState.typeFilter+":",")",]}if(elems.length===0){throw["Expected type filter before ",":"]}else if(query.literalSearch){throw["Cannot use quotes on type filter"]}const typeFilterElem=elems.pop();checkExtraTypeFilterCharacters(start,parserState);parserState.typeFilter=typeFilterElem.name;parserState.pos+=1;parserState.totalElems-=1;query.literalSearch=false;getNextElem(query,parserState,elems,isInGenerics)}}function getItemsBefore(query,parserState,elems,endChar){let foundStopChar=true;let foundSeparator=false;const oldTypeFilter=parserState.typeFilter;parserState.typeFilter=null;const oldIsInBinding=parserState.isInBinding;parserState.isInBinding=null;let hofParameters=null;let extra="";if(endChar===">"){extra="<"}else if(endChar==="]"){extra="["}else if(endChar===")"){extra="("}else if(endChar===""){extra="->"}else{extra=endChar}while(parserState.pos"," after ","="]}hofParameters=[...elems];elems.length=0;parserState.pos+=2;foundStopChar=true;foundSeparator=false;continue}else if(c===" "){parserState.pos+=1;continue}else if(isSeparatorCharacter(c)){parserState.pos+=1;foundStopChar=true;foundSeparator=true;continue}else if(c===":"&&isPathStart(parserState)){throw["Unexpected ","::",": paths cannot start with ","::"]}else if(isEndCharacter(c)){throw["Unexpected ",c," after ",extra]}if(!foundStopChar){let extra=[];if(isLastElemGeneric(query.elems,parserState)){extra=[" after ",">"]}else if(prevIs(parserState,"\"")){throw["Cannot have more than one element if you use quotes"]}if(endChar!==""){throw["Expected ",",",", ","=",", or ",endChar,...extra,", found ",c,]}throw["Expected ",","," or ","=",...extra,", found ",c,]}const posBefore=parserState.pos;getFilteredNextElem(query,parserState,elems,endChar!=="");if(endChar!==""&&parserState.pos>=parserState.length){throw["Unclosed ",extra]}if(posBefore===parserState.pos){parserState.pos+=1}foundStopChar=false}if(parserState.pos>=parserState.length&&endChar!==""){throw["Unclosed ",extra]}parserState.pos+=1;if(hofParameters){foundSeparator=false;if([...elems,...hofParameters].some(x=>x.bindingName)||parserState.isInBinding){throw["Unexpected ","="," within ","->"]}const hofElem=makePrimitiveElement("->",{generics:hofParameters,bindings:new Map([["output",[...elems]]]),typeFilter:null,});elems.length=0;elems[0]=hofElem}parserState.typeFilter=oldTypeFilter;parserState.isInBinding=oldIsInBinding;return{foundSeparator}}function getNextElem(query,parserState,elems,isInGenerics){const generics=[];skipWhitespace(parserState);let start=parserState.pos;let end;if("[(".indexOf(parserState.userQuery[parserState.pos])!==-1){let endChar=")";let name="()";let friendlyName="tuple";if(parserState.userQuery[parserState.pos]==="["){endChar="]";name="[]";friendlyName="slice"}parserState.pos+=1;const{foundSeparator}=getItemsBefore(query,parserState,generics,endChar);const typeFilter=parserState.typeFilter;const bindingName=parserState.isInBinding;parserState.typeFilter=null;parserState.isInBinding=null;for(const gen of generics){if(gen.bindingName!==null){throw["Type parameter ","=",` cannot be within ${friendlyName} `,name]}}if(name==="()"&&!foundSeparator&&generics.length===1&&typeFilter===null){elems.push(generics[0])}else if(name==="()"&&generics.length===1&&generics[0].name==="->"){generics[0].typeFilter=typeFilter;elems.push(generics[0])}else{if(typeFilter!==null&&typeFilter!=="primitive"){throw["Invalid search type: primitive ",name," and ",typeFilter," both specified",]}parserState.totalElems+=1;if(isInGenerics){parserState.genericsElems+=1}elems.push(makePrimitiveElement(name,{bindingName,generics}))}}else if(parserState.userQuery[parserState.pos]==="&"){if(parserState.typeFilter!==null&&parserState.typeFilter!=="primitive"){throw["Invalid search type: primitive ","&"," and ",parserState.typeFilter," both specified",]}parserState.typeFilter=null;parserState.pos+=1;let c=parserState.userQuery[parserState.pos];while(c===" "&&parserState.pos=end){throw["Found generics without a path"]}parserState.pos+=1;getItemsBefore(query,parserState,generics,">")}else if(parserState.pos=end){throw["Found generics without a path"]}if(parserState.isInBinding){throw["Unexpected ","("," after ","="]}parserState.pos+=1;const typeFilter=parserState.typeFilter;parserState.typeFilter=null;getItemsBefore(query,parserState,generics,")");skipWhitespace(parserState);if(isReturnArrow(parserState)){parserState.pos+=2;skipWhitespace(parserState);getFilteredNextElem(query,parserState,generics,isInGenerics);generics[generics.length-1].bindingName=makePrimitiveElement("output")}else{generics.push(makePrimitiveElement(null,{bindingName:makePrimitiveElement("output"),typeFilter:null,}))}parserState.typeFilter=typeFilter}if(isStringElem){skipWhitespace(parserState)}if(start>=end&&generics.length===0){return}if(parserState.userQuery[parserState.pos]==="="){if(parserState.isInBinding){throw["Cannot write ","="," twice in a binding"]}if(!isInGenerics){throw["Type parameter ","="," must be within generics list"]}const name=parserState.userQuery.slice(start,end).trim();if(name==="!"){throw["Type parameter ","="," key cannot be ","!"," never type"]}if(name.includes("!")){throw["Type parameter ","="," key cannot be ","!"," macro"]}if(name.includes("::")){throw["Type parameter ","="," key cannot contain ","::"," path"]}if(name.includes(":")){throw["Type parameter ","="," key cannot contain ",":"," type"]}parserState.isInBinding={name,generics}}else{elems.push(createQueryElement(query,parserState,parserState.userQuery.slice(start,end),generics,isInGenerics,),)}}}function checkExtraTypeFilterCharacters(start,parserState){const query=parserState.userQuery.slice(start,parserState.pos).trim();const match=query.match(REGEX_INVALID_TYPE_FILTER);if(match){throw["Unexpected ",match[0]," in type filter (before ",":",")",]}}function createQueryElement(query,parserState,name,generics,isInGenerics){const path=name.trim();if(path.length===0&&generics.length===0){throw["Unexpected ",parserState.userQuery[parserState.pos]]}if(query.literalSearch&&parserState.totalElems-parserState.genericsElems>0){throw["Cannot have more than one element if you use quotes"]}const typeFilter=parserState.typeFilter;parserState.typeFilter=null;if(name==="!"){if(typeFilter!==null&&typeFilter!=="primitive"){throw["Invalid search type: primitive never type ","!"," and ",typeFilter," both specified",]}if(generics.length!==0){throw["Never type ","!"," does not accept generic parameters",]}const bindingName=parserState.isInBinding;parserState.isInBinding=null;return makePrimitiveElement("never",{bindingName})}const quadcolon=/::\s*::/.exec(path);if(path.startsWith("::")){throw["Paths cannot start with ","::"]}else if(path.endsWith("::")){throw["Paths cannot end with ","::"]}else if(quadcolon!==null){throw["Unexpected ",quadcolon[0]]}const pathSegments=path.split(/(?:::\s*)|(?:\s+(?:::\s*)?)/);if(pathSegments.length===0||(pathSegments.length===1&&pathSegments[0]==="")){if(generics.length>0||prevIs(parserState,">")){throw["Found generics without a path"]}else{throw["Unexpected ",parserState.userQuery[parserState.pos]]}}for(const[i,pathSegment]of pathSegments.entries()){if(pathSegment==="!"){if(i!==0){throw["Never type ","!"," is not associated item"]}pathSegments[i]="never"}}parserState.totalElems+=1;if(isInGenerics){parserState.genericsElems+=1}const bindingName=parserState.isInBinding;parserState.isInBinding=null;const bindings=new Map();const pathLast=pathSegments[pathSegments.length-1];return{name:name.trim(),id:null,fullPath:pathSegments,pathWithoutLast:pathSegments.slice(0,pathSegments.length-1),pathLast,normalizedPathLast:pathLast.replace(/_/g,""),generics:generics.filter(gen=>{if(gen.bindingName!==null){if(gen.name!==null){gen.bindingName.generics.unshift(gen)}bindings.set(gen.bindingName.name,gen.bindingName.generics);return false}return true}),bindings,typeFilter,bindingName,}}function makePrimitiveElement(name,extra){return Object.assign({name,id:null,fullPath:[name],pathWithoutLast:[],pathLast:name,normalizedPathLast:name,generics:[],bindings:new Map(),typeFilter:"primitive",bindingName:null,},extra)}function getStringElem(query,parserState,isInGenerics){if(isInGenerics){throw["Unexpected ","\""," in generics"]}else if(query.literalSearch){throw["Cannot have more than one literal search element"]}else if(parserState.totalElems-parserState.genericsElems>0){throw["Cannot use literal search when there is more than one element"]}parserState.pos+=1;const start=parserState.pos;const end=getIdentEndPosition(parserState);if(parserState.pos>=parserState.length){throw["Unclosed ","\""]}else if(parserState.userQuery[end]!=="\""){throw["Unexpected ",parserState.userQuery[end]," in a string element"]}else if(start===end){throw["Cannot have empty string element"]}parserState.pos+=1;query.literalSearch=true}function getIdentEndPosition(parserState){let afterIdent=consumeIdent(parserState);let end=parserState.pos;let macroExclamation=-1;while(parserState.pos0){throw["Unexpected ",c," after ",parserState.userQuery[parserState.pos-1]," (not a valid identifier)"]}else{throw["Unexpected ",c," (not a valid identifier)"]}parserState.pos+=1;afterIdent=consumeIdent(parserState);end=parserState.pos}if(macroExclamation!==-1){if(parserState.typeFilter===null){parserState.typeFilter="macro"}else if(parserState.typeFilter!=="macro"){throw["Invalid search type: macro ","!"," and ",parserState.typeFilter," both specified",]}end=macroExclamation}return end}function isSpecialStartCharacter(c){return"<\"".indexOf(c)!==-1}function isPathStart(parserState){return parserState.userQuery.slice(parserState.pos,parserState.pos+2)==="::"}function consumeIdent(parserState){REGEX_IDENT.lastIndex=parserState.pos;const match=parserState.userQuery.match(REGEX_IDENT);if(match){parserState.pos+=match[0].length;return true}return false}function isPathSeparator(c){return c===":"||c===" "}class VlqHexDecoder{constructor(string,cons){this.string=string;this.cons=cons;this.offset=0;this.backrefQueue=[]}decodeList(){let c=this.string.charCodeAt(this.offset);const ret=[];while(c!==125){ret.push(this.decode());c=this.string.charCodeAt(this.offset)}this.offset+=1;return ret}decode(){let n=0;let c=this.string.charCodeAt(this.offset);if(c===123){this.offset+=1;return this.decodeList()}while(c<96){n=(n<<4)|(c&0xF);this.offset+=1;c=this.string.charCodeAt(this.offset)}n=(n<<4)|(c&0xF);const[sign,value]=[n&1,n>>1];this.offset+=1;return sign?-value:value}next(){const c=this.string.charCodeAt(this.offset);if(c>=48&&c<64){this.offset+=1;return this.backrefQueue[c-48]}if(c===96){this.offset+=1;return this.cons(0)}const result=this.cons(this.decode());this.backrefQueue.unshift(result);if(this.backrefQueue.length>16){this.backrefQueue.pop()}return result}}class RoaringBitmap{constructor(str){const strdecoded=atob(str);const u8array=new Uint8Array(strdecoded.length);for(let j=0;j=4){offsets=[];for(let j=0;j>3]&(1<<(j&0x7))){const runcount=(u8array[i]|(u8array[i+1]<<8));i+=2;this.containers.push(new RoaringBitmapRun(runcount,u8array.slice(i,i+(runcount*4)),));i+=runcount*4}else if(this.cardinalities[j]>=4096){this.containers.push(new RoaringBitmapBits(u8array.slice(i,i+8192)));i+=8192}else{const end=this.cardinalities[j]*2;this.containers.push(new RoaringBitmapArray(this.cardinalities[j],u8array.slice(i,i+end),));i+=end}}}contains(keyvalue){const key=keyvalue>>16;const value=keyvalue&0xFFFF;for(let i=0;i=start&&value<=(start+lenm1)){return true}}return false}}class RoaringBitmapArray{constructor(cardinality,array){this.cardinality=cardinality;this.array=array}contains(value){const l=this.cardinality*2;for(let i=0;i>3]&(1<<(value&7)))}}class DocSearch{constructor(rawSearchIndex,rootPath,searchState){this.searchIndexDeprecated=new Map();this.searchIndexEmptyDesc=new Map();this.functionTypeFingerprint=null;this.typeNameIdMap=new Map();this.ALIASES=new Map();this.rootPath=rootPath;this.searchState=searchState;this.typeNameIdOfArray=this.buildTypeMapIndex("array");this.typeNameIdOfSlice=this.buildTypeMapIndex("slice");this.typeNameIdOfArrayOrSlice=this.buildTypeMapIndex("[]");this.typeNameIdOfTuple=this.buildTypeMapIndex("tuple");this.typeNameIdOfUnit=this.buildTypeMapIndex("unit");this.typeNameIdOfTupleOrUnit=this.buildTypeMapIndex("()");this.typeNameIdOfFn=this.buildTypeMapIndex("fn");this.typeNameIdOfFnMut=this.buildTypeMapIndex("fnmut");this.typeNameIdOfFnOnce=this.buildTypeMapIndex("fnonce");this.typeNameIdOfHof=this.buildTypeMapIndex("->");this.EMPTY_BINDINGS_MAP=new Map();this.EMPTY_GENERICS_ARRAY=[];this.TYPES_POOL=new Map();this.searchIndex=this.buildIndex(rawSearchIndex)}buildTypeMapIndex(name,isAssocType){if(name===""||name===null){return null}if(this.typeNameIdMap.has(name)){const obj=this.typeNameIdMap.get(name);obj.assocOnly=isAssocType&&obj.assocOnly;return obj.id}else{const id=this.typeNameIdMap.size;this.typeNameIdMap.set(name,{id,assocOnly:isAssocType});return id}}buildItemSearchTypeAll(types,lowercasePaths){return types.length>0?types.map(type=>this.buildItemSearchType(type,lowercasePaths)):this.EMPTY_GENERICS_ARRAY}buildItemSearchType(type,lowercasePaths,isAssocType){const PATH_INDEX_DATA=0;const GENERICS_DATA=1;const BINDINGS_DATA=2;let pathIndex,generics,bindings;if(typeof type==="number"){pathIndex=type;generics=this.EMPTY_GENERICS_ARRAY;bindings=this.EMPTY_BINDINGS_MAP}else{pathIndex=type[PATH_INDEX_DATA];generics=this.buildItemSearchTypeAll(type[GENERICS_DATA],lowercasePaths,);if(type.length>BINDINGS_DATA&&type[BINDINGS_DATA].length>0){bindings=new Map(type[BINDINGS_DATA].map(binding=>{const[assocType,constraints]=binding;return[this.buildItemSearchType(assocType,lowercasePaths,true).id,this.buildItemSearchTypeAll(constraints,lowercasePaths),]}))}else{bindings=this.EMPTY_BINDINGS_MAP}}let result;if(pathIndex<0){result={id:pathIndex,ty:TY_GENERIC,path:null,exactPath:null,generics,bindings,}}else if(pathIndex===0){result={id:null,ty:null,path:null,exactPath:null,generics,bindings,}}else{const item=lowercasePaths[pathIndex-1];result={id:this.buildTypeMapIndex(item.name,isAssocType),ty:item.ty,path:item.path,exactPath:item.exactPath,generics,bindings,}}const cr=this.TYPES_POOL.get(result.id);if(cr){if(cr.generics.length===result.generics.length&&cr.generics!==result.generics&&cr.generics.every((x,i)=>result.generics[i]===x)){result.generics=cr.generics}if(cr.bindings.size===result.bindings.size&&cr.bindings!==result.bindings){let ok=true;for(const[k,v]of cr.bindings.entries()){const v2=result.bindings.get(v);if(!v2){ok=false;break}if(v!==v2&&v.length===v2.length&&v.every((x,i)=>v2[i]===x)){result.bindings.set(k,v)}else if(v!==v2){ok=false;break}}if(ok){result.bindings=cr.bindings}}if(cr.ty===result.ty&&cr.path===result.path&&cr.bindings===result.bindings&&cr.generics===result.generics&&cr.ty===result.ty){return cr}}this.TYPES_POOL.set(result.id,result);return result}buildFunctionTypeFingerprint(type,output,fps){let input=type.id;if(input===this.typeNameIdOfArray||input===this.typeNameIdOfSlice){input=this.typeNameIdOfArrayOrSlice}if(input===this.typeNameIdOfTuple||input===this.typeNameIdOfUnit){input=this.typeNameIdOfTupleOrUnit}if(input===this.typeNameIdOfFn||input===this.typeNameIdOfFnMut||input===this.typeNameIdOfFnOnce){input=this.typeNameIdOfHof}const hashint1=k=>{k=(~~k+0x7ed55d16)+(k<<12);k=(k ^ 0xc761c23c)^(k>>>19);k=(~~k+0x165667b1)+(k<<5);k=(~~k+0xd3a2646c)^(k<<9);k=(~~k+0xfd7046c5)+(k<<3);return(k ^ 0xb55a4f09)^(k>>>16)};const hashint2=k=>{k=~k+(k<<15);k ^=k>>>12;k+=k<<2;k ^=k>>>4;k=Math.imul(k,2057);return k ^(k>>16)};if(input!==null){const h0a=hashint1(input);const h0b=hashint2(input);const h1a=~~(h0a+Math.imul(h0b,2));const h1b=~~(h0a+Math.imul(h0b,3));const h2a=~~(h0a+Math.imul(h0b,4));const h2b=~~(h0a+Math.imul(h0b,5));output[0]|=(1<<(h0a%32))|(1<<(h1b%32));output[1]|=(1<<(h1a%32))|(1<<(h2b%32));output[2]|=(1<<(h2a%32))|(1<<(h0b%32));fps.add(input)}for(const g of type.generics){this.buildFunctionTypeFingerprint(g,output,fps)}const fb={id:null,ty:0,generics:this.EMPTY_GENERICS_ARRAY,bindings:this.EMPTY_BINDINGS_MAP,};for(const[k,v]of type.bindings.entries()){fb.id=k;fb.generics=v;this.buildFunctionTypeFingerprint(fb,output,fps)}output[3]=fps.size}buildIndex(rawSearchIndex){const buildFunctionSearchTypeCallback=lowercasePaths=>{return functionSearchType=>{if(functionSearchType===0){return null}const INPUTS_DATA=0;const OUTPUT_DATA=1;let inputs,output;if(typeof functionSearchType[INPUTS_DATA]==="number"){inputs=[this.buildItemSearchType(functionSearchType[INPUTS_DATA],lowercasePaths),]}else{inputs=this.buildItemSearchTypeAll(functionSearchType[INPUTS_DATA],lowercasePaths,)}if(functionSearchType.length>1){if(typeof functionSearchType[OUTPUT_DATA]==="number"){output=[this.buildItemSearchType(functionSearchType[OUTPUT_DATA],lowercasePaths,),]}else{output=this.buildItemSearchTypeAll(functionSearchType[OUTPUT_DATA],lowercasePaths,)}}else{output=[]}const where_clause=[];const l=functionSearchType.length;for(let i=2;inoop);let descShard={crate,shard:0,start:0,len:itemDescShardDecoder.next(),promise:null,resolve:null,};const descShardList=[descShard];this.searchIndexDeprecated.set(crate,new RoaringBitmap(crateCorpus.c));this.searchIndexEmptyDesc.set(crate,new RoaringBitmap(crateCorpus.e));let descIndex=0;const crateRow={crate,ty:3,name:crate,path:"",descShard,descIndex,exactPath:"",desc:crateCorpus.doc,parent:undefined,type:null,id,word:crate,normalizedName:crate.indexOf("_")===-1?crate:crate.replace(/_/g,""),bitIndex:0,implDisambiguator:null,};id+=1;searchIndex.push(crateRow);currentIndex+=1;if(!this.searchIndexEmptyDesc.get(crate).contains(0)){descIndex+=1}const itemTypes=crateCorpus.t;const itemNames=crateCorpus.n;const itemPaths=new Map(crateCorpus.q);const itemReexports=new Map(crateCorpus.r);const itemParentIdxDecoder=new VlqHexDecoder(crateCorpus.i,noop=>noop);const implDisambiguator=new Map(crateCorpus.b);const paths=crateCorpus.p;const aliases=crateCorpus.a;const lowercasePaths=[];const itemFunctionDecoder=new VlqHexDecoder(crateCorpus.f,buildFunctionSearchTypeCallback(lowercasePaths),);let len=paths.length;let lastPath=itemPaths.get(0);for(let i=0;i2){path=itemPaths.has(elem[2])?itemPaths.get(elem[2]):lastPath;lastPath=path}const exactPath=elem.length>3?itemPaths.get(elem[3]):path;lowercasePaths.push({ty,name:name.toLowerCase(),path,exactPath});paths[i]={ty,name,path,exactPath}}lastPath="";len=itemTypes.length;let lastName="";let lastWord="";for(let i=0;i=descShard.len&&!this.searchIndexEmptyDesc.get(crate).contains(bitIndex)){descShard={crate,shard:descShard.shard+1,start:descShard.start+descShard.len,len:itemDescShardDecoder.next(),promise:null,resolve:null,};descIndex=0;descShardList.push(descShard)}const name=itemNames[i]===""?lastName:itemNames[i];const word=itemNames[i]===""?lastWord:itemNames[i].toLowerCase();const path=itemPaths.has(i)?itemPaths.get(i):lastPath;const type=itemFunctionDecoder.next();if(type!==null){if(type){const fp=this.functionTypeFingerprint.subarray(id*4,(id+1)*4);const fps=new Set();for(const t of type.inputs){this.buildFunctionTypeFingerprint(t,fp,fps)}for(const t of type.output){this.buildFunctionTypeFingerprint(t,fp,fps)}for(const w of type.where_clause){for(const t of w){this.buildFunctionTypeFingerprint(t,fp,fps)}}}}const itemParentIdx=itemParentIdxDecoder.next();const row={crate,ty:itemTypes.charCodeAt(i)-65,name,path,descShard,descIndex,exactPath:itemReexports.has(i)?itemPaths.get(itemReexports.get(i)):path,parent:itemParentIdx>0?paths[itemParentIdx-1]:undefined,type,id,word,normalizedName:word.indexOf("_")===-1?word:word.replace(/_/g,""),bitIndex,implDisambiguator:implDisambiguator.has(i)?implDisambiguator.get(i):null,};id+=1;searchIndex.push(row);lastPath=row.path;if(!this.searchIndexEmptyDesc.get(crate).contains(bitIndex)){descIndex+=1}lastName=name;lastWord=word}if(aliases){const currentCrateAliases=new Map();this.ALIASES.set(crate,currentCrateAliases);for(const alias_name in aliases){if(!Object.prototype.hasOwnProperty.call(aliases,alias_name)){continue}let currentNameAliases;if(currentCrateAliases.has(alias_name)){currentNameAliases=currentCrateAliases.get(alias_name)}else{currentNameAliases=[];currentCrateAliases.set(alias_name,currentNameAliases)}for(const local_alias of aliases[alias_name]){currentNameAliases.push(local_alias+currentIndex)}}}currentIndex+=itemTypes.length;this.searchState.descShards.set(crate,descShardList)}this.TYPES_POOL=new Map();return searchIndex}static parseQuery(userQuery){function itemTypeFromName(typename){const index=itemTypes.findIndex(i=>i===typename);if(index<0){throw["Unknown type filter ",typename]}return index}function convertTypeFilterOnElem(elem){if(elem.typeFilter!==null){let typeFilter=elem.typeFilter;if(typeFilter==="const"){typeFilter="constant"}elem.typeFilter=itemTypeFromName(typeFilter)}else{elem.typeFilter=NO_TYPE_FILTER}for(const elem2 of elem.generics){convertTypeFilterOnElem(elem2)}for(const constraints of elem.bindings.values()){for(const constraint of constraints){convertTypeFilterOnElem(constraint)}}}function newParsedQuery(userQuery){return{original:userQuery,userQuery:userQuery.toLowerCase(),elems:[],returned:[],foundElems:0,totalElems:0,literalSearch:false,error:null,correction:null,proposeCorrectionFrom:null,proposeCorrectionTo:null,typeFingerprint:new Uint32Array(4),}}function parseInput(query,parserState){let foundStopChar=true;while(parserState.pos"){if(isReturnArrow(parserState)){break}throw["Unexpected ",c," (did you mean ","->","?)"]}else if(parserState.pos>0){throw["Unexpected ",c," after ",parserState.userQuery[parserState.pos-1]]}throw["Unexpected ",c]}else if(c===" "){skipWhitespace(parserState);continue}if(!foundStopChar){let extra="";if(isLastElemGeneric(query.elems,parserState)){extra=[" after ",">"]}else if(prevIs(parserState,"\"")){throw["Cannot have more than one element if you use quotes"]}if(parserState.typeFilter!==null){throw["Expected ",","," or ","->",...extra,", found ",c,]}throw["Expected ",",",", ",":"," or ","->",...extra,", found ",c,]}const before=query.elems.length;getFilteredNextElem(query,parserState,query.elems,false);if(query.elems.length===before){parserState.pos+=1}foundStopChar=false}if(parserState.typeFilter!==null){throw["Unexpected ",":"," (expected path after type filter ",parserState.typeFilter+":",")",]}while(parserState.pos"]}break}else{parserState.pos+=1}}}userQuery=userQuery.trim().replace(/\r|\n|\t/g," ");const parserState={length:userQuery.length,pos:0,totalElems:0,genericsElems:0,typeFilter:null,isInBinding:null,userQuery:userQuery.toLowerCase(),};let query=newParsedQuery(userQuery);try{parseInput(query,parserState);for(const elem of query.elems){convertTypeFilterOnElem(elem)}for(const elem of query.returned){convertTypeFilterOnElem(elem)}}catch(err){query=newParsedQuery(userQuery);query.error=err;return query}if(!query.literalSearch){query.literalSearch=parserState.totalElems>1}query.foundElems=query.elems.length+query.returned.length;query.totalElems=parserState.totalElems;return query}async execQuery(parsedQuery,filterCrates,currentCrate){const results_others=new Map(),results_in_args=new Map(),results_returned=new Map();function createQueryResults(results_in_args,results_returned,results_others,parsedQuery){return{"in_args":results_in_args,"returned":results_returned,"others":results_others,"query":parsedQuery,}}const buildHrefAndPath=item=>{let displayPath;let href;const type=itemTypes[item.ty];const name=item.name;let path=item.path;let exactPath=item.exactPath;if(type==="mod"){displayPath=path+"::";href=this.rootPath+path.replace(/::/g,"/")+"/"+name+"/index.html"}else if(type==="import"){displayPath=item.path+"::";href=this.rootPath+item.path.replace(/::/g,"/")+"/index.html#reexport."+name}else if(type==="primitive"||type==="keyword"){displayPath="";href=this.rootPath+path.replace(/::/g,"/")+"/"+type+"."+name+".html"}else if(type==="externcrate"){displayPath="";href=this.rootPath+name+"/index.html"}else if(item.parent!==undefined){const myparent=item.parent;let anchor=type+"."+name;const parentType=itemTypes[myparent.ty];let pageType=parentType;let pageName=myparent.name;exactPath=`${myparent.exactPath}::${myparent.name}`;if(parentType==="primitive"){displayPath=myparent.name+"::"}else if(type==="structfield"&&parentType==="variant"){const enumNameIdx=item.path.lastIndexOf("::");const enumName=item.path.substr(enumNameIdx+2);path=item.path.substr(0,enumNameIdx);displayPath=path+"::"+enumName+"::"+myparent.name+"::";anchor="variant."+myparent.name+".field."+name;pageType="enum";pageName=enumName}else{displayPath=path+"::"+myparent.name+"::"}if(item.implDisambiguator!==null){anchor=item.implDisambiguator+"/"+anchor}href=this.rootPath+path.replace(/::/g,"/")+"/"+pageType+"."+pageName+".html#"+anchor}else{displayPath=item.path+"::";href=this.rootPath+item.path.replace(/::/g,"/")+"/"+type+"."+name+".html"}return[displayPath,href,`${exactPath}::${name}`]};function pathSplitter(path){const tmp=""+path.replace(/::/g,"::");if(tmp.endsWith("")){return tmp.slice(0,tmp.length-6)}return tmp}const transformResults=results=>{const duplicates=new Set();const out=[];for(const result of results){if(result.id!==-1){const obj=this.searchIndex[result.id];obj.dist=result.dist;const res=buildHrefAndPath(obj);obj.displayPath=pathSplitter(res[0]);obj.fullPath=res[2]+"|"+obj.ty;if(duplicates.has(obj.fullPath)){continue}if(obj.ty===TY_IMPORT&&duplicates.has(res[2])){continue}if(duplicates.has(res[2]+"|"+TY_IMPORT)){continue}duplicates.add(obj.fullPath);duplicates.add(res[2]);obj.href=res[1];out.push(obj);if(out.length>=MAX_RESULTS){break}}}return out};const sortResults=async(results,isType,preferredCrate)=>{const userQuery=parsedQuery.userQuery;const casedUserQuery=parsedQuery.original;const result_list=[];for(const result of results.values()){result.item=this.searchIndex[result.id];result.word=this.searchIndex[result.id].word;result_list.push(result)}result_list.sort((aaa,bbb)=>{let a,b;a=(aaa.item.name!==casedUserQuery);b=(bbb.item.name!==casedUserQuery);if(a!==b){return a-b}a=(aaa.word!==userQuery);b=(bbb.word!==userQuery);if(a!==b){return a-b}a=(aaa.index<0);b=(bbb.index<0);if(a!==b){return a-b}a=aaa.path_dist;b=bbb.path_dist;if(a!==b){return a-b}a=aaa.index;b=bbb.index;if(a!==b){return a-b}a=(aaa.dist);b=(bbb.dist);if(a!==b){return a-b}a=this.searchIndexDeprecated.get(aaa.item.crate).contains(aaa.item.bitIndex);b=this.searchIndexDeprecated.get(bbb.item.crate).contains(bbb.item.bitIndex);if(a!==b){return a-b}a=(aaa.item.crate!==preferredCrate);b=(bbb.item.crate!==preferredCrate);if(a!==b){return a-b}a=aaa.word.length;b=bbb.word.length;if(a!==b){return a-b}a=aaa.word;b=bbb.word;if(a!==b){return(a>b?+1:-1)}a=this.searchIndexEmptyDesc.get(aaa.item.crate).contains(aaa.item.bitIndex);b=this.searchIndexEmptyDesc.get(bbb.item.crate).contains(bbb.item.bitIndex);if(a!==b){return a-b}a=aaa.item.ty;b=bbb.item.ty;if(a!==b){return a-b}a=aaa.item.path;b=bbb.item.path;if(a!==b){return(a>b?+1:-1)}return 0});return transformResults(result_list)};function unifyFunctionTypes(fnTypesIn,queryElems,whereClause,mgensIn,solutionCb,unboxingDepth,){if(unboxingDepth>=UNBOXING_LIMIT){return false}const mgens=mgensIn===null?null:new Map(mgensIn);if(queryElems.length===0){return!solutionCb||solutionCb(mgens)}if(!fnTypesIn||fnTypesIn.length===0){return false}const ql=queryElems.length;const fl=fnTypesIn.length;if(ql===1&&queryElems[0].generics.length===0&&queryElems[0].bindings.size===0){const queryElem=queryElems[0];for(const fnType of fnTypesIn){if(!unifyFunctionTypeIsMatchCandidate(fnType,queryElem,mgens)){continue}if(fnType.id<0&&queryElem.id<0){if(mgens&&mgens.has(fnType.id)&&mgens.get(fnType.id)!==queryElem.id){continue}const mgensScratch=new Map(mgens);mgensScratch.set(fnType.id,queryElem.id);if(!solutionCb||solutionCb(mgensScratch)){return true}}else if(!solutionCb||solutionCb(mgens?new Map(mgens):null)){return true}}for(const fnType of fnTypesIn){if(!unifyFunctionTypeIsUnboxCandidate(fnType,queryElem,whereClause,mgens,unboxingDepth+1,)){continue}if(fnType.id<0){if(mgens&&mgens.has(fnType.id)&&mgens.get(fnType.id)!==0){continue}const mgensScratch=new Map(mgens);mgensScratch.set(fnType.id,0);if(unifyFunctionTypes(whereClause[(-fnType.id)-1],queryElems,whereClause,mgensScratch,solutionCb,unboxingDepth+1,)){return true}}else if(unifyFunctionTypes([...fnType.generics,...Array.from(fnType.bindings.values()).flat()],queryElems,whereClause,mgens?new Map(mgens):null,solutionCb,unboxingDepth+1,)){return true}}return false}const fnTypes=fnTypesIn.slice();const flast=fl-1;const qlast=ql-1;const queryElem=queryElems[qlast];let queryElemsTmp=null;for(let i=flast;i>=0;i-=1){const fnType=fnTypes[i];if(!unifyFunctionTypeIsMatchCandidate(fnType,queryElem,mgens)){continue}let mgensScratch;if(fnType.id<0){mgensScratch=new Map(mgens);if(mgensScratch.has(fnType.id)&&mgensScratch.get(fnType.id)!==queryElem.id){continue}mgensScratch.set(fnType.id,queryElem.id)}else{mgensScratch=mgens}fnTypes[i]=fnTypes[flast];fnTypes.length=flast;if(!queryElemsTmp){queryElemsTmp=queryElems.slice(0,qlast)}const passesUnification=unifyFunctionTypes(fnTypes,queryElemsTmp,whereClause,mgensScratch,mgensScratch=>{if(fnType.generics.length===0&&queryElem.generics.length===0&&fnType.bindings.size===0&&queryElem.bindings.size===0){return!solutionCb||solutionCb(mgensScratch)}const solution=unifyFunctionTypeCheckBindings(fnType,queryElem,whereClause,mgensScratch,unboxingDepth,);if(!solution){return false}const simplifiedGenerics=solution.simplifiedGenerics;for(const simplifiedMgens of solution.mgens){const passesUnification=unifyFunctionTypes(simplifiedGenerics,queryElem.generics,whereClause,simplifiedMgens,solutionCb,unboxingDepth,);if(passesUnification){return true}}return false},unboxingDepth,);if(passesUnification){return true}fnTypes[flast]=fnTypes[i];fnTypes[i]=fnType;fnTypes.length=fl}for(let i=flast;i>=0;i-=1){const fnType=fnTypes[i];if(!unifyFunctionTypeIsUnboxCandidate(fnType,queryElem,whereClause,mgens,unboxingDepth+1,)){continue}let mgensScratch;if(fnType.id<0){mgensScratch=new Map(mgens);if(mgensScratch.has(fnType.id)&&mgensScratch.get(fnType.id)!==0){continue}mgensScratch.set(fnType.id,0)}else{mgensScratch=mgens}const generics=fnType.id<0?whereClause[(-fnType.id)-1]:fnType.generics;const bindings=fnType.bindings?Array.from(fnType.bindings.values()).flat():[];const passesUnification=unifyFunctionTypes(fnTypes.toSpliced(i,1,...generics,...bindings),queryElems,whereClause,mgensScratch,solutionCb,unboxingDepth+1,);if(passesUnification){return true}}return false}const unifyFunctionTypeIsMatchCandidate=(fnType,queryElem,mgensIn)=>{if(!typePassesFilter(queryElem.typeFilter,fnType.ty)){return false}if(fnType.id<0&&queryElem.id<0){if(mgensIn){if(mgensIn.has(fnType.id)&&mgensIn.get(fnType.id)!==queryElem.id){return false}for(const[fid,qid]of mgensIn.entries()){if(fnType.id!==fid&&queryElem.id===qid){return false}if(fnType.id===fid&&queryElem.id!==qid){return false}}}return true}else{if(queryElem.id===this.typeNameIdOfArrayOrSlice&&(fnType.id===this.typeNameIdOfSlice||fnType.id===this.typeNameIdOfArray)){}else if(queryElem.id===this.typeNameIdOfTupleOrUnit&&(fnType.id===this.typeNameIdOfTuple||fnType.id===this.typeNameIdOfUnit)){}else if(queryElem.id===this.typeNameIdOfHof&&(fnType.id===this.typeNameIdOfFn||fnType.id===this.typeNameIdOfFnMut||fnType.id===this.typeNameIdOfFnOnce)){}else if(fnType.id!==queryElem.id||queryElem.id===null){return false}if((fnType.generics.length+fnType.bindings.size)===0&&queryElem.generics.length!==0){return false}if(fnType.bindings.size0){const fnTypePath=fnType.path!==undefined&&fnType.path!==null?fnType.path.split("::"):[];if(queryElemPathLength>fnTypePath.length){return false}let i=0;for(const path of fnTypePath){if(path===queryElem.pathWithoutLast[i]){i+=1;if(i>=queryElemPathLength){break}}}if(i0){let mgensSolutionSet=[mgensIn];for(const[name,constraints]of queryElem.bindings.entries()){if(mgensSolutionSet.length===0){return false}if(!fnType.bindings.has(name)){return false}const fnTypeBindings=fnType.bindings.get(name);mgensSolutionSet=mgensSolutionSet.flatMap(mgens=>{const newSolutions=[];unifyFunctionTypes(fnTypeBindings,constraints,whereClause,mgens,newMgens=>{newSolutions.push(newMgens);return false},unboxingDepth,);return newSolutions})}if(mgensSolutionSet.length===0){return false}const binds=Array.from(fnType.bindings.entries()).flatMap(entry=>{const[name,constraints]=entry;if(queryElem.bindings.has(name)){return[]}else{return constraints}});if(simplifiedGenerics.length>0){simplifiedGenerics=[...simplifiedGenerics,...binds]}else{simplifiedGenerics=binds}return{simplifiedGenerics,mgens:mgensSolutionSet}}return{simplifiedGenerics,mgens:[mgensIn]}}function unifyFunctionTypeIsUnboxCandidate(fnType,queryElem,whereClause,mgens,unboxingDepth,){if(unboxingDepth>=UNBOXING_LIMIT){return false}if(fnType.id<0&&queryElem.id>=0){if(!whereClause){return false}if(mgens&&mgens.has(fnType.id)&&mgens.get(fnType.id)!==0){return false}const mgensTmp=new Map(mgens);mgensTmp.set(fnType.id,null);return checkIfInList(whereClause[(-fnType.id)-1],queryElem,whereClause,mgensTmp,unboxingDepth,)}else if(fnType.generics.length>0||fnType.bindings.size>0){const simplifiedGenerics=[...fnType.generics,...Array.from(fnType.bindings.values()).flat(),];return checkIfInList(simplifiedGenerics,queryElem,whereClause,mgens,unboxingDepth,)}return false}function checkIfInList(list,elem,whereClause,mgens,unboxingDepth){for(const entry of list){if(checkType(entry,elem,whereClause,mgens,unboxingDepth)){return true}}return false}const checkType=(row,elem,whereClause,mgens,unboxingDepth)=>{if(unboxingDepth>=UNBOXING_LIMIT){return false}if(row.bindings.size===0&&elem.bindings.size===0){if(elem.id<0&&mgens===null){return row.id<0||checkIfInList(row.generics,elem,whereClause,mgens,unboxingDepth+1,)}if(row.id>0&&elem.id>0&&elem.pathWithoutLast.length===0&&typePassesFilter(elem.typeFilter,row.ty)&&elem.generics.length===0&&elem.id!==this.typeNameIdOfArrayOrSlice&&elem.id!==this.typeNameIdOfTupleOrUnit&&elem.id!==this.typeNameIdOfHof){return row.id===elem.id||checkIfInList(row.generics,elem,whereClause,mgens,unboxingDepth,)}}return unifyFunctionTypes([row],[elem],whereClause,mgens,null,unboxingDepth)};function checkPath(contains,ty){if(contains.length===0){return 0}const maxPathEditDistance=Math.floor(contains.reduce((acc,next)=>acc+next.length,0)/3,);let ret_dist=maxPathEditDistance+1;const path=ty.path.split("::");if(ty.parent&&ty.parent.name){path.push(ty.parent.name.toLowerCase())}const length=path.length;const clength=contains.length;pathiter:for(let i=length-clength;i>=0;i-=1){let dist_total=0;for(let x=0;xmaxPathEditDistance){continue pathiter}dist_total+=dist}}ret_dist=Math.min(ret_dist,Math.round(dist_total/clength))}return ret_dist>maxPathEditDistance?null:ret_dist}function typePassesFilter(filter,type){if(filter<=NO_TYPE_FILTER||filter===type)return true;const name=itemTypes[type];switch(itemTypes[filter]){case"constant":return name==="associatedconstant";case"fn":return name==="method"||name==="tymethod";case"type":return name==="primitive"||name==="associatedtype";case"trait":return name==="traitalias"}return false}function createAliasFromItem(item){return{crate:item.crate,name:item.name,path:item.path,descShard:item.descShard,descIndex:item.descIndex,exactPath:item.exactPath,ty:item.ty,parent:item.parent,type:item.type,is_alias:true,bitIndex:item.bitIndex,implDisambiguator:item.implDisambiguator,}}const handleAliases=async(ret,query,filterCrates,currentCrate)=>{const lowerQuery=query.toLowerCase();const aliases=[];const crateAliases=[];if(filterCrates!==null){if(this.ALIASES.has(filterCrates)&&this.ALIASES.get(filterCrates).has(lowerQuery)){const query_aliases=this.ALIASES.get(filterCrates).get(lowerQuery);for(const alias of query_aliases){aliases.push(createAliasFromItem(this.searchIndex[alias]))}}}else{for(const[crate,crateAliasesIndex]of this.ALIASES){if(crateAliasesIndex.has(lowerQuery)){const pushTo=crate===currentCrate?crateAliases:aliases;const query_aliases=crateAliasesIndex.get(lowerQuery);for(const alias of query_aliases){pushTo.push(createAliasFromItem(this.searchIndex[alias]))}}}}const sortFunc=(aaa,bbb)=>{if(aaa.path{return this.searchIndexEmptyDesc.get(alias.crate).contains(alias.bitIndex)?"":this.searchState.loadDesc(alias)};const[crateDescs,descs]=await Promise.all([Promise.all(crateAliases.map(fetchDesc)),Promise.all(aliases.map(fetchDesc)),]);const pushFunc=alias=>{alias.alias=query;const res=buildHrefAndPath(alias);alias.displayPath=pathSplitter(res[0]);alias.fullPath=alias.displayPath+alias.name;alias.href=res[1];ret.others.unshift(alias);if(ret.others.length>MAX_RESULTS){ret.others.pop()}};aliases.forEach((alias,i)=>{alias.desc=descs[i]});aliases.forEach(pushFunc);crateAliases.forEach((alias,i)=>{alias.desc=crateDescs[i]});crateAliases.forEach(pushFunc)};function addIntoResults(results,fullId,id,index,dist,path_dist,maxEditDistance){if(dist<=maxEditDistance||index!==-1){if(results.has(fullId)){const result=results.get(fullId);if(result.dontValidate||result.dist<=dist){return}}results.set(fullId,{id:id,index:index,dontValidate:parsedQuery.literalSearch,dist:dist,path_dist:path_dist,})}}function handleSingleArg(row,pos,elem,results_others,results_in_args,results_returned,maxEditDistance,){if(!row||(filterCrates!==null&&row.crate!==filterCrates)){return}let path_dist=0;const fullId=row.id;const tfpDist=compareTypeFingerprints(fullId,parsedQuery.typeFingerprint,);if(tfpDist!==null){const in_args=row.type&&row.type.inputs&&checkIfInList(row.type.inputs,elem,row.type.where_clause,null,0);const returned=row.type&&row.type.output&&checkIfInList(row.type.output,elem,row.type.where_clause,null,0);if(in_args){results_in_args.max_dist=Math.max(results_in_args.max_dist||0,tfpDist);const maxDist=results_in_args.sizenormalizedIndex&&normalizedIndex!==-1)){index=normalizedIndex}if(elem.fullPath.length>1){path_dist=checkPath(elem.pathWithoutLast,row);if(path_dist===null){return}}if(parsedQuery.literalSearch){if(row.word===elem.pathLast){addIntoResults(results_others,fullId,pos,index,0,path_dist)}return}const dist=editDistance(row.normalizedName,elem.normalizedPathLast,maxEditDistance);if(index===-1&&dist>maxEditDistance){return}addIntoResults(results_others,fullId,pos,index,dist,path_dist,maxEditDistance)}function handleArgs(row,pos,results){if(!row||(filterCrates!==null&&row.crate!==filterCrates)||!row.type){return}const tfpDist=compareTypeFingerprints(row.id,parsedQuery.typeFingerprint,);if(tfpDist===null){return}if(results.size>=MAX_RESULTS&&tfpDist>results.max_dist){return}if(!unifyFunctionTypes(row.type.inputs,parsedQuery.elems,row.type.where_clause,null,mgens=>{return unifyFunctionTypes(row.type.output,parsedQuery.returned,row.type.where_clause,mgens,null,0,)},0,)){return}results.max_dist=Math.max(results.max_dist||0,tfpDist);addIntoResults(results,row.id,pos,0,tfpDist,0,Number.MAX_VALUE)}const compareTypeFingerprints=(fullId,queryFingerprint)=>{const fh0=this.functionTypeFingerprint[fullId*4];const fh1=this.functionTypeFingerprint[(fullId*4)+1];const fh2=this.functionTypeFingerprint[(fullId*4)+2];const[qh0,qh1,qh2]=queryFingerprint;const[in0,in1,in2]=[fh0&qh0,fh1&qh1,fh2&qh2];if((in0 ^ qh0)||(in1 ^ qh1)||(in2 ^ qh2)){return null}return this.functionTypeFingerprint[(fullId*4)+3]};const innerRunQuery=()=>{const queryLen=parsedQuery.elems.reduce((acc,next)=>acc+next.pathLast.length,0)+parsedQuery.returned.reduce((acc,next)=>acc+next.pathLast.length,0);const maxEditDistance=Math.floor(queryLen/3);const genericSymbols=new Map();const convertNameToId=(elem,isAssocType)=>{const loweredName=elem.pathLast.toLowerCase();if(this.typeNameIdMap.has(loweredName)&&(isAssocType||!this.typeNameIdMap.get(loweredName).assocOnly)){elem.id=this.typeNameIdMap.get(loweredName).id}else if(!parsedQuery.literalSearch){let match=null;let matchDist=maxEditDistance+1;let matchName="";for(const[name,{id,assocOnly}]of this.typeNameIdMap){const dist=Math.min(editDistance(name,loweredName,maxEditDistance),editDistance(name,elem.normalizedPathLast,maxEditDistance),);if(dist<=matchDist&&dist<=maxEditDistance&&(isAssocType||!assocOnly)){if(dist===matchDist&&matchName>name){continue}match=id;matchDist=dist;matchName=name}}if(match!==null){parsedQuery.correction=matchName}elem.id=match}if((elem.id===null&&parsedQuery.totalElems>1&&elem.typeFilter===-1&&elem.generics.length===0&&elem.bindings.size===0)||elem.typeFilter===TY_GENERIC){if(genericSymbols.has(elem.name)){elem.id=genericSymbols.get(elem.name)}else{elem.id=-(genericSymbols.size+1);genericSymbols.set(elem.name,elem.id)}if(elem.typeFilter===-1&&elem.name.length>=3){const maxPartDistance=Math.floor(elem.name.length/3);let matchDist=maxPartDistance+1;let matchName="";for(const name of this.typeNameIdMap.keys()){const dist=editDistance(name,elem.name,maxPartDistance);if(dist<=matchDist&&dist<=maxPartDistance){if(dist===matchDist&&matchName>name){continue}matchDist=dist;matchName=name}}if(matchName!==""){parsedQuery.proposeCorrectionFrom=elem.name;parsedQuery.proposeCorrectionTo=matchName}}elem.typeFilter=TY_GENERIC}if(elem.generics.length>0&&elem.typeFilter===TY_GENERIC){parsedQuery.error=["Generic type parameter ",elem.name," does not accept generic parameters",]}for(const elem2 of elem.generics){convertNameToId(elem2)}elem.bindings=new Map(Array.from(elem.bindings.entries()).map(entry=>{const[name,constraints]=entry;if(!this.typeNameIdMap.has(name)){parsedQuery.error=["Type parameter ",name," does not exist",];return[null,[]]}for(const elem2 of constraints){convertNameToId(elem2)}return[this.typeNameIdMap.get(name).id,constraints]}),)};const fps=new Set();for(const elem of parsedQuery.elems){convertNameToId(elem);this.buildFunctionTypeFingerprint(elem,parsedQuery.typeFingerprint,fps)}for(const elem of parsedQuery.returned){convertNameToId(elem);this.buildFunctionTypeFingerprint(elem,parsedQuery.typeFingerprint,fps)}if(parsedQuery.foundElems===1&&parsedQuery.returned.length===0){if(parsedQuery.elems.length===1){const elem=parsedQuery.elems[0];const length=this.searchIndex.length;for(let i=0,nSearchIndex=length;i0){const sortQ=(a,b)=>{const ag=a.generics.length===0&&a.bindings.size===0;const bg=b.generics.length===0&&b.bindings.size===0;if(ag!==bg){return ag-bg}const ai=a.id>0;const bi=b.id>0;return ai-bi};parsedQuery.elems.sort(sortQ);parsedQuery.returned.sort(sortQ);for(let i=0,nSearchIndex=this.searchIndex.length;i{const descs=await Promise.all(list.map(result=>{return this.searchIndexEmptyDesc.get(result.crate).contains(result.bitIndex)?"":this.searchState.loadDesc(result)}));for(const[i,result]of list.entries()){result.desc=descs[i]}}));if(parsedQuery.error!==null&&ret.others.length!==0){ret.query.error=null}return ret}}let rawSearchIndex;let docSearch;const longItemTypes=["keyword","primitive type","module","extern crate","re-export","struct","enum","function","type alias","static","trait","","trait method","method","struct field","enum variant","macro","assoc type","constant","assoc const","union","foreign type","existential type","attribute macro","derive macro","trait alias",];let currentResults;function printTab(nb){let iter=0;let foundCurrentTab=false;let foundCurrentResultSet=false;onEachLazy(document.getElementById("search-tabs").childNodes,elem=>{if(nb===iter){addClass(elem,"selected");foundCurrentTab=true}else{removeClass(elem,"selected")}iter+=1});const isTypeSearch=(nb>0||iter===1);iter=0;onEachLazy(document.getElementById("results").childNodes,elem=>{if(nb===iter){addClass(elem,"active");foundCurrentResultSet=true}else{removeClass(elem,"active")}iter+=1});if(foundCurrentTab&&foundCurrentResultSet){searchState.currentTab=nb;const correctionsElem=document.getElementsByClassName("search-corrections");if(isTypeSearch){removeClass(correctionsElem[0],"hidden")}else{addClass(correctionsElem[0],"hidden")}}else if(nb!==0){printTab(0)}}function buildUrl(search,filterCrates){let extra="?search="+encodeURIComponent(search);if(filterCrates!==null){extra+="&filter-crate="+encodeURIComponent(filterCrates)}return getNakedUrl()+extra+window.location.hash}function getFilterCrates(){const elem=document.getElementById("crate-search");if(elem&&elem.value!=="all crates"&&window.searchIndex.has(elem.value)){return elem.value}return null}function nextTab(direction){const next=(searchState.currentTab+direction+3)%searchState.focusedByTab.length;searchState.focusedByTab[searchState.currentTab]=document.activeElement;printTab(next);focusSearchResult()}function focusSearchResult(){const target=searchState.focusedByTab[searchState.currentTab]||document.querySelectorAll(".search-results.active a").item(0)||document.querySelectorAll("#search-tabs button").item(searchState.currentTab);searchState.focusedByTab[searchState.currentTab]=null;if(target){target.focus()}}async function addTab(array,query,display){const extraClass=display?" active":"";const output=document.createElement("div");if(array.length>0){output.className="search-results "+extraClass;for(const item of array){const name=item.name;const type=itemTypes[item.ty];const longType=longItemTypes[item.ty];const typeName=longType.length!==0?`${longType}`:"?";const link=document.createElement("a");link.className="result-"+type;link.href=item.href;const resultName=document.createElement("div");resultName.className="result-name";resultName.insertAdjacentHTML("beforeend",`${typeName}`);link.appendChild(resultName);let alias=" ";if(item.is_alias){alias=`
    \ +${item.alias} - see \ +
    `}resultName.insertAdjacentHTML("beforeend",`
    ${alias}\ +${item.displayPath}${name}\ +
    `);const description=document.createElement("div");description.className="desc";description.insertAdjacentHTML("beforeend",item.desc);link.appendChild(description);output.appendChild(link)}}else if(query.error===null){output.className="search-failed"+extraClass;output.innerHTML="No results :(
    "+"Try on DuckDuckGo?

    "+"Or try looking in one of these:"}return[output,array.length]}function makeTabHeader(tabNb,text,nbElems){const fmtNbElems=nbElems<10?`\u{2007}(${nbElems})\u{2007}\u{2007}`:nbElems<100?`\u{2007}(${nbElems})\u{2007}`:`\u{2007}(${nbElems})`;if(searchState.currentTab===tabNb){return""}return""}async function showResults(results,go_to_first,filterCrates){const search=searchState.outputElement();if(go_to_first||(results.others.length===1&&getSettingValue("go-to-only-result")==="true")){window.onunload=()=>{};searchState.removeQueryParameters();const elem=document.createElement("a");elem.href=results.others[0].href;removeClass(elem,"active");document.body.appendChild(elem);elem.click();return}if(results.query===undefined){results.query=DocSearch.parseQuery(searchState.input.value)}currentResults=results.query.userQuery;const[ret_others,ret_in_args,ret_returned]=await Promise.all([addTab(results.others,results.query,true),addTab(results.in_args,results.query,false),addTab(results.returned,results.query,false),]);let currentTab=searchState.currentTab;if((currentTab===0&&ret_others[1]===0)||(currentTab===1&&ret_in_args[1]===0)||(currentTab===2&&ret_returned[1]===0)){if(ret_others[1]!==0){currentTab=0}else if(ret_in_args[1]!==0){currentTab=1}else if(ret_returned[1]!==0){currentTab=2}}let crates="";if(rawSearchIndex.size>1){crates=" in 
    "}let output=`

    Results${crates}

    `;if(results.query.error!==null){const error=results.query.error;error.forEach((value,index)=>{value=value.split("<").join("<").split(">").join(">");if(index%2!==0){error[index]=`${value.replaceAll(" ", " ")}`}else{error[index]=value}});output+=`

    Query parser error: "${error.join("")}".

    `;output+="
    "+makeTabHeader(0,"In Names",ret_others[1])+"
    ";currentTab=0}else if(results.query.foundElems<=1&&results.query.returned.length===0){output+="
    "+makeTabHeader(0,"In Names",ret_others[1])+makeTabHeader(1,"In Parameters",ret_in_args[1])+makeTabHeader(2,"In Return Types",ret_returned[1])+"
    "}else{const signatureTabTitle=results.query.elems.length===0?"In Function Return Types":results.query.returned.length===0?"In Function Parameters":"In Function Signatures";output+="
    "+makeTabHeader(0,signatureTabTitle,ret_others[1])+"
    ";currentTab=0}if(results.query.correction!==null){const orig=results.query.returned.length>0?results.query.returned[0].name:results.query.elems[0].name;output+="

    "+`Type "${orig}" not found. `+"Showing results for closest type name "+`"${results.query.correction}" instead.

    `}if(results.query.proposeCorrectionFrom!==null){const orig=results.query.proposeCorrectionFrom;const targ=results.query.proposeCorrectionTo;output+="

    "+`Type "${orig}" not found and used as generic parameter. `+`Consider searching for "${targ}" instead.

    `}const resultsElem=document.createElement("div");resultsElem.id="results";resultsElem.appendChild(ret_others[0]);resultsElem.appendChild(ret_in_args[0]);resultsElem.appendChild(ret_returned[0]);search.innerHTML=output;const crateSearch=document.getElementById("crate-search");if(crateSearch){crateSearch.addEventListener("input",updateCrate)}search.appendChild(resultsElem);searchState.showResults(search);const elems=document.getElementById("search-tabs").childNodes;searchState.focusedByTab=[];let i=0;for(const elem of elems){const j=i;elem.onclick=()=>printTab(j);searchState.focusedByTab.push(null);i+=1}printTab(currentTab)}function updateSearchHistory(url){if(!browserSupportsHistoryApi()){return}const params=searchState.getQueryStringParams();if(!history.state&&!params.search){history.pushState(null,"",url)}else{history.replaceState(null,"",url)}}async function search(forced){const query=DocSearch.parseQuery(searchState.input.value.trim());let filterCrates=getFilterCrates();if(!forced&&query.userQuery===currentResults){if(query.userQuery.length>0){putBackSearch()}return}searchState.setLoadingSearch();const params=searchState.getQueryStringParams();if(filterCrates===null&¶ms["filter-crate"]!==undefined){filterCrates=params["filter-crate"]}searchState.title="\""+query.original+"\" Search - Rust";updateSearchHistory(buildUrl(query.original,filterCrates));await showResults(await docSearch.execQuery(query,filterCrates,window.currentCrate),params.go_to_first,filterCrates)}function onSearchSubmit(e){e.preventDefault();searchState.clearInputTimeout();search()}function putBackSearch(){const search_input=searchState.input;if(!searchState.input){return}if(search_input.value!==""&&!searchState.isDisplayed()){searchState.showResults();if(browserSupportsHistoryApi()){history.replaceState(null,"",buildUrl(search_input.value,getFilterCrates()))}document.title=searchState.title}}function registerSearchEvents(){const params=searchState.getQueryStringParams();if(searchState.input.value===""){searchState.input.value=params.search||""}const searchAfter500ms=()=>{searchState.clearInputTimeout();if(searchState.input.value.length===0){searchState.hideResults()}else{searchState.timeout=setTimeout(search,500)}};searchState.input.onkeyup=searchAfter500ms;searchState.input.oninput=searchAfter500ms;document.getElementsByClassName("search-form")[0].onsubmit=onSearchSubmit;searchState.input.onchange=e=>{if(e.target!==document.activeElement){return}searchState.clearInputTimeout();setTimeout(search,0)};searchState.input.onpaste=searchState.input.onchange;searchState.outputElement().addEventListener("keydown",e=>{if(e.altKey||e.ctrlKey||e.shiftKey||e.metaKey){return}if(e.which===38){const previous=document.activeElement.previousElementSibling;if(previous){previous.focus()}else{searchState.focus()}e.preventDefault()}else if(e.which===40){const next=document.activeElement.nextElementSibling;if(next){next.focus()}const rect=document.activeElement.getBoundingClientRect();if(window.innerHeight-rect.bottom{if(e.which===40){focusSearchResult();e.preventDefault()}});searchState.input.addEventListener("focus",()=>{putBackSearch()});searchState.input.addEventListener("blur",()=>{searchState.input.placeholder=searchState.input.origPlaceholder});if(browserSupportsHistoryApi()){const previousTitle=document.title;window.addEventListener("popstate",e=>{const params=searchState.getQueryStringParams();document.title=previousTitle;currentResults=null;if(params.search&¶ms.search.length>0){searchState.input.value=params.search;e.preventDefault();search()}else{searchState.input.value="";searchState.hideResults()}})}window.onpageshow=()=>{const qSearch=searchState.getQueryStringParams().search;if(searchState.input.value===""&&qSearch){searchState.input.value=qSearch}search()}}function updateCrate(ev){if(ev.target.value==="all crates"){const query=searchState.input.value.trim();updateSearchHistory(buildUrl(query,null))}currentResults=null;search(true)}function initSearch(searchIndx){rawSearchIndex=searchIndx;if(typeof window!=="undefined"){docSearch=new DocSearch(rawSearchIndex,ROOT_PATH,searchState);registerSearchEvents();if(window.searchState.getQueryStringParams().search){search()}}else if(typeof exports!=="undefined"){docSearch=new DocSearch(rawSearchIndex,ROOT_PATH,searchState);exports.docSearch=docSearch;exports.parseQuery=DocSearch.parseQuery}}if(typeof exports!=="undefined"){exports.initSearch=initSearch}if(typeof window!=="undefined"){window.initSearch=initSearch;if(window.searchIndex!==undefined){initSearch(window.searchIndex)}}else{initSearch(new Map())}})() \ No newline at end of file diff --git a/apps/rust_docs/static.files/storage-118b08c4c78b968e.js b/apps/rust_docs/static.files/storage-118b08c4c78b968e.js new file mode 100644 index 00000000..98189467 --- /dev/null +++ b/apps/rust_docs/static.files/storage-118b08c4c78b968e.js @@ -0,0 +1,24 @@ +"use strict";const builtinThemes=["light","dark","ayu"];const darkThemes=["dark","ayu"];window.currentTheme=document.getElementById("themeStyle");const settingsDataset=(function(){const settingsElement=document.getElementById("default-settings");return settingsElement&&settingsElement.dataset?settingsElement.dataset:null})();function getSettingValue(settingName){const current=getCurrentValue(settingName);if(current===null&&settingsDataset!==null){const def=settingsDataset[settingName.replace(/-/g,"_")];if(def!==undefined){return def}}return current}const localStoredTheme=getSettingValue("theme");function hasClass(elem,className){return elem&&elem.classList&&elem.classList.contains(className)}function addClass(elem,className){if(elem&&elem.classList){elem.classList.add(className)}}function removeClass(elem,className){if(elem&&elem.classList){elem.classList.remove(className)}}function onEach(arr,func){for(const elem of arr){if(func(elem)){return true}}return false}function onEachLazy(lazyArray,func){return onEach(Array.prototype.slice.call(lazyArray),func)}function updateLocalStorage(name,value){try{window.localStorage.setItem("rustdoc-"+name,value)}catch(e){}}function getCurrentValue(name){try{return window.localStorage.getItem("rustdoc-"+name)}catch(e){return null}}const getVar=(function getVar(name){const el=document.querySelector("head > meta[name='rustdoc-vars']");return el?el.attributes["data-"+name].value:null});function switchTheme(newThemeName,saveTheme){const themeNames=getVar("themes").split(",").filter(t=>t);themeNames.push(...builtinThemes);if(themeNames.indexOf(newThemeName)===-1){return}if(saveTheme){updateLocalStorage("theme",newThemeName)}document.documentElement.setAttribute("data-theme",newThemeName);if(builtinThemes.indexOf(newThemeName)!==-1){if(window.currentTheme){window.currentTheme.parentNode.removeChild(window.currentTheme);window.currentTheme=null}}else{const newHref=getVar("root-path")+encodeURIComponent(newThemeName)+getVar("resource-suffix")+".css";if(!window.currentTheme){if(document.readyState==="loading"){document.write(``);window.currentTheme=document.getElementById("themeStyle")}else{window.currentTheme=document.createElement("link");window.currentTheme.rel="stylesheet";window.currentTheme.id="themeStyle";window.currentTheme.href=newHref;document.documentElement.appendChild(window.currentTheme)}}else if(newHref!==window.currentTheme.href){window.currentTheme.href=newHref}}}const updateTheme=(function(){const mql=window.matchMedia("(prefers-color-scheme: dark)");function updateTheme(){if(getSettingValue("use-system-theme")!=="false"){const lightTheme=getSettingValue("preferred-light-theme")||"light";const darkTheme=getSettingValue("preferred-dark-theme")||"dark";updateLocalStorage("use-system-theme","true");switchTheme(mql.matches?darkTheme:lightTheme,true)}else{switchTheme(getSettingValue("theme"),false)}}mql.addEventListener("change",updateTheme);return updateTheme})();if(getSettingValue("use-system-theme")!=="false"&&window.matchMedia){if(getSettingValue("use-system-theme")===null&&getSettingValue("preferred-dark-theme")===null&&darkThemes.indexOf(localStoredTheme)>=0){updateLocalStorage("preferred-dark-theme",localStoredTheme)}}updateTheme();if(getSettingValue("source-sidebar-show")==="true"){addClass(document.documentElement,"src-sidebar-expanded")}if(getSettingValue("hide-sidebar")==="true"){addClass(document.documentElement,"hide-sidebar")}function updateSidebarWidth(){const desktopSidebarWidth=getSettingValue("desktop-sidebar-width");if(desktopSidebarWidth&&desktopSidebarWidth!=="null"){document.documentElement.style.setProperty("--desktop-sidebar-width",desktopSidebarWidth+"px",)}const srcSidebarWidth=getSettingValue("src-sidebar-width");if(srcSidebarWidth&&srcSidebarWidth!=="null"){document.documentElement.style.setProperty("--src-sidebar-width",srcSidebarWidth+"px",)}}updateSidebarWidth();window.addEventListener("pageshow",ev=>{if(ev.persisted){setTimeout(updateTheme,0);setTimeout(updateSidebarWidth,0)}});class RustdocSearchElement extends HTMLElement{constructor(){super()}connectedCallback(){const rootPath=getVar("root-path");const currentCrate=getVar("current-crate");this.innerHTML=``}}window.customElements.define("rustdoc-search",RustdocSearchElement) \ No newline at end of file diff --git a/apps/rust_docs/trait.impl/core/clone/trait.Clone.js b/apps/rust_docs/trait.impl/core/clone/trait.Clone.js index 69b3c95d..f4a24d65 100644 --- a/apps/rust_docs/trait.impl/core/clone/trait.Clone.js +++ b/apps/rust_docs/trait.impl/core/clone/trait.Clone.js @@ -1,4 +1,9 @@ -(function() {var implementors = { -"defindex_strategy_core":[["impl Clone for StrategyError"],["impl Clone for DepositEvent"],["impl Clone for HarvestEvent"],["impl Clone for InitializedEvent"],["impl Clone for WithdrawEvent"]], -"defindex_vault":[["impl Clone for ContractError"]] -};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file +(function() { + var implementors = Object.fromEntries([["defindex_strategy_core",[["impl Clone for StrategyError"],["impl Clone for DepositEvent"],["impl Clone for HarvestEvent"],["impl Clone for InitializedEvent"],["impl Clone for WithdrawEvent"]]],["defindex_vault",[["impl Clone for ContractError"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[1567,297]} \ No newline at end of file diff --git a/apps/rust_docs/trait.impl/core/cmp/trait.Eq.js b/apps/rust_docs/trait.impl/core/cmp/trait.Eq.js index f2413375..cbf1fb33 100644 --- a/apps/rust_docs/trait.impl/core/cmp/trait.Eq.js +++ b/apps/rust_docs/trait.impl/core/cmp/trait.Eq.js @@ -1,4 +1,9 @@ -(function() {var implementors = { -"defindex_strategy_core":[["impl Eq for StrategyError"],["impl Eq for DepositEvent"],["impl Eq for HarvestEvent"],["impl Eq for InitializedEvent"],["impl Eq for WithdrawEvent"]], -"defindex_vault":[["impl Eq for ContractError"]] -};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file +(function() { + var implementors = Object.fromEntries([["defindex_strategy_core",[["impl Eq for StrategyError"],["impl Eq for DepositEvent"],["impl Eq for HarvestEvent"],["impl Eq for InitializedEvent"],["impl Eq for WithdrawEvent"]]],["defindex_vault",[["impl Eq for ContractError"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[1502,284]} \ No newline at end of file diff --git a/apps/rust_docs/trait.impl/core/cmp/trait.Ord.js b/apps/rust_docs/trait.impl/core/cmp/trait.Ord.js index 8f9ded00..8963179f 100644 --- a/apps/rust_docs/trait.impl/core/cmp/trait.Ord.js +++ b/apps/rust_docs/trait.impl/core/cmp/trait.Ord.js @@ -1,4 +1,9 @@ -(function() {var implementors = { -"defindex_strategy_core":[["impl Ord for StrategyError"]], -"defindex_vault":[["impl Ord for ContractError"]] -};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file +(function() { + var implementors = Object.fromEntries([["defindex_strategy_core",[["impl Ord for StrategyError"]]],["defindex_vault",[["impl Ord for ContractError"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[310,287]} \ No newline at end of file diff --git a/apps/rust_docs/trait.impl/core/cmp/trait.PartialEq.js b/apps/rust_docs/trait.impl/core/cmp/trait.PartialEq.js index 5140c62e..7b35b5c6 100644 --- a/apps/rust_docs/trait.impl/core/cmp/trait.PartialEq.js +++ b/apps/rust_docs/trait.impl/core/cmp/trait.PartialEq.js @@ -1,4 +1,9 @@ -(function() {var implementors = { -"defindex_strategy_core":[["impl PartialEq for StrategyError"],["impl PartialEq for DepositEvent"],["impl PartialEq for HarvestEvent"],["impl PartialEq for InitializedEvent"],["impl PartialEq for WithdrawEvent"]], -"defindex_vault":[["impl PartialEq for ContractError"]] -};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file +(function() { + var implementors = Object.fromEntries([["defindex_strategy_core",[["impl PartialEq for StrategyError"],["impl PartialEq for DepositEvent"],["impl PartialEq for HarvestEvent"],["impl PartialEq for InitializedEvent"],["impl PartialEq for WithdrawEvent"]]],["defindex_vault",[["impl PartialEq for ContractError"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[1607,305]} \ No newline at end of file diff --git a/apps/rust_docs/trait.impl/core/cmp/trait.PartialOrd.js b/apps/rust_docs/trait.impl/core/cmp/trait.PartialOrd.js index ccc997b1..f9623d6a 100644 --- a/apps/rust_docs/trait.impl/core/cmp/trait.PartialOrd.js +++ b/apps/rust_docs/trait.impl/core/cmp/trait.PartialOrd.js @@ -1,4 +1,9 @@ -(function() {var implementors = { -"defindex_strategy_core":[["impl PartialOrd for StrategyError"]], -"defindex_vault":[["impl PartialOrd for ContractError"]] -};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file +(function() { + var implementors = Object.fromEntries([["defindex_strategy_core",[["impl PartialOrd for StrategyError"]]],["defindex_vault",[["impl PartialOrd for ContractError"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[331,308]} \ No newline at end of file diff --git a/apps/rust_docs/trait.impl/core/convert/trait.From.js b/apps/rust_docs/trait.impl/core/convert/trait.From.js index 4585f954..330fb1e6 100644 --- a/apps/rust_docs/trait.impl/core/convert/trait.From.js +++ b/apps/rust_docs/trait.impl/core/convert/trait.From.js @@ -1,4 +1,9 @@ -(function() {var implementors = { -"defindex_strategy_core":[["impl From<&StrategyError> for Error"],["impl From<&StrategyError> for InvokeError"],["impl From<StrategyError> for Error"],["impl From<StrategyError> for InvokeError"]], -"defindex_vault":[["impl From<&ContractError> for Error"],["impl From<&ContractError> for InvokeError"],["impl From<ContractError> for Error"],["impl From<ContractError> for InvokeError"]] -};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file +(function() { + var implementors = Object.fromEntries([["defindex_strategy_core",[["impl From<&StrategyError> for Error"],["impl From<&StrategyError> for InvokeError"],["impl From<StrategyError> for Error"],["impl From<StrategyError> for InvokeError"]]],["defindex_vault",[["impl From<&ContractError> for Error"],["impl From<&ContractError> for InvokeError"],["impl From<ContractError> for Error"],["impl From<ContractError> for InvokeError"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[1274,1203]} \ No newline at end of file diff --git a/apps/rust_docs/trait.impl/core/convert/trait.TryFrom.js b/apps/rust_docs/trait.impl/core/convert/trait.TryFrom.js index 862e37a0..19980391 100644 --- a/apps/rust_docs/trait.impl/core/convert/trait.TryFrom.js +++ b/apps/rust_docs/trait.impl/core/convert/trait.TryFrom.js @@ -1,4 +1,9 @@ -(function() {var implementors = { -"defindex_strategy_core":[["impl TryFrom<&Error> for StrategyError"],["impl TryFrom<&InvokeError> for StrategyError"],["impl TryFrom<Error> for StrategyError"],["impl TryFrom<InvokeError> for StrategyError"]], -"defindex_vault":[["impl TryFrom<&Error> for ContractError"],["impl TryFrom<&InvokeError> for ContractError"],["impl TryFrom<Error> for ContractError"],["impl TryFrom<InvokeError> for ContractError"]] -};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file +(function() { + var implementors = Object.fromEntries([["defindex_strategy_core",[["impl TryFrom<&Error> for StrategyError"],["impl TryFrom<&InvokeError> for StrategyError"],["impl TryFrom<Error> for StrategyError"],["impl TryFrom<InvokeError> for StrategyError"]]],["defindex_vault",[["impl TryFrom<&Error> for ContractError"],["impl TryFrom<&InvokeError> for ContractError"],["impl TryFrom<Error> for ContractError"],["impl TryFrom<InvokeError> for ContractError"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[1310,1239]} \ No newline at end of file diff --git a/apps/rust_docs/trait.impl/core/fmt/trait.Debug.js b/apps/rust_docs/trait.impl/core/fmt/trait.Debug.js index 5cfd1cbf..56878a26 100644 --- a/apps/rust_docs/trait.impl/core/fmt/trait.Debug.js +++ b/apps/rust_docs/trait.impl/core/fmt/trait.Debug.js @@ -1,4 +1,9 @@ -(function() {var implementors = { -"defindex_strategy_core":[["impl Debug for StrategyError"],["impl Debug for DepositEvent"],["impl Debug for HarvestEvent"],["impl Debug for InitializedEvent"],["impl Debug for WithdrawEvent"]], -"defindex_vault":[["impl Debug for ContractError"]] -};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file +(function() { + var implementors = Object.fromEntries([["defindex_strategy_core",[["impl Debug for StrategyError"],["impl Debug for DepositEvent"],["impl Debug for HarvestEvent"],["impl Debug for InitializedEvent"],["impl Debug for WithdrawEvent"]]],["defindex_vault",[["impl Debug for ContractError"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[1547,293]} \ No newline at end of file diff --git a/apps/rust_docs/trait.impl/core/marker/trait.Copy.js b/apps/rust_docs/trait.impl/core/marker/trait.Copy.js index 034fe13a..68b67abe 100644 --- a/apps/rust_docs/trait.impl/core/marker/trait.Copy.js +++ b/apps/rust_docs/trait.impl/core/marker/trait.Copy.js @@ -1,4 +1,9 @@ -(function() {var implementors = { -"defindex_strategy_core":[["impl Copy for StrategyError"]], -"defindex_vault":[["impl Copy for ContractError"]] -};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file +(function() { + var implementors = Object.fromEntries([["defindex_strategy_core",[["impl Copy for StrategyError"]]],["defindex_vault",[["impl Copy for ContractError"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[319,296]} \ No newline at end of file diff --git a/apps/rust_docs/trait.impl/core/marker/trait.Freeze.js b/apps/rust_docs/trait.impl/core/marker/trait.Freeze.js index e5a65e55..7a73071a 100644 --- a/apps/rust_docs/trait.impl/core/marker/trait.Freeze.js +++ b/apps/rust_docs/trait.impl/core/marker/trait.Freeze.js @@ -1,5 +1,9 @@ -(function() {var implementors = { -"defindex_factory":[["impl<'a> Freeze for DeFindexFactoryClient<'a>",1,["defindex_factory::DeFindexFactoryClient"]]], -"defindex_strategy_core":[["impl Freeze for StrategyError",1,["defindex_strategy_core::error::StrategyError"]],["impl Freeze for DepositEvent",1,["defindex_strategy_core::event::DepositEvent"]],["impl Freeze for HarvestEvent",1,["defindex_strategy_core::event::HarvestEvent"]],["impl Freeze for InitializedEvent",1,["defindex_strategy_core::event::InitializedEvent"]],["impl Freeze for WithdrawEvent",1,["defindex_strategy_core::event::WithdrawEvent"]],["impl Freeze for Spec",1,["defindex_strategy_core::Spec"]],["impl<'a> Freeze for DeFindexStrategyClient<'a>",1,["defindex_strategy_core::DeFindexStrategyClient"]]], -"defindex_vault":[["impl Freeze for ContractError",1,["defindex_vault::error::ContractError"]],["impl Freeze for DeFindexVault",1,["defindex_vault::DeFindexVault"]],["impl<'a> Freeze for DeFindexVaultClient<'a>",1,["defindex_vault::DeFindexVaultClient"]]] -};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file +(function() { + var implementors = Object.fromEntries([["defindex_factory",[["impl<'a> Freeze for DeFindexFactoryClient<'a>",1,["defindex_factory::DeFindexFactoryClient"]]]],["defindex_strategy_core",[["impl Freeze for StrategyError",1,["defindex_strategy_core::error::StrategyError"]],["impl Freeze for DepositEvent",1,["defindex_strategy_core::event::DepositEvent"]],["impl Freeze for HarvestEvent",1,["defindex_strategy_core::event::HarvestEvent"]],["impl Freeze for InitializedEvent",1,["defindex_strategy_core::event::InitializedEvent"]],["impl Freeze for WithdrawEvent",1,["defindex_strategy_core::event::WithdrawEvent"]],["impl Freeze for Spec",1,["defindex_strategy_core::Spec"]],["impl<'a> Freeze for DeFindexStrategyClient<'a>",1,["defindex_strategy_core::DeFindexStrategyClient"]]]],["defindex_vault",[["impl Freeze for ContractError",1,["defindex_vault::error::ContractError"]],["impl Freeze for DeFindexVault",1,["defindex_vault::DeFindexVault"]],["impl<'a> Freeze for DeFindexVaultClient<'a>",1,["defindex_vault::DeFindexVaultClient"]]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[403,2563,1035]} \ No newline at end of file diff --git a/apps/rust_docs/trait.impl/core/marker/trait.Send.js b/apps/rust_docs/trait.impl/core/marker/trait.Send.js index df4716db..d29284e0 100644 --- a/apps/rust_docs/trait.impl/core/marker/trait.Send.js +++ b/apps/rust_docs/trait.impl/core/marker/trait.Send.js @@ -1,5 +1,9 @@ -(function() {var implementors = { -"defindex_factory":[["impl<'a> !Send for DeFindexFactoryClient<'a>",1,["defindex_factory::DeFindexFactoryClient"]]], -"defindex_strategy_core":[["impl !Send for DepositEvent",1,["defindex_strategy_core::event::DepositEvent"]],["impl !Send for HarvestEvent",1,["defindex_strategy_core::event::HarvestEvent"]],["impl !Send for InitializedEvent",1,["defindex_strategy_core::event::InitializedEvent"]],["impl !Send for WithdrawEvent",1,["defindex_strategy_core::event::WithdrawEvent"]],["impl Send for StrategyError",1,["defindex_strategy_core::error::StrategyError"]],["impl Send for Spec",1,["defindex_strategy_core::Spec"]],["impl<'a> !Send for DeFindexStrategyClient<'a>",1,["defindex_strategy_core::DeFindexStrategyClient"]]], -"defindex_vault":[["impl Send for ContractError",1,["defindex_vault::error::ContractError"]],["impl Send for DeFindexVault",1,["defindex_vault::DeFindexVault"]],["impl<'a> !Send for DeFindexVaultClient<'a>",1,["defindex_vault::DeFindexVaultClient"]]] -};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file +(function() { + var implementors = Object.fromEntries([["defindex_factory",[["impl<'a> !Send for DeFindexFactoryClient<'a>",1,["defindex_factory::DeFindexFactoryClient"]]]],["defindex_strategy_core",[["impl !Send for DepositEvent",1,["defindex_strategy_core::event::DepositEvent"]],["impl !Send for HarvestEvent",1,["defindex_strategy_core::event::HarvestEvent"]],["impl !Send for InitializedEvent",1,["defindex_strategy_core::event::InitializedEvent"]],["impl !Send for WithdrawEvent",1,["defindex_strategy_core::event::WithdrawEvent"]],["impl Send for StrategyError",1,["defindex_strategy_core::error::StrategyError"]],["impl Send for Spec",1,["defindex_strategy_core::Spec"]],["impl<'a> !Send for DeFindexStrategyClient<'a>",1,["defindex_strategy_core::DeFindexStrategyClient"]]]],["defindex_vault",[["impl Send for ContractError",1,["defindex_vault::error::ContractError"]],["impl Send for DeFindexVault",1,["defindex_vault::DeFindexVault"]],["impl<'a> !Send for DeFindexVaultClient<'a>",1,["defindex_vault::DeFindexVaultClient"]]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[398,2526,1018]} \ No newline at end of file diff --git a/apps/rust_docs/trait.impl/core/marker/trait.StructuralPartialEq.js b/apps/rust_docs/trait.impl/core/marker/trait.StructuralPartialEq.js index 2ce3ef3d..6014f63a 100644 --- a/apps/rust_docs/trait.impl/core/marker/trait.StructuralPartialEq.js +++ b/apps/rust_docs/trait.impl/core/marker/trait.StructuralPartialEq.js @@ -1,4 +1,9 @@ -(function() {var implementors = { -"defindex_strategy_core":[["impl StructuralPartialEq for StrategyError"],["impl StructuralPartialEq for DepositEvent"],["impl StructuralPartialEq for HarvestEvent"],["impl StructuralPartialEq for InitializedEvent"],["impl StructuralPartialEq for WithdrawEvent"]], -"defindex_vault":[["impl StructuralPartialEq for ContractError"]] -};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file +(function() { + var implementors = Object.fromEntries([["defindex_strategy_core",[["impl StructuralPartialEq for StrategyError"],["impl StructuralPartialEq for DepositEvent"],["impl StructuralPartialEq for HarvestEvent"],["impl StructuralPartialEq for InitializedEvent"],["impl StructuralPartialEq for WithdrawEvent"]]],["defindex_vault",[["impl StructuralPartialEq for ContractError"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[1787,341]} \ No newline at end of file diff --git a/apps/rust_docs/trait.impl/core/marker/trait.Sync.js b/apps/rust_docs/trait.impl/core/marker/trait.Sync.js index bbc75352..912f2609 100644 --- a/apps/rust_docs/trait.impl/core/marker/trait.Sync.js +++ b/apps/rust_docs/trait.impl/core/marker/trait.Sync.js @@ -1,5 +1,9 @@ -(function() {var implementors = { -"defindex_factory":[["impl<'a> !Sync for DeFindexFactoryClient<'a>",1,["defindex_factory::DeFindexFactoryClient"]]], -"defindex_strategy_core":[["impl !Sync for DepositEvent",1,["defindex_strategy_core::event::DepositEvent"]],["impl !Sync for HarvestEvent",1,["defindex_strategy_core::event::HarvestEvent"]],["impl !Sync for InitializedEvent",1,["defindex_strategy_core::event::InitializedEvent"]],["impl !Sync for WithdrawEvent",1,["defindex_strategy_core::event::WithdrawEvent"]],["impl Sync for StrategyError",1,["defindex_strategy_core::error::StrategyError"]],["impl Sync for Spec",1,["defindex_strategy_core::Spec"]],["impl<'a> !Sync for DeFindexStrategyClient<'a>",1,["defindex_strategy_core::DeFindexStrategyClient"]]], -"defindex_vault":[["impl Sync for ContractError",1,["defindex_vault::error::ContractError"]],["impl Sync for DeFindexVault",1,["defindex_vault::DeFindexVault"]],["impl<'a> !Sync for DeFindexVaultClient<'a>",1,["defindex_vault::DeFindexVaultClient"]]] -};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file +(function() { + var implementors = Object.fromEntries([["defindex_factory",[["impl<'a> !Sync for DeFindexFactoryClient<'a>",1,["defindex_factory::DeFindexFactoryClient"]]]],["defindex_strategy_core",[["impl !Sync for DepositEvent",1,["defindex_strategy_core::event::DepositEvent"]],["impl !Sync for HarvestEvent",1,["defindex_strategy_core::event::HarvestEvent"]],["impl !Sync for InitializedEvent",1,["defindex_strategy_core::event::InitializedEvent"]],["impl !Sync for WithdrawEvent",1,["defindex_strategy_core::event::WithdrawEvent"]],["impl Sync for StrategyError",1,["defindex_strategy_core::error::StrategyError"]],["impl Sync for Spec",1,["defindex_strategy_core::Spec"]],["impl<'a> !Sync for DeFindexStrategyClient<'a>",1,["defindex_strategy_core::DeFindexStrategyClient"]]]],["defindex_vault",[["impl Sync for ContractError",1,["defindex_vault::error::ContractError"]],["impl Sync for DeFindexVault",1,["defindex_vault::DeFindexVault"]],["impl<'a> !Sync for DeFindexVaultClient<'a>",1,["defindex_vault::DeFindexVaultClient"]]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[398,2526,1018]} \ No newline at end of file diff --git a/apps/rust_docs/trait.impl/core/marker/trait.Unpin.js b/apps/rust_docs/trait.impl/core/marker/trait.Unpin.js index 8320930e..521e9def 100644 --- a/apps/rust_docs/trait.impl/core/marker/trait.Unpin.js +++ b/apps/rust_docs/trait.impl/core/marker/trait.Unpin.js @@ -1,5 +1,9 @@ -(function() {var implementors = { -"defindex_factory":[["impl<'a> Unpin for DeFindexFactoryClient<'a>",1,["defindex_factory::DeFindexFactoryClient"]]], -"defindex_strategy_core":[["impl Unpin for StrategyError",1,["defindex_strategy_core::error::StrategyError"]],["impl Unpin for DepositEvent",1,["defindex_strategy_core::event::DepositEvent"]],["impl Unpin for HarvestEvent",1,["defindex_strategy_core::event::HarvestEvent"]],["impl Unpin for InitializedEvent",1,["defindex_strategy_core::event::InitializedEvent"]],["impl Unpin for WithdrawEvent",1,["defindex_strategy_core::event::WithdrawEvent"]],["impl Unpin for Spec",1,["defindex_strategy_core::Spec"]],["impl<'a> Unpin for DeFindexStrategyClient<'a>",1,["defindex_strategy_core::DeFindexStrategyClient"]]], -"defindex_vault":[["impl Unpin for ContractError",1,["defindex_vault::error::ContractError"]],["impl Unpin for DeFindexVault",1,["defindex_vault::DeFindexVault"]],["impl<'a> Unpin for DeFindexVaultClient<'a>",1,["defindex_vault::DeFindexVaultClient"]]] -};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file +(function() { + var implementors = Object.fromEntries([["defindex_factory",[["impl<'a> Unpin for DeFindexFactoryClient<'a>",1,["defindex_factory::DeFindexFactoryClient"]]]],["defindex_strategy_core",[["impl Unpin for StrategyError",1,["defindex_strategy_core::error::StrategyError"]],["impl Unpin for DepositEvent",1,["defindex_strategy_core::event::DepositEvent"]],["impl Unpin for HarvestEvent",1,["defindex_strategy_core::event::HarvestEvent"]],["impl Unpin for InitializedEvent",1,["defindex_strategy_core::event::InitializedEvent"]],["impl Unpin for WithdrawEvent",1,["defindex_strategy_core::event::WithdrawEvent"]],["impl Unpin for Spec",1,["defindex_strategy_core::Spec"]],["impl<'a> Unpin for DeFindexStrategyClient<'a>",1,["defindex_strategy_core::DeFindexStrategyClient"]]]],["defindex_vault",[["impl Unpin for ContractError",1,["defindex_vault::error::ContractError"]],["impl Unpin for DeFindexVault",1,["defindex_vault::DeFindexVault"]],["impl<'a> Unpin for DeFindexVaultClient<'a>",1,["defindex_vault::DeFindexVaultClient"]]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[400,2542,1026]} \ No newline at end of file diff --git a/apps/rust_docs/trait.impl/core/panic/unwind_safe/trait.RefUnwindSafe.js b/apps/rust_docs/trait.impl/core/panic/unwind_safe/trait.RefUnwindSafe.js index e52e14af..6b65a05f 100644 --- a/apps/rust_docs/trait.impl/core/panic/unwind_safe/trait.RefUnwindSafe.js +++ b/apps/rust_docs/trait.impl/core/panic/unwind_safe/trait.RefUnwindSafe.js @@ -1,5 +1,9 @@ -(function() {var implementors = { -"defindex_factory":[["impl<'a> !RefUnwindSafe for DeFindexFactoryClient<'a>",1,["defindex_factory::DeFindexFactoryClient"]]], -"defindex_strategy_core":[["impl !RefUnwindSafe for DepositEvent",1,["defindex_strategy_core::event::DepositEvent"]],["impl !RefUnwindSafe for HarvestEvent",1,["defindex_strategy_core::event::HarvestEvent"]],["impl !RefUnwindSafe for InitializedEvent",1,["defindex_strategy_core::event::InitializedEvent"]],["impl !RefUnwindSafe for WithdrawEvent",1,["defindex_strategy_core::event::WithdrawEvent"]],["impl RefUnwindSafe for StrategyError",1,["defindex_strategy_core::error::StrategyError"]],["impl RefUnwindSafe for Spec",1,["defindex_strategy_core::Spec"]],["impl<'a> !RefUnwindSafe for DeFindexStrategyClient<'a>",1,["defindex_strategy_core::DeFindexStrategyClient"]]], -"defindex_vault":[["impl RefUnwindSafe for ContractError",1,["defindex_vault::error::ContractError"]],["impl RefUnwindSafe for DeFindexVault",1,["defindex_vault::DeFindexVault"]],["impl<'a> !RefUnwindSafe for DeFindexVaultClient<'a>",1,["defindex_vault::DeFindexVaultClient"]]] -};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file +(function() { + var implementors = Object.fromEntries([["defindex_factory",[["impl<'a> !RefUnwindSafe for DeFindexFactoryClient<'a>",1,["defindex_factory::DeFindexFactoryClient"]]]],["defindex_strategy_core",[["impl !RefUnwindSafe for DepositEvent",1,["defindex_strategy_core::event::DepositEvent"]],["impl !RefUnwindSafe for HarvestEvent",1,["defindex_strategy_core::event::HarvestEvent"]],["impl !RefUnwindSafe for InitializedEvent",1,["defindex_strategy_core::event::InitializedEvent"]],["impl !RefUnwindSafe for WithdrawEvent",1,["defindex_strategy_core::event::WithdrawEvent"]],["impl RefUnwindSafe for StrategyError",1,["defindex_strategy_core::error::StrategyError"]],["impl RefUnwindSafe for Spec",1,["defindex_strategy_core::Spec"]],["impl<'a> !RefUnwindSafe for DeFindexStrategyClient<'a>",1,["defindex_strategy_core::DeFindexStrategyClient"]]]],["defindex_vault",[["impl RefUnwindSafe for ContractError",1,["defindex_vault::error::ContractError"]],["impl RefUnwindSafe for DeFindexVault",1,["defindex_vault::DeFindexVault"]],["impl<'a> !RefUnwindSafe for DeFindexVaultClient<'a>",1,["defindex_vault::DeFindexVaultClient"]]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[448,2876,1168]} \ No newline at end of file diff --git a/apps/rust_docs/trait.impl/core/panic/unwind_safe/trait.UnwindSafe.js b/apps/rust_docs/trait.impl/core/panic/unwind_safe/trait.UnwindSafe.js index 5f2c6f02..a584c5b5 100644 --- a/apps/rust_docs/trait.impl/core/panic/unwind_safe/trait.UnwindSafe.js +++ b/apps/rust_docs/trait.impl/core/panic/unwind_safe/trait.UnwindSafe.js @@ -1,5 +1,9 @@ -(function() {var implementors = { -"defindex_factory":[["impl<'a> !UnwindSafe for DeFindexFactoryClient<'a>",1,["defindex_factory::DeFindexFactoryClient"]]], -"defindex_strategy_core":[["impl !UnwindSafe for DepositEvent",1,["defindex_strategy_core::event::DepositEvent"]],["impl !UnwindSafe for HarvestEvent",1,["defindex_strategy_core::event::HarvestEvent"]],["impl !UnwindSafe for InitializedEvent",1,["defindex_strategy_core::event::InitializedEvent"]],["impl !UnwindSafe for WithdrawEvent",1,["defindex_strategy_core::event::WithdrawEvent"]],["impl UnwindSafe for StrategyError",1,["defindex_strategy_core::error::StrategyError"]],["impl UnwindSafe for Spec",1,["defindex_strategy_core::Spec"]],["impl<'a> !UnwindSafe for DeFindexStrategyClient<'a>",1,["defindex_strategy_core::DeFindexStrategyClient"]]], -"defindex_vault":[["impl UnwindSafe for ContractError",1,["defindex_vault::error::ContractError"]],["impl UnwindSafe for DeFindexVault",1,["defindex_vault::DeFindexVault"]],["impl<'a> !UnwindSafe for DeFindexVaultClient<'a>",1,["defindex_vault::DeFindexVaultClient"]]] -};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file +(function() { + var implementors = Object.fromEntries([["defindex_factory",[["impl<'a> !UnwindSafe for DeFindexFactoryClient<'a>",1,["defindex_factory::DeFindexFactoryClient"]]]],["defindex_strategy_core",[["impl !UnwindSafe for DepositEvent",1,["defindex_strategy_core::event::DepositEvent"]],["impl !UnwindSafe for HarvestEvent",1,["defindex_strategy_core::event::HarvestEvent"]],["impl !UnwindSafe for InitializedEvent",1,["defindex_strategy_core::event::InitializedEvent"]],["impl !UnwindSafe for WithdrawEvent",1,["defindex_strategy_core::event::WithdrawEvent"]],["impl UnwindSafe for StrategyError",1,["defindex_strategy_core::error::StrategyError"]],["impl UnwindSafe for Spec",1,["defindex_strategy_core::Spec"]],["impl<'a> !UnwindSafe for DeFindexStrategyClient<'a>",1,["defindex_strategy_core::DeFindexStrategyClient"]]]],["defindex_vault",[["impl UnwindSafe for ContractError",1,["defindex_vault::error::ContractError"]],["impl UnwindSafe for DeFindexVault",1,["defindex_vault::DeFindexVault"]],["impl<'a> !UnwindSafe for DeFindexVaultClient<'a>",1,["defindex_vault::DeFindexVaultClient"]]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[439,2813,1141]} \ No newline at end of file diff --git a/apps/rust_docs/trait.impl/soroban_env_common/convert/trait.TryFromVal.js b/apps/rust_docs/trait.impl/soroban_env_common/convert/trait.TryFromVal.js index fa382e71..5c6cc1aa 100644 --- a/apps/rust_docs/trait.impl/soroban_env_common/convert/trait.TryFromVal.js +++ b/apps/rust_docs/trait.impl/soroban_env_common/convert/trait.TryFromVal.js @@ -1,4 +1,9 @@ -(function() {var implementors = { -"defindex_strategy_core":[["impl TryFromVal<Env, StrategyError> for Val"],["impl TryFromVal<Env, DepositEvent> for Val"],["impl TryFromVal<Env, HarvestEvent> for Val"],["impl TryFromVal<Env, InitializedEvent> for Val"],["impl TryFromVal<Env, WithdrawEvent> for Val"],["impl TryFromVal<Env, Val> for StrategyError"],["impl TryFromVal<Env, Val> for DepositEvent"],["impl TryFromVal<Env, Val> for HarvestEvent"],["impl TryFromVal<Env, Val> for InitializedEvent"],["impl TryFromVal<Env, Val> for WithdrawEvent"]], -"defindex_vault":[["impl TryFromVal<Env, ContractError> for Val"],["impl TryFromVal<Env, Val> for ContractError"]] -};if (window.register_implementors) {window.register_implementors(implementors);} else {window.pending_implementors = implementors;}})() \ No newline at end of file +(function() { + var implementors = Object.fromEntries([["defindex_strategy_core",[["impl TryFromVal<Env, StrategyError> for Val"],["impl TryFromVal<Env, DepositEvent> for Val"],["impl TryFromVal<Env, HarvestEvent> for Val"],["impl TryFromVal<Env, InitializedEvent> for Val"],["impl TryFromVal<Env, WithdrawEvent> for Val"],["impl TryFromVal<Env, Val> for StrategyError"],["impl TryFromVal<Env, Val> for DepositEvent"],["impl TryFromVal<Env, Val> for HarvestEvent"],["impl TryFromVal<Env, Val> for InitializedEvent"],["impl TryFromVal<Env, Val> for WithdrawEvent"]]],["defindex_vault",[["impl TryFromVal<Env, ContractError> for Val"],["impl TryFromVal<Env, Val> for ContractError"]]]]); + if (window.register_implementors) { + window.register_implementors(implementors); + } else { + window.pending_implementors = implementors; + } +})() +//{"start":57,"fragment_lengths":[2036,359]} \ No newline at end of file From d2d50ce764bdabd20b0da60b740d29e801140912 Mon Sep 17 00:00:00 2001 From: esteblock Date: Wed, 4 Dec 2024 16:08:27 -0300 Subject: [PATCH 23/28] add tests to corrct test folder --- apps/contracts/vault/src/test/{ => vault}/fees.rs | 0 .../src/test/{ => vault}/get_asset_amounts_per_shares.rs | 0 apps/contracts/vault/src/test/vault/mod.rs | 4 +++- 3 files changed, 3 insertions(+), 1 deletion(-) rename apps/contracts/vault/src/test/{ => vault}/fees.rs (100%) rename apps/contracts/vault/src/test/{ => vault}/get_asset_amounts_per_shares.rs (100%) diff --git a/apps/contracts/vault/src/test/fees.rs b/apps/contracts/vault/src/test/vault/fees.rs similarity index 100% rename from apps/contracts/vault/src/test/fees.rs rename to apps/contracts/vault/src/test/vault/fees.rs diff --git a/apps/contracts/vault/src/test/get_asset_amounts_per_shares.rs b/apps/contracts/vault/src/test/vault/get_asset_amounts_per_shares.rs similarity index 100% rename from apps/contracts/vault/src/test/get_asset_amounts_per_shares.rs rename to apps/contracts/vault/src/test/vault/get_asset_amounts_per_shares.rs diff --git a/apps/contracts/vault/src/test/vault/mod.rs b/apps/contracts/vault/src/test/vault/mod.rs index 0e1a89b6..c38d0d8e 100644 --- a/apps/contracts/vault/src/test/vault/mod.rs +++ b/apps/contracts/vault/src/test/vault/mod.rs @@ -5,4 +5,6 @@ mod emergency_withdraw; mod initialize; mod invest; mod rebalance; -mod withdraw; \ No newline at end of file +mod withdraw; +mod fees; +mod get_asset_amounts_per_shares; \ No newline at end of file From ef05ff1c501032c555fa0d14779e21bef04e828b Mon Sep 17 00:00:00 2001 From: esteblock Date: Wed, 4 Dec 2024 16:13:55 -0300 Subject: [PATCH 24/28] fix correct error --- apps/contracts/vault/src/test/vault/withdraw.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/apps/contracts/vault/src/test/vault/withdraw.rs b/apps/contracts/vault/src/test/vault/withdraw.rs index 1d810388..5d7f36af 100644 --- a/apps/contracts/vault/src/test/vault/withdraw.rs +++ b/apps/contracts/vault/src/test/vault/withdraw.rs @@ -57,7 +57,7 @@ fn test_withdraw_negative_amount() { // check that withdraw without balance after initialized returns error InsufficientBalance #[test] -fn test_withdraw_insufficient_balance() { +fn test_withdraw_0_total_supply() { let test = DeFindexVaultTest::setup(); test.env.mock_all_auths(); let strategy_params_token0 = create_strategy_params_token0(&test); @@ -84,7 +84,7 @@ fn test_withdraw_insufficient_balance() { let users = DeFindexVaultTest::generate_random_users(&test.env, 1); let result = test.defindex_contract.try_withdraw(&100i128, &users[0]); - assert_eq!(result, Err(Ok(ContractError::InsufficientBalance))); + assert_eq!(result, Err(Ok(ContractError::AmountOverTotalSupply))); } #[test] @@ -185,7 +185,7 @@ fn withdraw_from_idle_success() { .try_withdraw(&amount_to_withdraw_more, &users[0]); assert_eq!(result, - Err(Ok(ContractError::InsufficientBalance))); + Err(Ok(ContractError::AmountOverTotalSupply))); // // withdraw remaining balance From 09021d1ba44b85dd913024b8c348a7536e7e5a41 Mon Sep 17 00:00:00 2001 From: esteblock Date: Wed, 4 Dec 2024 16:15:44 -0300 Subject: [PATCH 25/28] remove unnevesary comments --- apps/contracts/vault/src/test/vault/deposit.rs | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/apps/contracts/vault/src/test/vault/deposit.rs b/apps/contracts/vault/src/test/vault/deposit.rs index 2708a139..908d91cf 100644 --- a/apps/contracts/vault/src/test/vault/deposit.rs +++ b/apps/contracts/vault/src/test/vault/deposit.rs @@ -307,24 +307,6 @@ fn one_asset_success() { assert_eq!(vault_balance, amount); // check total manage funds - - // fn fetch_total_managed_funds(e: &Env) -> Map { - // extend_instance_ttl(&e); - // fetch_total_managed_funds(e) - // } - // pub struct CurrentAssetInvestmentAllocation { - // pub asset: Address, - // pub total_amount: i128, - // pub idle_amount: i128, - // pub invested_amount: i128, - // pub strategy_allocations: Vec, - // } - // pub struct StrategyAllocation { - // pub strategy: Address, - // pub amount: i128, - // } - - // construct expected total manage funds let mut total_managed_funds_expected = Map::new(&test.env); let strategy_investments_expected = sorobanvec![&test.env, StrategyAllocation { strategy_address: test.strategy_client_token0.address.clone(), From de5a99e1a71cf22f4b111b070ab4f51136d577cc Mon Sep 17 00:00:00 2001 From: coderipper Date: Wed, 4 Dec 2024 16:49:21 -0300 Subject: [PATCH 26/28] fixed comments --- .../strategies/blend/src/test/success.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/apps/contracts/strategies/blend/src/test/success.rs b/apps/contracts/strategies/blend/src/test/success.rs index 43f7e858..9831bd7f 100644 --- a/apps/contracts/strategies/blend/src/test/success.rs +++ b/apps/contracts/strategies/blend/src/test/success.rs @@ -104,8 +104,8 @@ fn success() { assert_eq!(vault_positions.supply.get(0).unwrap(), starting_balance * 2); // user_4 deposit directly into pool - let merry_starting_balance = 200_0000000; - usdc_client.mint(&user_4, &merry_starting_balance); + let user_4_starting_balance = 200_0000000; + usdc_client.mint(&user_4, &user_4_starting_balance); pool_client.submit( &user_4, &user_4, @@ -115,13 +115,13 @@ fn success() { Request { request_type: 0, address: usdc.address().clone(), - amount: merry_starting_balance, + amount: user_4_starting_balance, }, ], ); // admin borrow back to 50% util rate - let borrow_amount = (merry_starting_balance + starting_balance * 2) / 2; + let borrow_amount = (user_4_starting_balance + starting_balance * 2) / 2; pool_client.submit( &admin, &admin, @@ -160,16 +160,16 @@ fn success() { Request { request_type: 1, address: usdc.address().clone(), - amount: merry_starting_balance * 2, + amount: user_4_starting_balance * 2, }, ], ); - let user_5_final_balance = usdc_client.balance(&user_4); - let user_5_profit = user_5_final_balance - merry_starting_balance; + let user_4_final_balance = usdc_client.balance(&user_4); + let user_4_profit = user_4_final_balance - user_4_starting_balance; // withdraw from blend strategy for user_2 and user_3 // they are expected to receive half of the profit of user_4 - let expected_user_4_profit = user_5_profit / 2; + let expected_user_4_profit = user_4_profit / 2; let withdraw_amount = starting_balance + expected_user_4_profit; // withdraw_amount = 100_0958904 From e8d77d93afadc98082335271f4b100db83d282e5 Mon Sep 17 00:00:00 2001 From: chopan123 Date: Wed, 4 Dec 2024 16:55:44 -0300 Subject: [PATCH 27/28] name fixing --- .../vault/src/test/vault/withdraw.rs | 43 ++++++++----------- 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/apps/contracts/vault/src/test/vault/withdraw.rs b/apps/contracts/vault/src/test/vault/withdraw.rs index 5d7f36af..230e51fb 100644 --- a/apps/contracts/vault/src/test/vault/withdraw.rs +++ b/apps/contracts/vault/src/test/vault/withdraw.rs @@ -4,17 +4,13 @@ use soroban_sdk::{vec as sorobanvec, String, Vec}; use crate::test::{ create_strategy_params_token0, defindex_vault::{ - AssetStrategySet, - AssetInvestmentAllocation, - StrategyAllocation, - ContractError + AssetInvestmentAllocation, AssetStrategySet, ContractError, StrategyAllocation, }, DeFindexVaultTest, }; - #[test] -fn test_withdraw_not_yet_initialized() { +fn not_yet_initialized() { let test = DeFindexVaultTest::setup(); let users = DeFindexVaultTest::generate_random_users(&test.env, 1); @@ -24,7 +20,7 @@ fn test_withdraw_not_yet_initialized() { // check that withdraw with negative amount after initialized returns error #[test] -fn test_withdraw_negative_amount() { +fn negative_amount() { let test = DeFindexVaultTest::setup(); test.env.mock_all_auths(); let strategy_params_token0 = create_strategy_params_token0(&test); @@ -54,10 +50,9 @@ fn test_withdraw_negative_amount() { assert_eq!(result, Err(Ok(ContractError::NegativeNotAllowed))); } - // check that withdraw without balance after initialized returns error InsufficientBalance #[test] -fn test_withdraw_0_total_supply() { +fn 0_total_supply() { let test = DeFindexVaultTest::setup(); test.env.mock_all_auths(); let strategy_params_token0 = create_strategy_params_token0(&test); @@ -88,7 +83,7 @@ fn test_withdraw_0_total_supply() { } #[test] -fn withdraw_from_idle_success() { +fn withdraw_from_idle_success() { let test = DeFindexVaultTest::setup(); test.env.mock_all_auths(); let strategy_params_token0 = create_strategy_params_token0(&test); @@ -129,7 +124,7 @@ fn withdraw_from_idle_success() { &sorobanvec![&test.env, amount_to_deposit], &sorobanvec![&test.env, amount_to_deposit], &users[0], - &false + &false, ); // Check Balances after deposit @@ -150,7 +145,7 @@ fn withdraw_from_idle_success() { // Df balance of user should be equal to deposited amount let df_balance = test.defindex_contract.balance(&users[0]); - assert_eq!(df_balance, amount_to_deposit - 1000 ); // 1000 gets locked in the vault forever + assert_eq!(df_balance, amount_to_deposit - 1000); // 1000 gets locked in the vault forever // user decides to withdraw a portion of deposited amount let amount_to_withdraw = 123456i128; @@ -174,7 +169,7 @@ fn withdraw_from_idle_success() { let strategy_balance = test.token0.balance(&test.strategy_client_token0.address); assert_eq!(strategy_balance, 0); - // Df balance of user should be equal to deposited amount - amount_to_withdraw - 1000 + // Df balance of user should be equal to deposited amount - amount_to_withdraw - 1000 let df_balance = test.defindex_contract.balance(&users[0]); assert_eq!(df_balance, amount_to_deposit - amount_to_withdraw - 1000); @@ -183,16 +178,18 @@ fn withdraw_from_idle_success() { let result = test .defindex_contract .try_withdraw(&amount_to_withdraw_more, &users[0]); - - assert_eq!(result, - Err(Ok(ContractError::AmountOverTotalSupply))); + assert_eq!(result, Err(Ok(ContractError::AmountOverTotalSupply))); // // withdraw remaining balance - let result= test.defindex_contract + let result = test + .defindex_contract .withdraw(&(amount_to_deposit - amount_to_withdraw - 1000), &users[0]); - assert_eq!(result, sorobanvec![&test.env, amount_to_deposit - amount_to_withdraw - 1000]); + assert_eq!( + result, + sorobanvec![&test.env, amount_to_deposit - amount_to_withdraw - 1000] + ); let df_balance = test.defindex_contract.balance(&users[0]); assert_eq!(df_balance, 0i128); @@ -241,7 +238,7 @@ fn withdraw_from_strategy_success() { &sorobanvec![&test.env, amount], &sorobanvec![&test.env, amount], &users[0], - &false + &false, ); let df_balance = test.defindex_contract.balance(&users[0]); @@ -261,11 +258,10 @@ fn withdraw_from_strategy_success() { }), ]; - test.defindex_contract.invest(&investments); let vault_balance = test.token0.balance(&test.defindex_contract.address); - assert_eq!(vault_balance, 0); + assert_eq!(vault_balance, 0); test.defindex_contract.withdraw(&df_balance, &users[0]); @@ -275,10 +271,9 @@ fn withdraw_from_strategy_success() { let user_balance = test.token0.balance(&users[0]); assert_eq!(user_balance, amount - 1000); } - // test withdraw without mock all auths #[test] -fn test_withdraw_from_strategy_success_no_mock_all_auths() { +fn from_strategy_success_no_mock_all_auths() { todo!(); -} \ No newline at end of file +} From fa7b8d63fc6b4950d509b213e78082a2cdd8b2f0 Mon Sep 17 00:00:00 2001 From: coderipper Date: Wed, 4 Dec 2024 17:12:49 -0300 Subject: [PATCH 28/28] using test/blend structure --- apps/contracts/strategies/blend/src/test.rs | 2 +- apps/contracts/strategies/blend/src/test/blend/mod.rs | 1 + apps/contracts/strategies/blend/src/test/{ => blend}/success.rs | 0 3 files changed, 2 insertions(+), 1 deletion(-) create mode 100644 apps/contracts/strategies/blend/src/test/blend/mod.rs rename apps/contracts/strategies/blend/src/test/{ => blend}/success.rs (100%) diff --git a/apps/contracts/strategies/blend/src/test.rs b/apps/contracts/strategies/blend/src/test.rs index a05dcf4f..927c5c91 100644 --- a/apps/contracts/strategies/blend/src/test.rs +++ b/apps/contracts/strategies/blend/src/test.rs @@ -349,4 +349,4 @@ impl<'a> BlendFixture<'a> { } } -mod success; +mod blend; diff --git a/apps/contracts/strategies/blend/src/test/blend/mod.rs b/apps/contracts/strategies/blend/src/test/blend/mod.rs new file mode 100644 index 00000000..916f9128 --- /dev/null +++ b/apps/contracts/strategies/blend/src/test/blend/mod.rs @@ -0,0 +1 @@ +mod success; \ No newline at end of file diff --git a/apps/contracts/strategies/blend/src/test/success.rs b/apps/contracts/strategies/blend/src/test/blend/success.rs similarity index 100% rename from apps/contracts/strategies/blend/src/test/success.rs rename to apps/contracts/strategies/blend/src/test/blend/success.rs