Skip to content

Commit

Permalink
✨ add multiple rebalance scenarios and error handling
Browse files Browse the repository at this point in the history
  • Loading branch information
MattPoblete committed Nov 29, 2024
1 parent a071fbf commit 7bb8b29
Showing 1 changed file with 277 additions and 2 deletions.
279 changes: 277 additions & 2 deletions apps/contracts/vault/src/test/rebalance.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use soroban_sdk::{vec as sorobanvec, String, Vec};
use soroban_sdk::{vec as sorobanvec, InvokeError, String, Vec};

use crate::test::{
create_strategy_params_token0,
Expand All @@ -13,9 +13,10 @@ use crate::test::{
},
DeFindexVaultTest,
};
use crate::test::defindex_vault::ContractError;

#[test]
fn rebalance() {
fn rebalance_multi_instructions() {
let test = DeFindexVaultTest::setup();
test.env.mock_all_auths();
let strategy_params_token0 = create_strategy_params_token0(&test);
Expand Down Expand Up @@ -105,3 +106,277 @@ fn rebalance() {
let vault_balance = test.token0.balance(&test.defindex_contract.address);
assert_eq!(vault_balance, instruction_amount_1);
}

#[test]
fn rebalance_one_instruction() {
let test = DeFindexVaultTest::setup();
test.env.mock_all_auths();
let strategy_params_token0 = create_strategy_params_token0(&test);
let assets: Vec<AssetStrategySet> = 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, "TestVault"),
&String::from_str(&test.env, "TSTV"),
);
let amount = 987654321i128;

let users = DeFindexVaultTest::generate_random_users(&test.env, 1);

test.token0_admin_client.mint(&users[0], &amount);
let user_balance = test.token0.balance(&users[0]);
assert_eq!(user_balance, amount);

let df_balance = test.defindex_contract.balance(&users[0]);
assert_eq!(df_balance, 0i128);

test.defindex_contract.deposit(
&sorobanvec![&test.env, amount],
&sorobanvec![&test.env, amount],
&users[0],
);

let df_balance = test.defindex_contract.balance(&users[0]);
assert_eq!(df_balance, amount - 1000);

let investments = sorobanvec![
&test.env,
Some(AssetInvestmentAllocation {
asset: test.token0.address.clone(),
strategy_investments: sorobanvec![
&test.env,
Some(StrategyInvestment {
strategy: test.strategy_client_token0.address.clone(),
amount: amount,
}),
],
}),
];

test.defindex_contract.invest(&investments);

let vault_balance = test.token0.balance(&test.defindex_contract.address);
assert_eq!(vault_balance, 0);

// REBALANCE

let instruction_amount_0 = 200i128;

let instructions = sorobanvec![
&test.env,
Instruction {
action: ActionType::Withdraw,
strategy: Some(test.strategy_client_token0.address.clone()),
amount: Some(instruction_amount_0),
swap_details_exact_in: OptionalSwapDetailsExactIn::None,
swap_details_exact_out: OptionalSwapDetailsExactOut::None,
},
];

test.defindex_contract.rebalance(&instructions);

let vault_balance = test.token0.balance(&test.defindex_contract.address);
assert_eq!(vault_balance, instruction_amount_0);
}

#[test]
fn rebalance_empty_instructions(){
let test = DeFindexVaultTest::setup();
test.env.mock_all_auths();

let strategy_params_token0 = create_strategy_params_token0(&test);
let assets: Vec<AssetStrategySet> = 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,
&100u32,
&test.defindex_protocol_receiver,
&test.defindex_factory,
&String::from_str(&test.env, "testVault"),
&String::from_str(&test.env, "TSTV"),
);
let amount: i128 = 987654321;
let users = DeFindexVaultTest::generate_random_users(&test.env, 1);
test.token0_admin_client.mint(&users[0], &amount);
let vault_balance = test.defindex_contract.balance(&users[0]);
assert_eq!(vault_balance, 0i128);

test.defindex_contract.deposit(
&sorobanvec![&test.env, amount],
&sorobanvec![&test.env, amount],
&users[0],
);
let df_balance = test.defindex_contract.balance(&users[0]);
assert_eq!(df_balance, amount - 1000);

let instructions = sorobanvec![
&test.env,
Instruction {
action: ActionType::Withdraw,
strategy: None,
amount: None,
swap_details_exact_in: OptionalSwapDetailsExactIn::None,
swap_details_exact_out: OptionalSwapDetailsExactOut::None,
},
];
let rebalance = test.defindex_contract.try_rebalance(&instructions);
assert_eq!(rebalance, Err(Ok(ContractError::MissingInstructionData)));

