Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Swap With Soroswap #319

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added apps/contracts/soroswap/soroswap_aggregator.wasm
Binary file not shown.
Binary file added apps/contracts/soroswap/soroswap_factory.wasm
Binary file not shown.
Binary file added apps/contracts/soroswap/soroswap_pair.wasm
Binary file not shown.
Binary file added apps/contracts/soroswap/soroswap_router.wasm
Binary file not shown.
72 changes: 51 additions & 21 deletions apps/contracts/vault/src/test.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
#![cfg(test)]
extern crate std;
use soroban_sdk::token::{
StellarAssetClient as SorobanTokenAdminClient, TokenClient as SorobanTokenClient,
use soroban_sdk::{
token::{
StellarAssetClient as SorobanTokenAdminClient, TokenClient as SorobanTokenClient
},
testutils::{
Address as _, AuthorizedFunction, AuthorizedInvocation, MockAuth, MockAuthInvoke},
vec as sorobanvec, Address, Env, String, Vec, Val, IntoVal,
};
use soroban_sdk::Val;
use soroban_sdk::{testutils::Address as _, vec as sorobanvec, Address, Env, String, Vec};
use std::vec;

// DeFindex Hodl Strategy Contract
use soroswap_setup::{create_soroswap_aggregator, create_soroswap_factory, create_soroswap_pool, create_soroswap_router, SoroswapFactoryClient, SoroswapRouterClient};

// DeFindex Hodl Strategy Contract
pub mod hodl_strategy {
soroban_sdk::contractimport!(
file = "../target/wasm32-unknown-unknown/release/hodl_strategy.optimized.wasm"
Expand Down Expand Up @@ -49,21 +54,6 @@ pub fn create_defindex_vault<'a>(
client
}

// DeFindex Factory Contract
// pub mod defindex_factory {
// soroban_sdk::contractimport!(file = "../target/wasm32-unknown-unknown/release/defindex_factory.optimized.wasm");
// pub type DeFindexFactoryClient<'a> = Client<'a>;
// }
// use defindex_factory::DeFindexFactoryClient;

// fn create_defindex_factory<'a>(
// e: & Env
// ) -> DeFindexFactoryClient<'a> {
// let address = &e.register_contract_wasm(None, defindex_factory::WASM);
// let client = DeFindexFactoryClient::new(e, address);
// client
// }

// Create Test Token
pub(crate) fn create_token_contract<'a>(e: &Env, admin: &Address) -> SorobanTokenClient<'a> {
SorobanTokenClient::new(
Expand Down Expand Up @@ -102,6 +92,31 @@ pub(crate) fn create_strategy_params_token1(test: &DeFindexVaultTest) -> Vec<Str
]
}

pub fn mock_mint(
env: &Env,
token_admin_client: &SorobanTokenAdminClient,
token_admin: &Address,
to: &Address,
amount: &i128,
) {

token_admin_client
.mock_auths(&[MockAuth {
address: &token_admin,
invoke: &MockAuthInvoke {
contract: &token_admin_client.address.clone(),
fn_name: "mint",
args: sorobanvec![
&env,
to.into_val(env),
amount.into_val(env)
],
sub_invokes: &[],
},
}])
.mint(&to, &amount);
}

pub struct DeFindexVaultTest<'a> {
env: Env,
defindex_factory: Address,
Expand Down Expand Up @@ -146,6 +161,20 @@ impl<'a> DeFindexVaultTest<'a> {
let strategy_client_token0 = create_hodl_strategy(&env, &token0.address);
let strategy_client_token1 = create_hodl_strategy(&env, &token1.address);

// Soroswap Setup
let soroswap_admin = Address::generate(&env);

mock_mint(&env, &token0_admin_client, &token0_admin, &soroswap_admin, &10000_0_000_000);
mock_mint(&env, &token1_admin_client, &token1_admin, &soroswap_admin, &10000_0_000_000);

let soroswap_factory = create_soroswap_factory(&env, &soroswap_admin);
let soroswap_router = create_soroswap_router(&env, &soroswap_factory.address);

env.budget().reset_unlimited();

create_soroswap_pool(&env, &soroswap_router, &soroswap_admin, &token0.address, &token1.address, &10000_0_000_000, &10000_0_000_000);
// let soroswap_pair = soroswap_factory.get_pair(&token0.address, &token1.address);

env.budget().reset_unlimited();

DeFindexVaultTest {
Expand All @@ -162,7 +191,7 @@ impl<'a> DeFindexVaultTest<'a> {
defindex_protocol_receiver,
manager,
strategy_client_token0,
strategy_client_token1,
strategy_client_token1,
}
}

Expand All @@ -176,3 +205,4 @@ impl<'a> DeFindexVaultTest<'a> {
}

mod vault;
mod soroswap_setup;
125 changes: 125 additions & 0 deletions apps/contracts/vault/src/test/soroswap_setup.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
use soroban_sdk::{
vec, Address, BytesN, Env, String,
testutils::{Address as _, AuthorizedFunction, AuthorizedInvocation, MockAuth, MockAuthInvoke},
IntoVal,
};

fn pair_contract_wasm(e: &Env) -> BytesN<32> {
soroban_sdk::contractimport!(
file = "../soroswap/soroswap_pair.wasm"
);
e.deployer().upload_contract_wasm(WASM)
}

// SoroswapFactory Contract
mod factory {
soroban_sdk::contractimport!(file = "../soroswap/soroswap_factory.wasm");
pub type SoroswapFactoryClient<'a> = Client<'a>;
}
pub use factory::SoroswapFactoryClient;

pub fn create_soroswap_factory<'a>(e: &Env, setter: &Address) -> SoroswapFactoryClient<'a> {
let pair_hash = pair_contract_wasm(&e);
let factory_address = &e.register(factory::WASM, ());
let factory = SoroswapFactoryClient::new(e, factory_address);
factory.initialize(&setter, &pair_hash);
factory
}

// SoroswapRouter Contract
mod router {
soroban_sdk::contractimport!(file = "../soroswap/soroswap_router.wasm");
pub type SoroswapRouterClient<'a> = Client<'a>;
}
pub use router::SoroswapRouterClient;

// SoroswapRouter Contract
pub fn create_soroswap_router<'a>(e: &Env, factory: &Address) -> SoroswapRouterClient<'a> {
let router_address = &e.register(router::WASM, ());
let router = SoroswapRouterClient::new(e, router_address);
router.initialize(factory);
router
}

pub fn create_soroswap_pool<'a>(e: &Env, router: &SoroswapRouterClient, to: &Address, token_a: &Address, token_b: &Address, amount_a: &i128, amount_b: &i128) -> (i128, i128, i128) {

let pair_address = router.router_pair_for(token_a, token_b);
router.mock_auths(&[
MockAuth {
address: &to,
invoke: &MockAuthInvoke {
contract: &router.address.clone(),
fn_name: "add_liquidity",
args: vec![
&e,
token_a.into_val(e),
token_b.into_val(e),
amount_a.into_val(e),
amount_b.into_val(e),
0i128.into_val(e),
0i128.into_val(e),
to.into_val(e),
(e.ledger().timestamp() + 3600).into_val(e),
],
sub_invokes: &[
MockAuthInvoke {
contract: &token_a.clone(),
fn_name: "transfer",
args: vec![
&e,
to.into_val(e),
pair_address.into_val(e),
amount_a.into_val(e)
],
sub_invokes: &[],
},
MockAuthInvoke {
contract: &token_b.clone(),
fn_name: "transfer",
args: vec![
&e,
to.into_val(e),
pair_address.into_val(e),
amount_b.into_val(e)
],
sub_invokes: &[],
},
],
},
},
])
.add_liquidity(
token_a,
token_b,
&amount_a,
&amount_b,
&0i128,
&0i128,
&to,
&(e.ledger().timestamp() + 3600)
)
}

// SoroswapRouter Contract
mod aggregator {
soroban_sdk::contractimport!(file = "../soroswap/soroswap_aggregator.wasm");
pub type SoroswapAggregatorClient<'a> = Client<'a>;
}
pub use aggregator::{SoroswapAggregatorClient, Adapter};

pub fn create_soroswap_aggregator<'a>(e: &Env, admin: &Address, router: &Address) -> SoroswapAggregatorClient<'a> {
let aggregator_address = &e.register(aggregator::WASM, ());
let aggregator = SoroswapAggregatorClient::new(e, aggregator_address);

let adapter_vec = vec![
e,
Adapter {
protocol_id: String::from_str(e, "soroswap"),
address: router.clone(),
paused: false,
}
];

aggregator.initialize(&admin, &adapter_vec);
aggregator
}
128 changes: 124 additions & 4 deletions apps/contracts/vault/src/test/vault/rebalance.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
use soroban_sdk::{vec as sorobanvec, InvokeError, String, Vec};
use soroban_sdk::{vec as sorobanvec, InvokeError, String, Vec, Map};

use crate::test::{
create_defindex_vault, create_strategy_params_token0, defindex_vault::{
ActionType, AssetInvestmentAllocation, AssetStrategySet, Instruction, OptionalSwapDetailsExactIn, OptionalSwapDetailsExactOut, StrategyAllocation
}, DeFindexVaultTest
create_defindex_vault, create_strategy_params_token0, create_strategy_params_token1,
defindex_vault::{
ActionType, AssetInvestmentAllocation, AssetStrategySet, Instruction, OptionalSwapDetailsExactIn,
OptionalSwapDetailsExactOut, StrategyAllocation, DexDistribution, SwapDetailsExactIn, CurrentAssetInvestmentAllocation},
DeFindexVaultTest
};
use crate::test::defindex_vault::ContractError;

Expand Down Expand Up @@ -421,5 +423,123 @@ fn insufficient_balance(){
}
}

#[test]
fn swap_exact_in() {
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<AssetStrategySet> = 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()
}
];

