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

Blend Soroswap setup #298

Merged
merged 4 commits into from
Dec 11, 2024
Merged
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
4 changes: 2 additions & 2 deletions apps/contracts/strategies/blend/src/blend_pool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,8 @@ pub fn withdraw(e: &Env, from: &Address, amount: &i128, config: &Config) -> (i12
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, config.reserve_id], from)
// TODO: Hardcoded reserve_token_ids for now
pool_client.claim(from, &vec![&e, 0u32, 1u32, 2u32, 3u32], from)
}

pub fn perform_reinvest(e: &Env, config: &Config) -> Result<bool, StrategyError>{
Expand Down
2 changes: 1 addition & 1 deletion apps/contracts/strategies/blend/src/constants.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ 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;
pub const REWARD_THRESHOLD: i128 = 40_0000000;
24 changes: 23 additions & 1 deletion apps/contracts/strategies/blend/src/soroswap.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use defindex_strategy_core::StrategyError;
use soroban_sdk::{vec, Address, Env, IntoVal, Symbol, Val, Vec};
use soroban_sdk::{auth::{ContractContext, InvokerContractAuthEntry, SubContractInvocation}, vec, Address, Env, IntoVal, Symbol, Val, Vec};

use crate::storage::Config;

Expand All @@ -19,6 +19,28 @@ pub fn internal_swap_exact_tokens_for_tokens(
swap_args.push_back(to.to_val());
swap_args.push_back(deadline.into_val(e));

// Maybe instead of using the router directly, we should use the pair for swaps
let pair_address: Address = e.invoke_contract(
&config.router,
&Symbol::new(&e, "router_pair_for"),
vec![&e, path.get(0).unwrap().into_val(e), path.get(1).unwrap().into_val(e)]
);

e.authorize_as_current_contract(vec![
&e,
InvokerContractAuthEntry::Contract(SubContractInvocation {
context: ContractContext {
contract: path.get(0).unwrap().clone(),
fn_name: Symbol::new(&e, "transfer"),
args: (
e.current_contract_address(),
pair_address,
amount_in.clone()).into_val(e),
},
sub_invocations: vec![&e],
}),
]);

e.invoke_contract(
&config.router,
&Symbol::new(&e, "swap_exact_tokens_for_tokens"),
Expand Down
3 changes: 2 additions & 1 deletion apps/contracts/strategies/blend/src/test/blend/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
mod success;
mod success;
mod soroswap_setup;
60 changes: 60 additions & 0 deletions apps/contracts/strategies/blend/src/test/blend/soroswap_setup.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
use soroban_sdk::{
Env, BytesN, Address,
testutils::{Address as _}
};

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

// SoroswapFactory Contract
mod factory {
soroban_sdk::contractimport!(file = "../external_wasms/soroswap/soroswap_factory.optimized.wasm");
pub type SoroswapFactoryClient<'a> = Client<'a>;
}
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 = "../external_wasms/soroswap/soroswap_router.optimized.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, to: &Address, token_a: &Address, token_b: &Address, amount_a: &i128, amount_b: &i128) -> SoroswapRouterClient<'a> {
let soroswap_admin = Address::generate(&e);
let factory = create_soroswap_factory(&e, &soroswap_admin);
let router = create_soroswap_router(&e, &factory.address);

router.add_liquidity(
token_a,
token_b,
&amount_a,
&amount_b,
&0i128,
&0i128,
&to,
&(e.ledger().timestamp() + 3600)
);

router
}
37 changes: 26 additions & 11 deletions apps/contracts/strategies/blend/src/test/blend/success.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
use crate::blend_pool::{BlendPoolClient, Request};
use crate::constants::MIN_DUST;
use crate::storage::DAY_IN_LEDGERS;
use crate::test::blend::soroswap_setup::create_soroswap_pool;
use crate::test::{create_blend_pool, create_blend_strategy, BlendFixture, EnvTestUtils};
use crate::BlendStrategyClient;
use defindex_strategy_core::StrategyError;
Expand All @@ -25,18 +26,27 @@ fn success() {
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());

// Setting up soroswap pool
let pool_admin = Address::generate(&e);
let amount_a = 100000000_0_000_000;
let amount_b = 50000000_0_000_000;
blnd_client.mint(&pool_admin, &amount_a);
usdc_client.mint(&pool_admin, &amount_b);
let soroswap_router = create_soroswap_pool(&e, &pool_admin, &blnd.address(), &usdc.address(), &amount_a, &amount_b);
// End of setting up soroswap pool

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 = create_blend_strategy(&e, &usdc.address(), &pool, &0u32, &blnd.address(), &soroswap_router.address);
let strategy_client = BlendStrategyClient::new(&e, &strategy);

/*
Expand All @@ -51,7 +61,7 @@ fn success() {
usdc_client.mint(&user_2, &starting_balance);
usdc_client.mint(&user_3, &starting_balance);

let user_3_balance = usdc_client.balance(&user_2);
let user_3_balance = usdc_client.balance(&user_3);
assert_eq!(user_3_balance, starting_balance);


Expand Down Expand Up @@ -198,16 +208,12 @@ fn success() {
)
);

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!(strategy_client.balance(&user_2), 0);
assert_eq!(strategy_client.balance(&user_3), 0);

// -> verify withdraw from empty vault fails
let result = strategy_client.try_withdraw(&MIN_DUST, &user_3);
let result = strategy_client.try_withdraw(&MIN_DUST, &user_2);
assert_eq!(result, Err(Ok(StrategyError::InsufficientBalance)));

// TODO: Finish harvest testings, pending soroswap router setup with a blend token pair with the underlying asset
Expand All @@ -219,8 +225,17 @@ fn success() {
*/

// harvest
// strategy_client.harvest(&usdc, &user_2, &expected_fees);
let blnd_strategy_balance = blnd_client.balance(&strategy);
assert_eq!(blnd_strategy_balance, 0);

// -> verify harvest

strategy_client.harvest(&user_3);

let blnd_strategy_balance = blnd_client.balance(&strategy);
assert_eq!(blnd_strategy_balance, 0);

let usdc_strategy_balance = usdc_client.balance(&strategy);
assert_eq!(usdc_strategy_balance, 0);

let user_3_strategy_balance = strategy_client.balance(&user_3);
assert_eq!(user_3_strategy_balance, 1226627059);
}
Loading