let no_strategy_instructions = sorobanvec![
&test.env,
Instruction {
action: ActionType::Withdraw,
strategy: Some(test.strategy_client_token0.address.clone()),
amount: None,
swap_details_exact_in: OptionalSwapDetailsExactIn::None,
swap_details_exact_out: OptionalSwapDetailsExactOut::None,
},
];
let rebalance = test.defindex_contract.try_rebalance(&no_strategy_instructions);
assert_eq!(rebalance, Err(Ok(ContractError::MissingInstructionData)));

let no_amount_instructions = sorobanvec![
&test.env,
Instruction {
action: ActionType::Withdraw,
strategy: Some(test.strategy_client_token0.address.clone()),
amount: None,
swap_details_exact_in: OptionalSwapDetailsExactIn::None,
swap_details_exact_out: OptionalSwapDetailsExactOut::None,
},
];
let rebalance = test.defindex_contract.try_rebalance(&no_amount_instructions);
assert_eq!(rebalance, Err(Ok(ContractError::MissingInstructionData)));
}

#[test]
fn rebalance_no_instructions(){
let test = DeFindexVaultTest::setup();
test.env.mock_all_auths();

let strategy_params_token0 = create_strategy_params_token0(&test);
let assets: Vec<AssetStrategySet> = 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,
&100u32,
&test.defindex_protocol_receiver,
&test.defindex_factory,
&String::from_str(&test.env, "testVault"),
&String::from_str(&test.env, "TSTV"),
);
let amount: i128 = 987654321;
let users = DeFindexVaultTest::generate_random_users(&test.env, 1);
test.token0_admin_client.mint(&users[0], &amount);
let vault_balance = test.defindex_contract.balance(&users[0]);
assert_eq!(vault_balance, 0i128);

test.defindex_contract.deposit(
&sorobanvec![&test.env, amount],
&sorobanvec![&test.env, amount],
&users[0],
);
let df_balance = test.defindex_contract.balance(&users[0]);
assert_eq!(df_balance, amount - 1000);

let rebalance = test.defindex_contract.try_rebalance(&sorobanvec![&test.env]);
assert_eq!(rebalance, Err(Ok(ContractError::NoInstructions)));
}

#[test]
fn rebalance_insufficient_balance(){
let test = DeFindexVaultTest::setup();
test.env.mock_all_auths();

let strategy_params_token0 = create_strategy_params_token0(&test);
let assets: Vec<AssetStrategySet> = 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,
&100u32,
&test.defindex_protocol_receiver,
&test.defindex_factory,
&String::from_str(&test.env, "testVault"),
&String::from_str(&test.env, "TSTV"),
);
let amount: i128 = 987654321;
let users = DeFindexVaultTest::generate_random_users(&test.env, 1);
test.token0_admin_client.mint(&users[0], &amount);
let vault_balance = test.defindex_contract.balance(&users[0]);
assert_eq!(vault_balance, 0i128);

test.defindex_contract.deposit(
&sorobanvec![&test.env, amount],
&sorobanvec![&test.env, amount],
&users[0],
);
let df_balance = test.defindex_contract.balance(&users[0]);
assert_eq!(df_balance, amount - 1000);

let withdraw_instructions = sorobanvec![
&test.env,
Instruction {
action: ActionType::Withdraw,
strategy: Some(test.strategy_client_token0.address.clone()),
amount: Some(amount + 1),
swap_details_exact_in: OptionalSwapDetailsExactIn::None,
swap_details_exact_out: OptionalSwapDetailsExactOut::None,
},
];
let rebalance = test.defindex_contract.try_rebalance(&withdraw_instructions);
assert_eq!(rebalance, Err(Ok(ContractError::StrategyWithdrawError)));

let invest_instructions = sorobanvec!(
&test.env,
Instruction {
action: ActionType::Invest,
strategy: Some(test.strategy_client_token0.address.clone()),
amount: Some(amount + 1),
swap_details_exact_in: OptionalSwapDetailsExactIn::None,
swap_details_exact_out: OptionalSwapDetailsExactOut::None,
},
);
let rebalance = test.defindex_contract.try_rebalance(&invest_instructions);
if rebalance == Err(Err(InvokeError::Contract(10))) {
return;
} else {
panic!("Expected error not returned");
}
}

0 comments on commit 7bb8b29

Please sign in to comment.