let defindex_contract = create_defindex_vault(
&test.env,
assets,
test.manager.clone(),
test.emergency_manager.clone(),
test.vault_fee_receiver.clone(),
2000u32,
test.defindex_protocol_receiver.clone(),
test.defindex_factory.clone(),
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);

test.token0_admin_client.mint(&users[0], &amount0);
test.token1_admin_client.mint(&users[0], &amount1);

let deposit_result=defindex_contract.deposit(
&sorobanvec![&test.env, amount0, amount1],
&sorobanvec![&test.env, amount0, amount1],
&users[0],
&false,
);

// 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_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_address: 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: amount0,
idle_amount: amount0,
invested_amount: 0i128,
strategy_allocations: 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_allocations: strategy_investments_expected_token_1,
}
);
let total_managed_funds = defindex_contract.fetch_total_managed_funds();
assert_eq!(total_managed_funds, total_managed_funds_expected);

todo!();

// let mut distribution_vec = Vec::new(&test.env);
// // add one with part 1 and other with part 0
// let mut path: Vec<Address> = Vec::new(&test.env);
// path.push_back(test.token_0.address.clone());
// path.push_back(test.token_1.address.clone());

// let distribution_0 = DexDistribution {
// protocol_id: String::from_str(&test.env, "soroswap"),
// path,
// parts: 1,
// };
// distribution_vec.push_back(distribution_0);

// test.token_0_admin_client.mint(&test.defindex_vault.address.clone(), &100000000);

// // Rebalance from here on
// let instructions = sorobanvec![
// &test.env,
// Instruction {
// action: ActionType::SwapExactIn,
// strategy: None,
// amount: None,
// swap_details_exact_in: OptionalSwapDetailsExactIn::Some(SwapDetailsExactIn {
// token_in: test.token_0.address.clone(),
// token_out: test.token_1.address.clone(),
// amount_in: 100,
// amount_out_min: 0,
// distribution: distribution_vec,
// deadline: test.env.ledger().timestamp() + 3600u64,
// router: test.soroswap_router.address.clone(),
// pair: test.soroswap_pair.clone(),
// }),
// swap_details_exact_out: OptionalSwapDetailsExactOut::None,
// }
// ];

// test.defindex_vault.rebalance(&instructions);

}

Loading